indigo e2a4961ebe Upgrade to OpenUSD 25.11 (Python 3.12) and fix Arnold/Embree regressions
Build against OpenUSD 25.11 built from source with Python 3.12, OCIO 2.2.1,
OpenVDB, Ptex and Embree, replacing the 25.05/py311 mix.

Build system:
- CMAKE_PREFIX_PATH -> third_party/OpenUSD-v25.11; HDARNOLD_ROOT ->
  hdArnold-v25.11. hdEmbree is bundled in the USD build now, so
  HDEMBREE_USD_ROOT is no longer needed.
- FindOpenUSD: drop usd_ndr (ndr was merged into sdr in 25.11).
- hdArnold plugin renames: ndrArnold -> nodeRegistryArnold, plus the new
  usdImagingArnold plugin.
- Glob the version-suffixed OpenColorIO_*.dll instead of hardcoding 2_1.
- Drop the python311.dll workaround; USD and Cycles now share Python 3.12.
- Cycles: deploy OpenColorIO_2_5.dll (needed by its bundled OpenImageIO) and
  stop the debug-DLL filter from eating IlmThread.dll -- the regex `d[.]dll$`
  also matched legitimate Release DLLs.

Runtime fixes:
- cullStyle now defaults to Nothing, matching usdview (viewSettingsDataModel
  cullBackfaces=False). BackUnlessDoubleSided drops back faces on geometry
  that isn't authored doubleSided, which hdEmbree applies to occlusion rays
  too, so interiors shaded as single-sided.
- Set HDARNOLD_osl_includepath (and PXR_MTLX_STDLIB_SEARCH_PATHS) in main.cpp
  before the plugin DLL pre-load. hdArnold compiles MaterialX via generated
  OSL that begins with #include "mx_funcs.h"; without an include path Arnold
  fails with "fatal error: 'mx_funcs.h' file not found". It must be set before
  any plugin loads because TF_DEFINE_ENV_SETTING caches the value when
  hdArnold.dll registers its settings.
- Deploy the MaterialX standard library next to the executable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 10:02:00 +08:00
2026-06-13 08:45:16 +08:00
2026-07-11 11:08:59 +08:00
2026-06-03 09:00:11 +08:00
2026-06-03 09:00:11 +08:00

USD Layer Manager

A C++17 / Windows desktop application providing a Maya-style USD scene and look-dev editor using OpenUSD v25.11, ImGui 1.92.7 (docking branch), and OpenGL 3.3 (via GLAD). Users can open, edit, and save USD files, manage layered stage overrides, inspect and edit prim properties, author UsdShade material graphs with a live shader-ball preview, animate with a Bezier curve editor, and interact with 3D scenes through a multi-viewport Hydra renderer with OCIO color management.

Screenshot

Features

  • Layer Stack ManagementStageEditorPanel: create, reorder, mute/unmute sublayers, set the edit target, add existing files as sublayers, with full undo support
  • Scene Hierarchy — Browse prim tree with per-type SVG icons; create, delete, rename, reparent, and group prims; add/replace references
  • Property Editor — Maya Channel Box-style attribute editing with type-aware drag inputs, color pickers, and undoable transforms
  • Material Editor — Hypershade-style node-graph editor for UsdShade/MaterialX networks (MaterialEditorPanel): material browser, drag-to-connect node canvas, per-node/per-pin display modes, Sdr-driven node creation menu and enum dropdowns, colorSpace authoring on texture inputs, and a live shader-ball preview (MaterialPreviewRenderer) with its own renderer/HDRI/preview-shape controls. In-canvas node thumbnails (NodeThumbnailCache) show texture previews and per-node shader-ball renders, amortized across frames and re-rendered until progressive delegates (Arnold/Cycles/Embree) fully converge
  • Timeline & Curve Editor — Transport controls with loop/bounce and Auto-Key (TimelinePanel); a Maya-style F-curve editor (CurveEditorPanel) with Bezier round-trip to USD time samples; Playblast export to MP4 via MovieEncoder (libavcodec)
  • 3D Viewport — Hydra rendering via UsdImagingGLEngine into an offscreen FBO; switchable render delegates (Storm, Embree, Arnold, Cycles); OCIO-based color management (sRGB or full display/view/look pipeline) applied as a post-Hydra GL pass; grid overlay; selection bounding boxes; camera/light wireframes
  • Multi-Viewport — Single, horizontal split, vertical split, and quad layouts; per-tile camera, render delegate, and AOV; Space to maximize/restore
  • Camera Control — Free orbital camera (tumble/truck/dolly) or drive from USD camera prims; auto near/far clipping; frame selection; correct camera prim orientation for Y-up and Z-up stages
  • Transform Gizmo — Pure ImDrawList-based manipulator (translate/rotate/scale) in object or world space
  • Undo/Redo — Full command history (ICommand subclasses under src/core/commands/) covering prim creation/deletion/reparenting/grouping, attribute edits, transform changes, shader-node creation/connection, and layer operations; Ctrl+Z / Ctrl+Y hotkeys; Edit menu integration
  • Multi-select — Rectangular selection in viewport with cross-panel syncing
Material Editor (Arnold) Curve Editor Quad Viewport (4 delegates) MaterialX import
Material Editor Curve Editor Quad Viewport MaterialX

Dependencies

Dependency Version Notes
OpenUSD v25.11 Prebuilt; found via FindOpenUSD.cmake
Dear ImGui v1.92.7 Docking branch; Win32 + OpenGL3 backends
GLAD OpenGL 3.3 core loader
Python 3.12 Required by OpenUSD runtime (python312.dll)

Optional Render Delegates

Delegate Renderer Version Variable Notes
hdEmbree Embree 4.3.3 HDEMBREE_USD_ROOT (optional) Bundled directly in third_party/OpenUSD-v25.11 (built with --embree); set HDEMBREE_USD_ROOT only if using a separate USD build, and EMBREE_LOCATION if Embree DLLs aren't in its bin/
hdArnold Arnold 7.4.0 (MtoA 5.5.0) HDARNOLD_ROOT, ARNOLD_LOCATION arnold-usd (tag Arnold-7.4.5.1, for USD 25.11's ndrsdr API change) install dir + MtoA root for ai.dll
hdCycles Cycles 5.2.0 WITH_CYCLES=ON Built from source under third_party/cycles via ExternalProject; requires MSVC

All delegate paths are pre-configured in CMakePresets.json.

Build

Prerequisites

  • Visual Studio 17 2022 (MSVC v143) with C++17 support
  • CMake 3.20+
  • Python 3.12 installed at %LOCALAPPDATA%\Programs\Python\Python312\

Steps

cmake --preset default
cmake --build build --config Release
cmake --install build --config Release

The installed executable lives in install/bin/.

Presetsdefault (Release, WITH_CYCLES=ON, all render delegates), debug (Debug), release (RelWithDebInfo, installs), no-tests (Release). All presets currently build with BUILD_TESTS=OFF.

Building with Cycles

WITH_CYCLES=ON is set in the default preset. The first build compiles Blender Cycles from third_party/cycles via ExternalProject — expect a significantly longer initial build. Subsequent builds are incremental.

Cycles runtime dependencies (embree4.dll, openvdb.dll, OpenImageDenoise.dll, tbb12.dll, etc.) are automatically deployed to the output directory by a post-build step. CRT DLLs bundled inside the Cycles install are excluded to avoid version conflicts with the app's own MSVC runtime.

Tests

There is currently no working test runner: BUILD_TESTS is OFF in every preset. The two test executables (ViewportDisplayTest, RendererDiagnosticTest) have stale USD include paths and don't build — fix those before turning BUILD_TESTS on.

Architecture

src/
├── main.cpp                  — Entry point (plugin path init, app lifecycle)
├── core/                     — USD business logic (no UI dependency)
│   ├── UsdStageManager       — Stage open/create/save/close lifecycle
│   ├── LayerManager          — Layer stack introspection and mutation
│   ├── PropertyManager       — Property read/write via edit target with undo
│   ├── MaterialManager       — UsdShade graph introspection + Sdr node-type/enum discovery
│   ├── CommandHistory        — Undo/redo stack for ICommand instances
│   ├── UsdSceneRenderer      — Hydra rendering + picking + overlays + OCIO color correction
│   ├── ViewportCamera        — Free / USD-camera-driven orbital camera
│   └── commands/             — ICommand subclasses for all mutable operations
│       ├── TransformCommand          — Undoable translate/rotate/scale
│       ├── CreatePrimCommand         — Undoable prim creation (with camera orientation)
│       ├── DeletePrimCommand         — Undoable prim deletion (SdfCopySpec snapshot)
│       ├── RenamePrimCommand         — Undoable prim rename
│       ├── ReparentPrimCommand       — Undoable reparent via UsdNamespaceEditor
│       ├── GroupPrimsCommand         — Group selected prims under a new Xform
│       ├── AttributeSetCommand       — Type-agnostic undoable attribute writes
│       ├── AddReferenceCommand       — Undoable reference addition
│       ├── ReplaceReferenceCommand   — Undoable reference replacement
│       ├── CreateShaderNodeCommand   — Undoable UsdShadeShader creation (Material Editor)
│       ├── ConnectShaderAttrsCommand — Undoable shader input↔output connection
│       ├── DisconnectShaderAttrCommand — Undoable shader connection removal
│       └── LayerCommands             — Create, remove, reorder sublayers
├── ui/                       — ImGui panels and application shell
│   ├── Application            — App shell (owns managers/panels, docking, menus)
│   ├── ImGuiContext            — Win32+OpenGL+ImGui initialization and loop
│   ├── ViewportPanel           — Viewport container (layout, divider drag, maximize)
│   ├── ViewportTile            — Single viewport tile (camera, rendering, overlays, picking)
│   ├── SceneHierarchyPanel     — Prim tree browser with context menus
│   ├── PropertyPanel           — Attribute/transform editor (channel box-style)
│   ├── StageEditorPanel        — Layer stack editor (edit target, dirty state, drag-drop ordering)
│   ├── TimelinePanel           — Transport controls, loop/bounce, frame scrub, Playblast
│   ├── CurveEditorPanel        — Maya-style F-curve editor (Bezier ↔ USD time samples)
│   ├── MaterialEditorPanel     — Hypershade-style UsdShade node-graph editor
│   ├── MaterialPreviewRenderer — Shader-ball preview: independent Hydra instance + scratch stage
│   ├── NodeThumbnailCache      — Async texture decode + amortized shader-ball thumbnails for the node canvas
│   ├── TransformManipulator    — ImDrawList gizmo (move/rotate/scale)
│   ├── IconManager             — SVG icon rasterization via NanoSVG
│   └── NodeEditor/             — Vendored/patched imgui-node-editor
└── utils/                    — Cross-cutting utilities
    ├── Logger                — Thread-safe logging (file + console); also sinks USD TF_WARN/TF_ERROR
    ├── FileDialog            — Win32 file open/save dialogs
    ├── PathUtils             — Exe-relative path resolution
    ├── OcioConfigParser      — Enumerates displays/views/colorspaces/looks from the active OCIO config
    ├── MovieEncoder          — Streams RGBA frames to H.264/MP4 via libavcodec (Playblast)
    └── GLExt                 — GLAD extension initialization

Key Design Patterns

  • Command Pattern — All mutable USD operations go through ICommandCommandHistory for undo/redo
  • Panel-Manager Separation — UI panels hold pointers to core managers but contain no USD layer/prim logic
  • Callback Wiring — Cross-panel communication via std::function callbacks (e.g. viewport pick → hierarchy select → property panel update)
  • Render-Delegate PlugabilityUsdSceneRenderer can switch Hydra render plugins at runtime
  • Own Color Correction Pass — Hydra's HdxColorCorrectionTask is bypassed; a file-local ViewportColorCorrector (inside UsdSceneRenderer.cpp) applies sRGB/OCIO as a fullscreen GL pass after Hydra renders linear (see docs/adr/0001-viewport-color-correction.md)
  • Gizmo as 2D OverlayTransformManipulator uses pure ImDrawList calls (no GL resources), same approach as ImGuizmo

Project Configuration

Config Purpose
cmake/modules/FindOpenUSD.cmake OpenUSD SDK discovery
cmake/modules/FindImgui.cmake ImGui source integration
cmake/modules/FindGlad.cmake GLAD loader setup
CMakePresets.json Build presets (VS 17 2022, x64)
docs/adr/ Architecture decision records
AGENTS.md AI agent build/architecture guide
.kilo/ Kilo AI configuration (commands, agents, skills)
openspec/changes/ Feature proposals and implementation tracking

Development Workflow

This project uses OpenSpec for feature development:

  1. Propose — Create a new change under openspec/changes/<name>/ with proposal.md, design.md, specs/, and tasks.md
  2. Implement — Work through checkbox-tracked tasks in tasks.md
  3. Archive — Move completed changes to openspec/archive/ when done

Use Kilo's openspec-* skills to streamline this workflow.

Runtime Requirements

  • Python 3.12 — OpenUSD requires python312.dll at runtime. CMake copies it to the output directory via POST_BUILD commands.
  • USD Plugin Path — The app scans <exe_dir>/usd/ for plugInfo.json and registers plugins via pxr::PlugRegistry.
  • Render delegate DLLs — hdEmbree, hdArnold, and hdCycles each bring their own runtime dependencies (Embree, Arnold SDK, Cycles libs). CMake POST_BUILD steps deploy all required DLLs next to the executable automatically.

Contributing

Before writing any OpenUSD API call, verify the API exists in the actual SDK:

findstr /r /s "FunctionName" third_party\OpenUSD-v25.11\include\

Always build and install before manually verifying a change:

cmake --build build --config Release
cmake --install build --config Release

License

See LICENSE file for details.

S
Description
USD Layer Manager for USD Scene Editing
Readme 12 MiB
Languages
C++ 96.6%
CMake 3.4%