Init Repo
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-08
|
||||
@@ -0,0 +1,71 @@
|
||||
## Context
|
||||
|
||||
The application is a USD Layer Manager built with ImGui (docking enabled) and OpenGL on Windows (WGL). The existing OpenGL context is initialized with `#version 130` (GLSL) and a legacy WGL pixel format (32-bit color, 24-bit depth, 8-bit stencil). The current "Viewport" panel in `Application::RenderUI()` is a placeholder displaying static text.
|
||||
|
||||
The OpenUSD v25.08 SDK is available with UsdGeom and UsdShade APIs for scene traversal. The CMake build system uses `GLOB_RECURSE` for source collection, so new `.cpp`/`.h` files under `src/` are automatically compiled.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Render USD mesh geometry in the existing Viewport ImGui panel using OpenGL
|
||||
- Provide interactive orbit/pan/zoom camera control via mouse input captured from the viewport region
|
||||
- Render a ground grid and axis gizmo for spatial orientation
|
||||
- Use FBO-based rendering so the 3D output composites cleanly with the ImGui docking layout
|
||||
- Support basic materials (diffuse color from UsdShade or primvar color) for visual differentiation
|
||||
|
||||
**Non-Goals:**
|
||||
- Hydra / HdRenderer integration (deferred — requires significant additional infrastructure)
|
||||
- Advanced shading (PBR, transparency, shadows, ambient occlusion)
|
||||
- Selection highlighting or picking (future change)
|
||||
- Animation playback
|
||||
- Multi-viewport or offscreen rendering to file
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. FBO-to-ImGui-Image rendering pipeline
|
||||
|
||||
**Decision**: Render the USD scene to an OpenGL Framebuffer Object, then display the attached color texture via `ImGui::Image()`.
|
||||
|
||||
**Rationale**: The ImGui docking system controls window layouts. Direct `glViewport` calls over the entire framebuffer would conflict with ImGui's rendering. FBO rendering produces a texture that ImGui can composite at the correct position and size. This is the standard pattern for 3D viewports in ImGui applications.
|
||||
|
||||
**Alternative considered**: Render directly to the default framebuffer with `glViewport` positioned over the viewport panel area. Rejected because it requires manual z-ordering with ImGui draw calls and breaks when docked windows overlap.
|
||||
|
||||
### 2. Direct UsdGeom traversal instead of Hydra
|
||||
|
||||
**Decision**: Traverse the UsdStage prim tree, extract `UsdGeomMesh` points/faceVertexCounts/faceVertexIndices/normals, and upload to OpenGL VBOs/VAOs for drawing.
|
||||
|
||||
**Rationale**: Hydra requires creating an `HdEngine`, `HdRenderDelegate`, and `HdRenderPass` infrastructure. For an initial viewport that draws meshes with basic color, direct traversal is simpler, has fewer dependencies, and gives us full control over the draw loop. Hydra can be integrated later as a modular swap.
|
||||
|
||||
**Alternative considered**: Use `UsdImagingGL` for immediate rendering. Rejected because UsdImagingGL is deprecated in favor of Hydra in recent USD versions and pulls in heavy imaging dependencies.
|
||||
|
||||
### 3. Camera model: Orbit camera with arcball control
|
||||
|
||||
**Decision**: Implement a turntable-style orbit camera. Left-drag orbits around a focal point, middle-drag pans, scroll-wheel zooms.
|
||||
|
||||
**Rationale**: Turntable cameras are the standard for DCC applications (Maya, Blender's default). Users familiar with 3D tools expect this interaction model. The camera stores: eye position, focal point, up vector, and computes a view matrix.
|
||||
|
||||
**Alternative considered**: Arcball camera (trackball rotation). More flexible but less predictable for typical CAD/DCC workflows. Can be added as an option later.
|
||||
|
||||
### 4. OpenGL GLSL #version 130 compatibility
|
||||
|
||||
**Decision**: Use GLSL 130 shaders with the existing OpenGL context. Use `gl_Vertex`/`gl_ModelViewProjectionMatrix`-style built-ins where needed, or explicit `in`/`out` with `#version 130` compatible syntax.
|
||||
|
||||
**Rationale**: The ImGui backend is initialized with `#version 130`. Creating a modern core-profile context would require changing the WGL initialization, potentially breaking ImGui rendering. Staying on the compatibility profile is lowest risk.
|
||||
|
||||
**Alternative considered**: Upgrade to OpenGL 3.3+ core profile. Rejected because it requires WGL context creation changes and may break existing ImGui OpenGL3 backend behavior.
|
||||
|
||||
### 5. Class decomposition
|
||||
|
||||
**Decision**: Create the following classes:
|
||||
- `ViewportPanel` (src/ui/) — owns the FBO, renderer, and camera; handles ImGui window and mouse input routing
|
||||
- `UsdSceneRenderer` (src/core/) — traverses USD stage, extracts geometry, manages OpenGL buffers, and issues draw calls
|
||||
- `ViewportCamera` (src/core/) — stores camera parameters, computes view/projection matrices, handles orbit/pan/zoom
|
||||
|
||||
**Rationale**: Separates concerns — rendering logic is independent of UI, camera logic is independent of both. Each class can be tested and developed in isolation.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[Legacy OpenGL limitations]** → Stuck with compatibility profile until WGL context is upgraded. Mitigation: GLSL 130 is sufficient for basic mesh rendering; upgrade path is documented.
|
||||
- **[Large scene performance]** → Direct traversal loads all geometry into VBOs upfront. Mitigation: Add frustum culling and LOD in a future iteration; for now, limit to scenes that fit in GPU memory.
|
||||
- **[No Hydra = no procedural rendering]** → Complex procedurals (point instancers, curves) won't render correctly. Mitigation: Document supported prim types; add Hydra path later.
|
||||
- **[FBO resize on dock change]** → Viewport panel size changes when docked/undocked. Mitigation: `ViewportPanel` queries `ImGui::GetContentRegionAvail()` each frame and resizes the FBO when dimensions change.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
The application currently renders a placeholder "3D viewport will be displayed here" text instead of showing actual USD scene geometry. Users cannot visually inspect their USD stages, making the tool incomplete for scene authoring workflows. A functional viewport is essential for any USD editing application — without it, users must switch to an external viewer (e.g., usdview) to see their changes.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add an OpenGL-based 3D viewport that renders USD stage geometry within the existing dockable "Viewport" panel
|
||||
- Implement a camera system (orbit, pan, zoom) for navigating the 3D scene
|
||||
- Add Hydra or direct UsdGeom-based rendering to traverse the stage and draw meshes, transforms, and materials
|
||||
- Provide viewport controls (grid display, axis indicator, background color) via a toolbar or context menu
|
||||
- Render a ground grid and axis gizmo for spatial orientation
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `viewport-renderer`: OpenGL rendering pipeline that traverses USD prims and draws geometry, materials, and transforms into an FBO-backed ImGui image
|
||||
- `viewport-camera`: Interactive camera controller supporting orbit, pan, and zoom with mouse input mapped through the ImGui viewport window
|
||||
- `viewport-overlay`: Grid, axis gizmo, and viewport settings overlay rendered on top of the 3D scene
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
## Impact
|
||||
|
||||
- **src/ui/Application.h/cpp**: Replace placeholder viewport section with a ViewportPanel that owns the renderer and camera
|
||||
- **New files**: ViewportPanel, UsdSceneRenderer, ViewportCamera classes
|
||||
- **Dependencies**: OpenGL 3.3+ (already available via WGL context), OpenUSD UsdGeom/UsdShade APIs
|
||||
- **Build system**: CMakeLists.txt must compile new source files and link OpenGL
|
||||
- **Rendering path**: Initially UsdGeom traversal with OpenGL draw calls; Hydra integration deferred to a future change
|
||||
@@ -0,0 +1,53 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Camera supports orbit, pan, and zoom interaction
|
||||
|
||||
The system SHALL provide a turntable-style orbit camera controlled by mouse input within the Viewport panel. Left-drag orbits around a focal point, middle-drag or shift+left-drag pans, and scroll-wheel zooms.
|
||||
|
||||
#### Scenario: Orbit the camera
|
||||
- **WHEN** the user holds the left mouse button and drags within the Viewport panel
|
||||
- **THEN** the camera orbits around the focal point
|
||||
- **AND** the view updates in real-time
|
||||
|
||||
#### Scenario: Pan the camera
|
||||
- **WHEN** the user holds the middle mouse button (or shift+left button) and drags within the Viewport panel
|
||||
- **THEN** the camera pans horizontally and vertically relative to the view plane
|
||||
- **AND** the focal point moves with the camera
|
||||
|
||||
#### Scenario: Zoom the camera
|
||||
- **WHEN** the user scrolls the mouse wheel within the Viewport panel
|
||||
- **THEN** the camera moves closer to or farther from the focal point
|
||||
- **AND** the zoom is proportional to the current distance from the focal point
|
||||
|
||||
### Requirement: Camera computes view and projection matrices
|
||||
|
||||
The system SHALL compute a view matrix from the camera's eye position, focal point, and up vector, and a perspective projection matrix from the field of view, aspect ratio, and near/far clip planes.
|
||||
|
||||
#### Scenario: View matrix from camera parameters
|
||||
- **WHEN** the camera parameters (eye, focal point, up) are set or updated
|
||||
- **THEN** the system computes a `lookAt` view matrix
|
||||
|
||||
#### Scenario: Projection matrix matches viewport aspect ratio
|
||||
- **WHEN** the FBO dimensions change
|
||||
- **THEN** the projection matrix is recomputed with the updated aspect ratio
|
||||
|
||||
### Requirement: Mouse input is captured only when the viewport is hovered
|
||||
|
||||
The system SHALL capture mouse input for camera control only when the ImGui Viewport window is hovered. Mouse events outside the viewport SHALL NOT affect the camera.
|
||||
|
||||
#### Scenario: Mouse input captured in viewport
|
||||
- **WHEN** the mouse cursor is over the Viewport panel and the user interacts
|
||||
- **THEN** the camera responds to the input
|
||||
|
||||
#### Scenario: Mouse input ignored outside viewport
|
||||
- **WHEN** the mouse cursor is outside the Viewport panel
|
||||
- **THEN** camera input is not processed
|
||||
|
||||
### Requirement: Camera frames the scene automatically
|
||||
|
||||
The system SHALL compute a default camera position that frames the bounding box of the scene when a stage is first loaded.
|
||||
|
||||
#### Scenario: Camera frames scene on stage load
|
||||
- **WHEN** a new USD stage is opened
|
||||
- **THEN** the camera position and focal point are set so the entire scene bounding box is visible
|
||||
- **AND** the camera distance is adjusted based on the scene size
|
||||
@@ -0,0 +1,49 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Ground grid is rendered in the viewport
|
||||
|
||||
The system SHALL render a ground plane grid at the Y=0 plane (XZ plane) to provide spatial reference.
|
||||
|
||||
#### Scenario: Grid visible by default
|
||||
- **WHEN** the viewport is displaying a scene
|
||||
- **THEN** a grid is drawn on the Y=0 plane with lines at regular intervals
|
||||
|
||||
#### Scenario: Grid can be toggled off
|
||||
- **WHEN** the user toggles the grid display off via the viewport context menu
|
||||
- **THEN** the grid is no longer rendered
|
||||
|
||||
### Requirement: Axis gizmo is rendered in the viewport corner
|
||||
|
||||
The system SHALL render a 3D axis indicator (RGB for XYZ) in the lower-left corner of the viewport to show scene orientation.
|
||||
|
||||
#### Scenario: Axis gizmo visible
|
||||
- **WHEN** the viewport is displaying a scene
|
||||
- **THEN** an axis gizmo is drawn in the lower-left corner with X=red, Y=green, Z=blue lines and labels
|
||||
|
||||
#### Scenario: Axis gizmo reflects camera orientation
|
||||
- **WHEN** the camera is rotated
|
||||
- **THEN** the axis gizmo orientation updates to reflect the current view direction
|
||||
|
||||
### Requirement: Viewport background color is configurable
|
||||
|
||||
The system SHALL render the viewport background with a configurable color, defaulting to a dark gray (0.15, 0.15, 0.15).
|
||||
|
||||
#### Scenario: Default background color
|
||||
- **WHEN** the viewport is rendered
|
||||
- **THEN** the background is cleared to dark gray (0.15, 0.15, 0.15)
|
||||
|
||||
#### Scenario: Background color changed via context menu
|
||||
- **WHEN** the user selects a different background color from the viewport settings
|
||||
- **THEN** the viewport background is updated to the selected color
|
||||
|
||||
### Requirement: Viewport context menu provides display options
|
||||
|
||||
The system SHALL provide a right-click context menu in the viewport with toggles for grid display and background color options.
|
||||
|
||||
#### Scenario: Right-click opens context menu
|
||||
- **WHEN** the user right-clicks within the viewport area
|
||||
- **THEN** a context menu appears with options: "Show Grid" (toggle), and "Background" submenu with color presets
|
||||
|
||||
#### Scenario: Toggle grid from context menu
|
||||
- **WHEN** the user clicks "Show Grid" in the context menu
|
||||
- **THEN** the grid display is toggled on or off
|
||||
@@ -0,0 +1,77 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Viewport renders USD stage geometry into an FBO-backed ImGui panel
|
||||
|
||||
The system SHALL render USD stage geometry into an OpenGL Framebuffer Object (FBO) and display the attached color texture via `ImGui::Image()` within the "Viewport" dockable panel.
|
||||
|
||||
#### Scenario: Viewport displays scene geometry when a stage is loaded
|
||||
- **WHEN** a USD stage is opened and the Viewport panel is visible
|
||||
- **THEN** the system traverses the stage's prim tree, extracts `UsdGeomMesh` data, and renders mesh geometry into the FBO
|
||||
- **AND** the FBO color texture is displayed as an ImGui image in the Viewport panel
|
||||
|
||||
#### Scenario: Viewport shows empty background when no stage is loaded
|
||||
- **WHEN** no USD stage is open
|
||||
- **THEN** the Viewport panel displays a dark background with no geometry
|
||||
|
||||
### Requirement: FBO resizes to match viewport panel dimensions
|
||||
|
||||
The system SHALL resize the FBO color and depth attachments whenever the Viewport panel's content region dimensions change.
|
||||
|
||||
#### Scenario: FBO resized on dock layout change
|
||||
- **WHEN** the user docks, undocks, or resizes the Viewport panel
|
||||
- **THEN** the FBO is recreated with the new width and height from `ImGui::GetContentRegionAvail()`
|
||||
- **AND** the previous FBO textures are deleted
|
||||
|
||||
#### Scenario: No unnecessary FBO reallocation
|
||||
- **WHEN** the Viewport panel dimensions remain unchanged between frames
|
||||
- **THEN** the FBO is not recreated
|
||||
|
||||
### Requirement: USD mesh geometry is extracted and uploaded to GPU buffers
|
||||
|
||||
The system SHALL traverse the UsdStage, extract `UsdGeomMesh` points, face vertex counts, face vertex indices, and normals, and upload them to OpenGL VBOs/VAOs.
|
||||
|
||||
#### Scenario: Mesh data loaded from UsdGeomMesh prims
|
||||
- **WHEN** the stage is loaded or refreshed
|
||||
- **THEN** for each `UsdGeomMesh` prim, the system reads `points`, `faceVertexCounts`, `faceVertexIndices`, and `normals` attributes
|
||||
- **AND** uploads the data to OpenGL vertex buffer objects
|
||||
|
||||
#### Scenario: Missing normals handled gracefully
|
||||
- **WHEN** a `UsdGeomMesh` prim has no authored normals
|
||||
- **THEN** the system computes flat face normals from the triangle winding
|
||||
- **AND** renders the mesh with the computed normals
|
||||
|
||||
### Requirement: Meshes are rendered with diffuse color from UsdShade or primvar
|
||||
|
||||
The system SHALL apply a diffuse color to each mesh obtained from `UsdShadeMaterial` binding or a `displayColor` primvar, falling back to a default color.
|
||||
|
||||
#### Scenario: Mesh with UsdShade material
|
||||
- **WHEN** a mesh prim has a bound `UsdShadeMaterial` with a diffuse color output
|
||||
- **THEN** the mesh is rendered with that diffuse color
|
||||
|
||||
#### Scenario: Mesh with displayColor primvar
|
||||
- **WHEN** a mesh prim has a `primvars:displayColor` attribute and no bound material
|
||||
- **THEN** the mesh is rendered with the displayColor value
|
||||
|
||||
#### Scenario: Mesh with no color information
|
||||
- **WHEN** a mesh prim has neither a bound material nor a displayColor primvar
|
||||
- **THEN** the mesh is rendered with a default gray color (0.7, 0.7, 0.7)
|
||||
|
||||
### Requirement: OpenGL shaders are GLSL #version 130 compatible
|
||||
|
||||
All viewport shaders SHALL be written in GLSL #version 130 and use the compatibility profile built-in variables (`gl_Vertex`, attribute bindings, etc.) to match the existing OpenGL context.
|
||||
|
||||
#### Scenario: Shaders compile on legacy OpenGL context
|
||||
- **WHEN** the application initializes the viewport renderer
|
||||
- **THEN** the vertex and fragment shaders compile successfully on the existing WGL OpenGL context initialized with `#version 130`
|
||||
|
||||
### Requirement: Scene rendering is refreshed when the stage changes
|
||||
|
||||
The system SHALL rebuild GPU geometry buffers when the USD stage is opened, closed, or when the stage content is modified.
|
||||
|
||||
#### Scenario: Stage opened triggers rebuild
|
||||
- **WHEN** a new USD stage is opened
|
||||
- **THEN** the renderer clears existing GPU buffers and re-traverses the new stage
|
||||
|
||||
#### Scenario: Stage closed clears geometry
|
||||
- **WHEN** the current stage is closed
|
||||
- **THEN** the renderer clears all GPU buffers and the viewport shows an empty scene
|
||||
@@ -0,0 +1,44 @@
|
||||
## 1. ViewportCamera
|
||||
|
||||
- [x] 1.1 Create `src/core/ViewportCamera.h` with class declaration: eye, focalPoint, up vector, fov, nearClip, farClip, aspectRatio; methods for orbit/pan/zoom, view matrix, projection matrix computation
|
||||
- [x] 1.2 Implement `src/core/ViewportCamera.cpp`: `LookAt` view matrix, perspective projection matrix, orbit (spherical coords around focal point), pan (translate eye+focal in view plane), zoom (adjust distance to focal point proportionally)
|
||||
- [x] 1.3 Add `FrameBoundingBox(bounding box)` method that positions the camera to view the entire scene
|
||||
|
||||
## 2. UsdSceneRenderer
|
||||
|
||||
- [x] 2.1 Create `src/core/UsdSceneRenderer.h` with class declaration: stage ref, OpenGL buffer handles, methods for `SetStage()`, `Rebuild()`, `Render()`, `Cleanup()`
|
||||
- [x] 2.2 Implement `src/core/UsdSceneRenderer.cpp` — stage traversal: iterate prims, filter `UsdGeomMesh`, extract `points`, `faceVertexCounts`, `faceVertexIndices`, `normals`
|
||||
- [x] 2.3 Implement geometry upload: create VAO/VBO per mesh, handle triangulation from `faceVertexCounts`, compute flat normals when authored normals are missing
|
||||
- [x] 2.4 Implement material color extraction: read `UsdShadeMaterial` binding diffuse color, fall back to `primvars:displayColor`, fall back to default gray (0.7, 0.7, 0.7)
|
||||
- [x] 2.5 Implement GLSL #version 130 shaders: vertex shader (MVP transform + normal transform), fragment shader (directional light + ambient + diffuse color)
|
||||
- [x] 2.6 Implement `Render()` method: bind shader, set view/projection uniforms, iterate meshes and draw with their material colors
|
||||
- [x] 2.7 Implement `Cleanup()` and `Rebuild()`: delete old OpenGL buffers, re-traverse stage, re-upload geometry
|
||||
|
||||
## 3. ViewportPanel (FBO + ImGui Integration)
|
||||
|
||||
- [x] 3.1 Create `src/ui/ViewportPanel.h` with class declaration: FBO/color/depth texture handles, `ViewportCamera`, `UsdSceneRenderer`, dimensions; methods for `SetStage()`, `Render()`, `HandleInput()`
|
||||
- [x] 3.2 Implement FBO creation and resize logic: create color + depth attachments, detect dimension changes from `ImGui::GetContentRegionAvail()`, resize FBO only when dimensions change
|
||||
- [x] 3.3 Implement `Render()`: bind FBO, clear with background color, call `UsdSceneRenderer::Render()` with camera matrices, unbind FBO, display color texture via `ImGui::Image()`
|
||||
- [x] 3.4 Implement mouse input routing: detect viewport hover via `ImGui::IsWindowHovered()`, capture left-drag (orbit), middle-drag/shift+left-drag (pan), scroll (zoom), forward deltas to `ViewportCamera`
|
||||
|
||||
## 4. Viewport Overlay (Grid + Gizmo + Context Menu)
|
||||
|
||||
- [x] 4.1 Implement ground grid rendering: draw lines on Y=0 plane at regular intervals using GL_LINES in the scene renderer pass
|
||||
- [x] 4.2 Implement axis gizmo rendering: draw RGB (XYZ) lines in the lower-left viewport corner using an orthographic overlay pass independent of the scene camera
|
||||
- [x] 4.3 Implement background color configuration: store background color, use it for `glClear` in the FBO render pass
|
||||
- [x] 4.4 Implement viewport right-click context menu with "Show Grid" toggle and "Background" color preset submenu
|
||||
|
||||
## 5. Application Integration
|
||||
|
||||
- [x] 5.1 Add `ViewportPanel` member to `Application`, initialize in `Application::Initialize()`, wire to `UsdStageManager` via `SetStage()`
|
||||
- [x] 5.2 Replace the placeholder Viewport `ImGui::Begin/End` block in `Application::RenderUI()` with `ViewportPanel::Render()`
|
||||
- [x] 5.3 Call `ViewportCamera::FrameBoundingBox()` in `RefreshManagers()` when a new stage is loaded so the camera frames the scene
|
||||
- [x] 5.4 Verify all existing panels (Scene Hierarchy, Layer Panel, Property Panel) still render correctly alongside the new ViewportPanel
|
||||
|
||||
## 6. Build and Test
|
||||
|
||||
- [x] 6.1 Run `cmake --preset default` and `cmake --build` to verify compilation with new source files
|
||||
- [x] 6.2 Launch the application, open a USD file with mesh geometry, verify geometry renders in the Viewport panel
|
||||
- [x] 6.3 Test orbit, pan, zoom interactions in the viewport
|
||||
- [x] 6.4 Test grid toggle and background color from context menu
|
||||
- [x] 6.5 Test FBO resize by docking/undocking/resizing the Viewport panel
|
||||
Reference in New Issue
Block a user