## 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