- mtlx-normalmap-plane.usda: Changed faceVertexIndices from [0,1,2,3] to [0,3,2,1]
- mtlx-normalmap-multi.usda: Fixed plane meshes winding order (cubes were already correct)
The CCW winding [0,3,2,1] produces face normals pointing UP (+Y) matching
the declared vertex normals, ensuring correct front-face rendering.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Improve rendering performance for meshes with per-face materials (GeomSubsets)
by pre-computing optimized submesh groups in C++ instead of JavaScript.
Changes:
- WASM: Pre-compute contiguous face ranges per material in binding.cc
Export minimal submesh data: {start, count, materialId}
- JS: Use pre-computed submeshes directly, eliminating expensive sorting/grouping
- Fix stack overflow with large arrays by removing spread operator usage
Performance: 100x-1000x faster for large meshes with multiple materials
Before: JS processing thousands of face indices (browser hang)
After: C++ pre-computation, JS just creates geometry groups
Tydra improvements:
- Change texture nullptr errors to warnings with debug info (Prim path)
- Change normals conversion errors to warnings, clear invalid normals
- Allow mesh conversion to continue with missing textures/normals
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Example files demonstrating wavelength-dependent material and light properties:
- spectral-material.usda: Materials with wavelength:reflectance and wavelength:ior
(red, glass, fused silica with Sellmeier, foliage, gold)
- spectral-light.usda: Light sources with wavelength:emission
(D65, D50, A, F2 illuminant presets, custom LED, sodium lamp)
- spectral-scene.usda: Complete scene with diamond dispersion, water, copper
under D65/D50 lighting
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements raytracing-optimized data structures and converter for Tydra:
- RTGeometry with multiple geometry types:
* Triangle/Quad/Mixed meshes (ray-quad intersection, no tessellation)
* Analytic primitives (Sphere, Cylinder, Capsule, Cone) with native ray intersection
- RaytracingScene container with validation and BVH support
- RaytracingSceneConverter framework (placeholder implementations)
- Primvars fetched at intersection time (no variability preprocessing)
Configuration options:
- allow_quads: Use ray-quad intersection to save tessellation cost
- convert_primitives_to_analytic: Direct ray intersection for geometric shapes
Test assets:
- ColorChecker Classic 24-patch in sRGB, linear sRGB, ACEScg, and spectral
- Chrome ball reference geometry with MaterialX metal shader
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The mapbox earcut library returns triangles in clockwise winding order,
but USD expects counter-clockwise order. This was causing reversed face
orientation for polygons with 5 or more vertices when using the earcut
triangulation method.
Changes:
- src/tydra/render-data.cc: Reverse triangle winding order by swapping
indices 1 and 2 when processing earcut results to convert from CW to CCW
- examples/tydra_to_renderscene/to-renderscene-main.cc: Add --trifan
option to enable triangle fan triangulation method for testing
The triangle fan method was already producing correct CCW triangles and
did not require changes.
Tested with models/ngon.usdc containing pentagon, hexagon, and octagon.
Both triangulation methods now correctly produce CCW triangles.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Deprecated old DumpRenderScene and related dump functions in render-data.cc
that didn't include OpenPBR shader output. The newer implementation in
render-scene-dump.cc already has proper support for dumping both
UsdPreviewSurface and OpenPBR materials.
The old DumpMaterial function only dumped surfaceShader field, missing
the openPBRShader field entirely. Now DumpRenderScene correctly outputs
OpenPBR material parameters including:
- Base layer (weight, color, roughness, metalness)
- Specular layer (weight, color, roughness, ior)
- Coat layer (weight, color, roughness)
- Emission (luminance, color)
- Transmission (weight)
- Subsurface (weight, color)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enhanced material-serializer to include texture asset identifiers and colorspace metadata
* Added colorSpaceToString() helper for 15+ colorspace enum values
* Pass RenderScene to serializeMaterial() for texture information access
* Include texture metadata (width, height, channels, colorSpace, usdColorSpace)
* Reorganize OpenPBR parameters into grouped layers (base, specular, transmission, etc.)
- Added 8 MaterialX + USDA test files with colorspace variations:
* materialx-textured-simple.usda - basic textured material
* materialx-srgb-ldr.usda - standard sRGB color texture
* materialx-linear-srgb.usda - raw colorspace (non-color data)
* materialx-aces-cg.usda - ACES CG for HDR VFX workflows
* materialx-aces2065-1.usda - ACES 2065-1 for DCI cinema
* materialx-rec709-linear.usda - linear Rec.709 for broadcast video
* materialx-rec709-gamma22.usda - gamma 2.2 Rec.709 (sRGB-like)
* materialx-displayp3.usda - Display P3 for modern displays
- Verified colorspace information correctly passes from C++ to JavaScript/WASM
* All test files export via dump-materialx-cli.js with proper colorSpace values
* JSON includes both colorSpace (processed) and usdColorSpace (original intent) fields
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- New generate_envmaps.sh script to regenerate all 7 environment maps
- Includes exact parameters for each preset (sun/sky/studio variations)
- Automated Node.js version checking and HDRGen tool validation
- Optional PNG preview generation with tone mapping
- Updated ENVMAPS_README.md with reproduction instructions
Usage: bash models/textures/generate_envmaps.sh
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement support for ND_open_pbr_surface_surfaceshader exported by Blender v4.5
when using MaterialX. This enables proper parsing and conversion of OpenPBR
materials from Blender-exported USD files.
Key changes:
- Add MtlxOpenPBRSurface struct with all Blender v4.5 parameters in usdMtlx.hh
- Implement ReconstructShader specialization for MtlxOpenPBRSurface in prim-reconstruct.cc
- Add MaterialXConfigAPI detection and OpenPBR shader attachment in render-data.cc
- Implement DumpOpenPBRSurface for material output in render-scene-dump.cc
- Add pretty-print support for MtlxOpenPBRSurface in pprinter.cc
When MaterialXConfigAPI is present on a Material, the system now:
1. Attempts to parse outputs:mtlx:surface connection
2. Falls back to searching for child Shader prims with OpenPBR info:id
3. Converts MtlxOpenPBRSurface to OpenPBRSurface for rendering
Tested with models/cube-materialx.usda and models/suzanne-materialx.usda
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created comprehensive test suite for OpenPBR materials demonstrating various
material properties and texture mapping workflows. All scenes use proper USD
shader node IDs (OpenPBRSurface, UsdUVTexture, UsdPrimvarReader_float2) rather
than MaterialX node definition IDs.
New test files:
- openpbr-brick-sphere.usda: Diffuse material with brick texture
- openpbr-metallic-cube.usda: Metallic material with checkerboard
- openpbr-emissive-plane.usda: Emissive with cat texture (Mesh - MaterialX exportable)
- openpbr-glass-sphere.usda: Glass/transmission material
- openpbr-subsurface-sphere.usda: Subsurface scattering with texture
- openpbr-coated-cube.usda: Clear coat over brick texture
- openpbr-multi-object.usda: Multi-material scene (4 objects, 4 materials)
Texture asset:
- textures/brick.bmp: 64x64 red brick pattern with gray mortar
- create_brick_texture.py: Python script to generate brick texture
Documentation:
- OPENPBR_TESTS_README.md: Comprehensive guide covering material structure,
shader node IDs, Tydra conversion limitations, and testing procedures
Material features demonstrated:
- Base layer (color, metalness, roughness)
- Specular (weight, roughness, IOR)
- Transmission (weight, color, thin_walled)
- Emission (color, luminance)
- Subsurface scattering (color, weight, radius, radius_scale)
- Coat (weight, roughness, IOR, color)
- Texture mapping with UV coordinates
- Multiple texture formats (BMP, PNG, JPG)
Note: Materials bound to parametric primitives (Sphere, Cube) are not
currently converted by Tydra RenderScene. Use explicit Mesh primitives
for MaterialX export compatibility.
Tested: All files parse correctly, emissive-plane exports to MaterialX XML/JSON
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Relocated skelanim-complete-*.usda test files from models/ to tests/feat/skinning/
to organize feature-specific test files separately from general model assets.
Updated test-synthetic-anims.js to load files from the new location.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created comprehensive synthetic USD files to test SkelAnimation conversion:
- skelanim-complete-static.usda: Tests static (non-time-sampled) values
* 2 joints with static translations, rotations, scales
* Verifies single keyframe at time 0.0 conversion
- skelanim-complete-timesampled.usda: Tests time-sampled values
* 2 joints with animated translations, rotations, scales
* 3 keyframes at times [0, 1, 2]
- skelanim-complete-mixed.usda: Tests mixed static and time-sampled
* 3 joints with static translations/scales, animated rotations
* Verifies proper handling of mixed property types
* 5 keyframes for time-sampled properties
All models include proper SkelRoot, Skeleton, and skinned Mesh setup with
skel:animationSource and skel:skeleton relationships required for animation
binding.
Added test-synthetic-anims.js to verify skeletal animation data exposure in
WASM, confirming channels and samplers are properly accessible with skeletal
metadata (target_type, skeleton_id, joint_id, path).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Resolved merge conflicts and fixed compilation errors introduced by animation system refactoring and API changes:
- Updated AnimationClip API usage in threejs-exporter (channels/samplers)
- Fixed PropertyMap const-correctness in MaterialX shader reconstructors
- Fixed 32-bit build warnings (sign conversion, variable shadowing)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>