From 6adf022c13502b0cbf7e36bac6a785212481ce03 Mon Sep 17 00:00:00 2001 From: indigo Date: Tue, 30 Jun 2026 02:35:39 +0800 Subject: [PATCH] Add Camera Guide viewport toggle (stageView.py DrawCameraGuides port) Adds a per-viewport "Camera Guide" toggle (default off) that draws a full frustum wireframe box (near quad + far quad + 4 connecting edges) in oracle orange for every non-active UsdGeomCamera prim, matching usdview's displayCameraOracles behaviour. Uses GfFrustum::ComputeCorners() and the same 24-index line layout as DrawCameraGuides. Toggle exposed in the right-click context menu and gear popup; persists to INI as ShowCameraGuide. Co-Authored-By: Claude Sonnet 4.6 --- src/core/UsdSceneRenderer.cpp | 40 +++++++++++++++++++++++++++++++++++ src/core/UsdSceneRenderer.h | 4 ++++ src/ui/ViewportPanel.cpp | 2 ++ src/ui/ViewportTile.cpp | 10 +++++++++ src/ui/ViewportTile.h | 1 + 5 files changed, 57 insertions(+) diff --git a/src/core/UsdSceneRenderer.cpp b/src/core/UsdSceneRenderer.cpp index ab32b34..c61bd6d 100644 --- a/src/core/UsdSceneRenderer.cpp +++ b/src/core/UsdSceneRenderer.cpp @@ -166,6 +166,7 @@ void main() { outColor = color; } UsdSceneRenderer::UsdSceneRenderer() : m_showGrid(true) + , m_showCameraGuide(false) , m_aaEnabled(false) , m_backgroundColor(0.15f, 0.15f, 0.15f) , m_shadingMode(ShadingMode::SmoothShaded) @@ -1464,6 +1465,26 @@ void UsdSceneRenderer::BuildCameraWireframeLines(const pxr::GfCamera& gfCam, push(arrowBase, arrowTip); } +// Builds near quad + far quad + 4 connecting edges for the full GfFrustum. +// Mirrors stageView.py DrawCameraGuides: corners via GfFrustum::ComputeCorners(), +// line pairs via the same 24-index layout. Appends 24 XYZ float triples. +static void BuildCameraGuideLines(const pxr::GfCamera& gfCam, + std::vector& outVerts) +{ + const std::vector c = gfCam.GetFrustum().ComputeCorners(); + // 0=LBN 1=RBN 2=LTN 3=RTN 4=LBF 5=RBF 6=LTF 7=RTF + static const int kIdx[24] = { + 0,1, 1,3, 3,2, 2,0, // near quad + 4,5, 5,7, 7,6, 6,4, // far quad + 3,7, 0,4, 1,5, 2,6 // connecting edges + }; + for (int i : kIdx) { + outVerts.push_back(static_cast(c[i][0])); + outVerts.push_back(static_cast(c[i][1])); + outVerts.push_back(static_cast(c[i][2])); + } +} + // =========================================================================== // DrawCameraWireframes // =========================================================================== @@ -1518,6 +1539,8 @@ void UsdSceneRenderer::DrawCameraWireframes( pxr::GfMatrix4f vp = pxr::GfMatrix4f(viewProjMatrix); + std::vector guideVerts; // accumulates frustum oracle lines + for (const auto& camPath : m_cachedCameraPaths) { pxr::UsdPrim prim = stage->GetPrimAtPath(camPath); if (!prim) continue; @@ -1553,6 +1576,23 @@ void UsdSceneRenderer::DrawCameraWireframes( glBindVertexArray(m_camWireVAO); glDrawArrays(GL_LINES, 0, vertCount); glBindVertexArray(0); + + // Accumulate full-frustum oracle lines for non-active cameras (stageView.DrawCameraGuides) + if (m_showCameraGuide && !isActive) + BuildCameraGuideLines(gfCam, guideVerts); + } + + // Draw all camera guide frustum boxes in one call (oracle orange from stageView.py) + if (m_showCameraGuide && !guideVerts.empty()) { + glUniform4f(m_bboxUniformColor, 0.82745f, 0.39608f, 0.16471f, 1.0f); + glBindBuffer(GL_ARRAY_BUFFER, m_camWireVBO); + glBufferData(GL_ARRAY_BUFFER, + static_cast(guideVerts.size() * sizeof(float)), + guideVerts.data(), GL_DYNAMIC_DRAW); + glUniformMatrix4fv(m_bboxUniformMVP, 1, GL_TRUE, vp.GetArray()); + glBindVertexArray(m_camWireVAO); + glDrawArrays(GL_LINES, 0, static_cast(guideVerts.size() / 3)); + glBindVertexArray(0); } // Restore GL state diff --git a/src/core/UsdSceneRenderer.h b/src/core/UsdSceneRenderer.h index c46ea3e..e8ed8df 100644 --- a/src/core/UsdSceneRenderer.h +++ b/src/core/UsdSceneRenderer.h @@ -180,6 +180,9 @@ public: bool ShowGrid() const { return m_showGrid; } void SetShowGrid(bool show) { m_showGrid = show; } + bool ShowCameraGuide() const { return m_showCameraGuide; } + void SetShowCameraGuide(bool show) { m_showCameraGuide = show; } + bool GetAAEnabled() const { return m_aaEnabled; } void SetAAEnabled(bool enabled) { m_aaEnabled = enabled; } @@ -327,6 +330,7 @@ private: std::vector m_clipPlanes; bool m_showGrid; + bool m_showCameraGuide; bool m_aaEnabled; ///< GL_LINE_SMOOTH anti-aliasing for all line overlays pxr::GfVec3f m_backgroundColor; diff --git a/src/ui/ViewportPanel.cpp b/src/ui/ViewportPanel.cpp index 51ed475..fbce136 100644 --- a/src/ui/ViewportPanel.cpp +++ b/src/ui/ViewportPanel.cpp @@ -657,6 +657,7 @@ void ViewportPanel::SaveSettings(const std::string& path) const f << "\n[Tile" << i << "]\n"; f << "RenderDelegate=" << s.renderDelegate << "\n"; f << "ShowGrid=" << (s.showGrid ? 1 : 0) << "\n"; + f << "ShowCameraGuide=" << (s.showCameraGuide ? 1 : 0) << "\n"; f << "AAEnabled=" << (s.aaEnabled ? 1 : 0) << "\n"; f << "BgColorR=" << s.bgColorR << "\n"; f << "BgColorG=" << s.bgColorG << "\n"; @@ -723,6 +724,7 @@ void ViewportPanel::LoadSettings(const std::string& path) auto& ts = tileSettings[section]; if (key == "RenderDelegate") ts.renderDelegate = val; else if (key == "ShowGrid") ts.showGrid = (val == "1"); + else if (key == "ShowCameraGuide") ts.showCameraGuide = (val == "1"); else if (key == "AAEnabled") ts.aaEnabled = (val == "1"); else if (key == "BgColorR") ts.bgColorR = toFloat(val, ts.bgColorR); else if (key == "BgColorG") ts.bgColorG = toFloat(val, ts.bgColorG); diff --git a/src/ui/ViewportTile.cpp b/src/ui/ViewportTile.cpp index d49180e..fd53259 100644 --- a/src/ui/ViewportTile.cpp +++ b/src/ui/ViewportTile.cpp @@ -93,6 +93,7 @@ ViewportTileSettings ViewportTile::GetSettings() const ViewportTileSettings s; s.renderDelegate = m_renderer.GetCurrentRendererId().GetString(); s.showGrid = m_renderer.ShowGrid(); + s.showCameraGuide = m_renderer.ShowCameraGuide(); s.aaEnabled = m_renderer.GetAAEnabled(); const pxr::GfVec3f& bg = m_renderer.GetBackgroundColor(); s.bgColorR = bg[0]; s.bgColorG = bg[1]; s.bgColorB = bg[2]; @@ -108,6 +109,7 @@ void ViewportTile::ApplySettings(const ViewportTileSettings& s) if (!s.renderDelegate.empty()) m_renderer.SetRendererPlugin(pxr::TfToken(s.renderDelegate)); m_renderer.SetShowGrid(s.showGrid); + m_renderer.SetShowCameraGuide(s.showCameraGuide); m_renderer.SetAAEnabled(s.aaEnabled); m_renderer.SetBackgroundColor(pxr::GfVec3f(s.bgColorR, s.bgColorG, s.bgColorB)); m_renderer.SetBBoxMode(static_cast(s.bboxMode)); @@ -738,6 +740,10 @@ void ViewportTile::RenderContextMenu(int tileIndex) if (ImGui::MenuItem("Show Grid", nullptr, &showGrid)) m_renderer.SetShowGrid(showGrid); + bool showGuide = m_renderer.ShowCameraGuide(); + if (ImGui::MenuItem("Camera Guide", nullptr, &showGuide)) + m_renderer.SetShowCameraGuide(showGuide); + ImGui::Separator(); bool ambientOnly = m_renderer.GetAmbientLightOnly(); @@ -1024,6 +1030,10 @@ void ViewportTile::RenderCompactToolbar(int tileIndex) if (ImGui::MenuItem("Show Grid", nullptr, grid)) m_renderer.SetShowGrid(!grid); + bool guide = m_renderer.ShowCameraGuide(); + if (ImGui::MenuItem("Camera Guide", nullptr, guide)) + m_renderer.SetShowCameraGuide(!guide); + bool aaItem = m_renderer.GetAAEnabled(); if (ImGui::MenuItem("Anti-Aliasing", nullptr, aaItem)) m_renderer.SetAAEnabled(!aaItem); diff --git a/src/ui/ViewportTile.h b/src/ui/ViewportTile.h index 2a0aff1..55eb427 100644 --- a/src/ui/ViewportTile.h +++ b/src/ui/ViewportTile.h @@ -22,6 +22,7 @@ namespace UsdLayerManager { struct ViewportTileSettings { std::string renderDelegate; ///< empty = use AppPreferences default on first load bool showGrid = true; + bool showCameraGuide = false; bool aaEnabled = false; float bgColorR = 0.15f; float bgColorG = 0.15f;