Skip to content

[MAX-MAT-001] Strip buggy specular_rotation=0.25 from MaterialX export - #36

Open
doug-smith-miris wants to merge 1 commit into
Autodesk:devfrom
doug-smith-miris:miris/max-mat-001-strip-buggy-specular-rotation
Open

[MAX-MAT-001] Strip buggy specular_rotation=0.25 from MaterialX export#36
doug-smith-miris wants to merge 1 commit into
Autodesk:devfrom
doug-smith-miris:miris/max-mat-001-strip-buggy-specular-rotation

Conversation

@doug-smith-miris

Copy link
Copy Markdown

Summary

3ds Max's MtlxIOUtil.ExportMtlxString MaxScript bridge writes specular_rotation = 0.25 on every ND_standard_surface_surfaceshader, regardless of source PhysicalMaterial anisotropy. The MaterialX standard_surface nodedef default is 0.0, and specular_rotation is multiplied by specular_anisotropy in the BSDF — so when anisotropy is 0 (the universal default case), the value has zero observable effect, but it silently corrupts downstream pipelines that read MaterialX values directly or layer-override anisotropy later.

This PR adds a post-parse normalization step in MtlxShaderWriter::Write() that drops specular_rotation from standard_surface nodes when:

  • the value is statically 0.25 (the bug pattern), AND
  • specular_anisotropy is absent OR statically zero.

Connected anisotropy, any non-0.25 rotation, or a connected rotation input are all left untouched, so the fix is surgical and does not touch genuinely-authored anisotropic materials.

Diagnostic finding

  • Fingerprint: MAX-MAT-001-specular-rotation-default-0.25
  • Scope: 6/6 materials in samples/complex_export.usda affected
  • Severity: medium — semantic correctness; silent regression risk for downstream anisotropy edits

What's changed

  • src/translators/MtlxShaderWriter.cpp — adds _NormalizeStandardSurfaceSpecularRotation, called immediately after readFromXmlString.
  • src/Tests/Integration/mtlxShaderWriter_test.ms — adds test_export_physical_material_strips_buggy_specular_rotation, a regression test that creates a default PhysicalMaterial, exports it via MaterialX, and asserts specular_rotation is either absent or 0.0.
  • doc/translation-mapping.md — new tracking doc for 3ds Max -> MaterialX property translation status. MAX-MAT-001 is the first row.
  • doc/changelog.md — Unreleased entry.

Validation

3ds Max is Windows-only and this repo builds via Visual Studio (configure-vsdevcmd.bat). I cannot build or run the plugin on macOS, so I validated by mirroring the C++ logic in Python at the USD layer (normalize_specular_rotation.py in the arch-build dir):

  • Positive corpus — running the normalizer on samples/complex_export.usda strips exactly the 6 known-bogus specular_rotation = 0.25 lines and changes nothing else (USDA diff = 6 deletions, 0 additions, 0 modifications).
  • Visual no-op — Karma renders of the pre-fix and post-fix USDs are byte-identical (same SHA-256: eaf3832840…b8351). This is the expected outcome: specular_rotation * specular_anisotropy = 0 when anisotropy is 0, so the lighting integrator never sees the value.
  • Negative test — a synthetic fixture injects specular_anisotropy = 0.4 onto one shader. The normalizer correctly preserves specular_rotation = 0.25 on that shader while still stripping it from the other 5. Confirms the fix is surgical.

Build / run status

  • Build (Visual Studio, Windows): deferred — requires a Windows MSBuild environment with the 3ds Max SDK; not available on this Mac.
  • MaxScript regression test: deferred — requires 3ds Max (Windows-only).
  • Logic equivalence: verified via Python validator against the captured corpus.

Status

Opening for review. The C++ change is straightforward and has clear semantics, but a Windows build/test pass is needed before this is merge-ready. The visual evidence and Python-validated post-fix USD strongly suggest the change is correct.

3ds Max's MtlxIOUtil bridge hardcodes specular_rotation=0.25 on every
ND_standard_surface_surfaceshader, regardless of source PhysicalMaterial
anisotropy. The MaterialX nodedef default is 0.0; the value has no
visual effect when specular_anisotropy is zero (the BSDF multiplies
them), but it silently introduces a 90deg highlight rotation if a
downstream layer turns anisotropy on.

Add a post-parse normalization pass in MtlxShaderWriter::Write that
walks the parsed MaterialX document and drops specular_rotation from
standard_surface nodes when:
  * the value is statically 0.25 (the bug pattern), AND
  * specular_anisotropy is absent or statically 0.0.

Connected anisotropy, any non-0.25 rotation value, and connected
rotation are conservatively left untouched.

Validated against the diagnostic corpus (samples/complex_export.usda):
6/6 affected materials cleaned, Karma renders byte-identical pre/post
(SHA-256 match — semantic-only fix). Synthetic negative test
(BrushedSteel with specular_anisotropy=0.4) confirms the fix is
surgical and preserves intentional rotation.

Also adds doc/translation-mapping.md to track 3ds Max -> MaterialX
property mappings going forward, and a MaxScript regression test in
mtlxShaderWriter_test.ms.

Build/run validation deferred: 3ds Max is Windows-only and this repo
builds via Visual Studio (configure-vsdevcmd.bat). The Python
validator in the arch-build dir mirrors the C++ logic exactly at the
USD layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant