UsdLayerManager/openspec/changes/camera-wireframe-viewport/tasks.md

56 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 1. UsdSceneRenderer — DrawCameraWireframes
- [ ] 1.1 Add to `UsdSceneRenderer.h`: `void DrawCameraWireframes(pxr::UsdStageRefPtr stage, const pxr::SdfPathVector& selectedPaths, const pxr::SdfPath& activeCameraPath, const pxr::GfMatrix4d& viewProjMatrix, double viewportCameraDist)` and private helpers `BuildCameraWireframeLines(const pxr::GfCamera& gfCam, double scale, std::vector<float>& outVerts)` and `pxr::SdfPathVector m_cachedCameraPaths` + `bool m_cameraCacheDirty = true`
- [ ] 1.2 In `UsdSceneRenderer.cpp` implement `DrawCameraWireframes`:
- If `m_cameraCacheDirty`, traverse stage for `UsdGeomCamera` prims and cache paths; clear dirty flag
- For each cached camera path, resolve world transform + lens params via `UsdGeomCamera::GetCamera(UsdTimeCode::Default())``GfCamera`
- Compute `frustumScale = std::min(viewportCameraDist * 0.12, 50.0)`
- Call `BuildCameraWireframeLines` to produce a `std::vector<float>` of XYZ vertex pairs (GL_LINES)
- Determine colour: selected → `(1.0,0.75,0.1,1.0)`, active → `(0.2,0.9,1.0,1.0)`, inactive → `(0.55,0.55,0.55,0.85)`
- `BindDrawTarget()`, draw all segments using the existing axis GLSL program + a dynamic VBO (same pattern as `DrawBoundingBoxes`), `UnbindDrawTarget()`
- [ ] 1.3 Implement `BuildCameraWireframeLines`: given `GfCamera` and scale, produce:
- **Body box** — 12 edges of a small box (width × height × depth = scale×0.15 each) centred at camera origin in local space, transformed to world space by the camera's transform matrix
- **Frustum pyramid** — 4 lines from camera origin to each corner of a near-display quad at depth `max(nearClip, 0.01)`, scaled so the quad width/height match `horizontalAperture/focalLength * nearDepth` (perspective divide)
- **Up arrow** — one line from body-box top-centre upward by `scale * 0.2` along camera local Y
- [ ] 1.4 Set `m_cameraCacheDirty = true` inside `SetStage` (already exists) and inside the `SetForceRefresh(true)` path
## 2. UsdSceneRenderer — PickCameraAtPoint
- [ ] 2.1 Add to `UsdSceneRenderer.h`: `bool PickCameraAtPoint(pxr::UsdStageRefPtr stage, const ImVec2& mousePosAbsolute, const pxr::GfMatrix4d& viewProjMatrix, const ImVec2& imagePos, int viewW, int viewH, double viewportCameraDist, pxr::SdfPath* outCameraPath)`
- [ ] 2.2 In `UsdSceneRenderer.cpp` implement `PickCameraAtPoint`:
- Iterate `m_cachedCameraPaths` (build cache if needed)
- For each camera: build wireframe vertex list via `BuildCameraWireframeLines`
- Project each vertex pair to screen space using the same `WorldToScreen` math as `TransformManipulator`
- Compute `PointToSegmentDist` for each segment against `mousePosAbsolute`
- Track minimum distance and corresponding path; if `< kCameraPickRadius (10 px)` return true with that path
- If tie between multiple cameras, return the one with the smallest minimum distance
## 3. ViewportPanel — Integration
- [ ] 3.1 In `ViewportPanel.h`: add `pxr::SdfPath GetActiveCameraPath() const` (returns `m_camera.GetUsdCameraPath()` when in UsdCamera mode, else `SdfPath()`) — check `ViewportCamera` API for the getter name
- [ ] 3.2 In `ViewportPanel.cpp` `Render()`: after the `DrawBoundingBoxes` call, add:
```cpp
m_renderer.DrawCameraWireframes(m_stage, m_selectedSdfPaths,
m_camera.GetUsdCameraPath(), viewProj, m_camera.GetDist());
```
(Use the local `viewProj` already computed in that scope)
- [ ] 3.3 In `ViewportPanel.cpp` `HandleInput()`, single-click path (before the existing `PickObject` call): add camera pick:
```cpp
pxr::SdfPath camPath;
if (m_renderer.PickCameraAtPoint(m_stage, mouse, viewProj,
m_imageScreenPos, m_viewWidth, m_viewHeight,
m_camera.GetDist(), &camPath)) {
// fire selection callbacks with camPath
}
```
Only fall through to `PickObject` if `PickCameraAtPoint` returns false
## 4. Build and Verification
- [ ] 4.1 Run `cmake --preset default` (only needed if new `.cpp` files were added; all changes here are in existing files so this may be skipped) then `cmake --build build --config Release` — resolve any compilation errors
- [ ] 4.2 Install and launch `install/bin/App.exe`; create a `Camera` prim via Stage menu, verify its frustum wireframe appears in the viewport at the world origin
- [ ] 4.3 Verify clicking the camera wireframe selects the prim in the Scene Hierarchy panel
- [ ] 4.4 Verify the Move (W) gizmo appears on the selected camera and dragging repositions it; the wireframe moves to match
- [ ] 4.5 Switch the viewport to that camera via the camera toolbar; verify the wireframe turns cyan
- [ ] 4.6 With the camera active in the toolbar, click it in the viewport; verify it turns yellow-orange (selected overrides active colour)