Skip to content

Fix TetMesh._infer_frequency for length-1 attribute arrays - #3240

Merged
mzamoramora-nvidia merged 6 commits into
newton-physics:mainfrom
eric-heiden:fix-issue-3228
Jul 14, 2026
Merged

Fix TetMesh._infer_frequency for length-1 attribute arrays#3240
mzamoramora-nvidia merged 6 commits into
newton-physics:mainfrom
eric-heiden:fix-issue-3228

Conversation

@eric-heiden

@eric-heiden eric-heiden commented Jun 25, 2026

Copy link
Copy Markdown
Member

Description

Prevent unrelated USD attributes from aborting TetMesh and volume-deformable imports.

This PR:

  • infers an unambiguous length-1 TetMesh custom attribute as AttributeFrequency.ONCE, while preserving the ambiguity error when a geometry count is also one;
  • makes direct get_tetmesh() loading warn and omit custom arrays whose frequency cannot be inferred instead of rejecting the entire TetMesh;
  • makes add_usd() load only builder-registered TetMesh custom attributes, using the registered frequency as authoritative;
  • validates registered attribute lengths and skips malformed or unsupported values without dropping the soft body; and
  • flattens indexed USD primvars before importing their values.

This fixes PhysX-authored volume deformables containing irrelevant metadata such as deformablePose:default:omniphysics:purposes = ["bindPose"] or physxVolumeDeformableSim:simMeshHexCrc. These attributes are no longer normalized eagerly and cannot prevent the simulation TetMesh from loading.

Closes #3228

Checklist

  • New or existing tests cover these changes
  • The documentation is up to date with these changes
  • CHANGELOG.md has been updated (if user-facing change)

Test plan

uv run --extra dev -m newton.tests -k test_import_usd_deformable_volume
# Ran 23 tests: OK

uv run --extra dev -m newton.tests -k test_import_usd
# Ran 373 tests: OK (skipped=1)

uvx pre-commit run -a
# All hooks passed

Also verified manually with the reported OmniPhysics representation:

uniform token[] deformablePose:default:omniphysics:purposes = ["bindPose"]

Direct get_tetmesh() loading classifies this as ONCE on an unambiguous multi-tet mesh, while ModelBuilder.add_usd() imports the soft body without warning about or retaining the unregistered metadata.

Bug fix

Steps to reproduce:

  1. Author or cook a UsdGeom.TetMesh with more than one tetrahedron.
  2. Author the PhysX/OmniPhysics length-1 deformablePose:default:omniphysics:purposes token array on the simulation TetMesh.
  3. Import the stage using ModelBuilder.add_usd().
  4. Without this fix, custom-attribute frequency inference raises before add_usd() can discard the unregistered attribute.

Minimal reproduction:

import newton
from pxr import Sdf, Usd, UsdGeom

stage = Usd.Stage.CreateInMemory()
tet = UsdGeom.TetMesh.Define(stage, "/Soft")
tet.CreatePointsAttr(
    [
        (0.0, 0.0, 0.0),
        (1.0, 0.0, 0.0),
        (0.0, 1.0, 0.0),
        (0.0, 0.0, 1.0),
        (1.0, 1.0, 1.0),
    ]
)
tet.CreateTetVertexIndicesAttr([(0, 1, 2, 3), (1, 2, 3, 4)])
tet.GetPrim().CreateAttribute(
    "deformablePose:default:omniphysics:purposes",
    Sdf.ValueTypeNames.TokenArray,
).Set(["bindPose"])

builder = newton.ModelBuilder()
builder.add_usd(stage)

assert builder.particle_count == 5
assert builder.tet_count == 2

Summary by CodeRabbit

  • Bug Fixes
    • Improved TetMesh USD loading for custom attributes, including reliable handling of length-one arrays and indexed primvars.
    • Unambiguous custom attributes are now imported with the correct frequency.
    • Ambiguous or invalid attributes are skipped with warnings without preventing the soft body from loading.
    • ModelBuilder.add_usd() now imports only registered TetMesh custom attributes with their declared frequencies.

When a custom attribute array has length 1 and no geometry count
(vertex_count, tet_count, tri_count) also equals 1, infer
AttributeFrequency.ONCE instead of raising ValueError.  When a
geometry count does equal 1, raise an ambiguity error asking for
an explicit (array, frequency) tuple.

Fixes newton-physics#3228
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: aaf3771a-6826-4f7c-a332-a85fb1327314

📥 Commits

Reviewing files that changed from the base of the PR and between 92cbe9b and 6f74470.

📒 Files selected for processing (1)
  • newton/_src/geometry/types.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • newton/_src/geometry/types.py

📝 Walkthrough

Walkthrough

TetMesh USD loading now separates cached geometry from custom-attribute import, flattens indexed primvars, infers unambiguous length-1 attributes as ONCE, and skips invalid attributes without failing the TetMesh load. Builder imports use registered frequencies.

Changes

TetMesh USD custom attributes

Layer / File(s) Summary
Frequency inference and test coverage
newton/_src/geometry/types.py, newton/tests/test_import_usd.py
Length-1 arrays infer ONCE when unambiguous; tests cover ambiguity and explicit tetrahedron frequencies.
USD attribute extraction and validation
newton/_src/usd/utils.py
get_tetmesh() optionally skips custom attributes, flattens primvars, validates inferred frequencies, and omits invalid or reserved attributes with warnings.
Cached geometry and registered attributes
newton/_src/utils/import_usd.py, newton/_src/utils/import_usd_deformable_volume.py
Cached loads skip custom attributes; deformable-volume import reads registered attributes, validates declared frequencies and shapes, and avoids mutating cached meshes.
Release note
CHANGELOG.md
Documents the updated TetMesh USD loading and builder-import behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant USD
  participant get_tetmesh
  participant TetMesh
  participant ModelBuilder
  USD->>get_tetmesh: Load geometry and flattened custom values
  get_tetmesh->>TetMesh: Construct and validate TetMesh attributes
  get_tetmesh-->>ModelBuilder: Provide cached TetMesh geometry
  ModelBuilder->>USD: Read registered custom attributes
  ModelBuilder->>TetMesh: Attach frequency-validated attributes
Loading

Possibly related PRs

Suggested labels: usd

Suggested reviewers: vreutskyy, jcarius-nv

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing TetMesh frequency inference for length-1 arrays.
Linked Issues check ✅ Passed The PR addresses #3228 by inferring length-1 arrays as ONCE and skipping irrelevant unknown USD attributes instead of failing.
Out of Scope Changes check ✅ Passed The changes are all aligned with TetMesh USD import robustness, caching, and deformable-volume attribute handling.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@haixiangl-nv

Copy link
Copy Markdown

Is it possible to skip attributes with frequencies that are unable to be inferred at all, instead of erroring out?

If user has some custom attributes with weird size, but are irrelevant to the newton solver, usd parsing will error out even though the attributes are not relevant to Newton. It would be nice for Newton to print a warning regarding the bad attributes, instead of erroring out.

@huidongc

Copy link
Copy Markdown
Contributor

Is it possible to skip attributes with frequencies that are unable to be inferred at all, instead of erroring out?

If user has some custom attributes with weird size, but are irrelevant to the newton solver, usd parsing will error out even though the attributes are not relevant to Newton. It would be nice for Newton to print a warning regarding the bad attributes, instead of erroring out.

Agreed. I am hitting the same issue in IL.

parse_usd() later filters tetmesh.custom_attributes down to only attributes registered on the ModelBuilder. The offending attribute would be dropped anyway, but the failure occurs earlier during TetMesh construction.

Newton should not hard-fail on an unregistered custom attribute that will be discarded.

@huidongc

Copy link
Copy Markdown
Contributor

@eric-heiden Do you plan to rework and fix the issue? We hit a bug related to this - NVBUG#6445358.

Keep direct TetMesh construction strict while making USD loading tolerant of arbitrary authored arrays. Warn and omit only attributes whose frequency is ambiguous or unavailable so irrelevant PhysX data cannot discard the whole soft body.
Use ModelBuilder declarations as the authoritative source for USD
attribute names and frequencies during soft-body import. Ignore unrelated
vendor metadata without losing the TetMesh, and diagnose malformed or
unsupported registered arrays.

Flatten indexed primvars so direct TetMesh loading and add_usd preserve
the expanded value order.
@mzamoramora-nvidia

Copy link
Copy Markdown
Member

@eric-heiden @huidongc @mmichelis I have a few follow up commits regarding this PR on this branch: https://github.com/mzamoramora-nvidia/newton/tree/mzamoramora/pr-3240-merge-ready
Would that solve the issue for you?

@huidongc

Copy link
Copy Markdown
Contributor

@mzamoramora-nvidia yes, that will fix the error.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
newton/_src/geometry/types.py (1)

1438-1445: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add | None to the device type hint.

As per coding guidelines, use PEP 604 unions for optional arguments. Since the device parameter defaults to None, its type should explicitly be annotated as Devicelike | None.

  • newton/_src/geometry/types.py#L1438-L1445: change device: Devicelike = None to device: Devicelike | None = None in Mesh.finalize.
  • newton/_src/geometry/types.py#L2435-L2440: change device: Devicelike = None to device: Devicelike | None = None in Gaussian.finalize.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@newton/_src/geometry/types.py` around lines 1438 - 1445, Update the device
parameter annotation in Mesh.finalize and Gaussian.finalize in
newton/_src/geometry/types.py at lines 1438-1445 and 2435-2440, respectively,
from Devicelike to Devicelike | None while retaining the None default.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@newton/_src/geometry/types.py`:
- Around line 1438-1445: Update the device parameter annotation in Mesh.finalize
and Gaussian.finalize in newton/_src/geometry/types.py at lines 1438-1445 and
2435-2440, respectively, from Devicelike to Devicelike | None while retaining
the None default.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: a84461cb-2229-4a47-a365-de1d59c044f4

📥 Commits

Reviewing files that changed from the base of the PR and between 9c82fac and 92cbe9b.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • newton/_src/geometry/types.py
  • newton/_src/usd/utils.py
  • newton/_src/utils/import_usd.py
  • newton/_src/utils/import_usd_deformable_volume.py

Keep TetMesh.create_from_usd documentation identical to the public get_tetmesh helper. The API parity test requires both entry points to describe resolved primvar interpolation consistently.
@mzamoramora-nvidia
mzamoramora-nvidia added this pull request to the merge queue Jul 14, 2026
@mzamoramora-nvidia mzamoramora-nvidia added this to the 1.4 Release milestone Jul 14, 2026
Merged via the queue into newton-physics:main with commit db91242 Jul 14, 2026
30 checks passed
jcarius-nv pushed a commit that referenced this pull request Jul 14, 2026
Co-authored-by: Miguel Angel Zamora Mora <mzamoramora@nvidia.com>
(cherry picked from commit db91242)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[BUG] USD Parse for tetMesh can not handle unknown attribute frequency.

5 participants