Skip to main content

Authoring Assets

The SuperDex Physics engine provides some basic utilities to convert geometry data into simulation-ready model assets. This standalone workflow uses only APIs shipped in superdex-physics: load model data, validate it, optionally convert its length units and axis convention, optionally bake a grid-interpolated signed-distance field (SDF) for use in the Contact formulation, and save the result as a .mochi.h5 file.

Supported inputs are:

  • Wavefront OBJ (.obj)
  • STL (.stl)
  • Stanford PLY (.ply)
  • Object File Format (.off)
  • SuperDex Physics JSON (.mochi.json)
  • SuperDex Physics HDF5 (.mochi.h5)

The OBJ, STL, PLY, and OFF loaders mentioned above import only triangulated surface geometry. Parsing or generating mesh data for tetrahedral meshes or polylines from formats other than SuperDex JSON or HDF5 is outside the current scope of the physics engine. An application may use other functionality (e.g., a third-party mesh generator) to produce flattened nodes and connectivity arrays for a tetrahedral mesh or polyline, then construct MeshData from these directly (as described in Mesh Shapes) and assign it to ModelData.mesh. Set nodesPerElement / nodes_per_element to 2 for polylines, 3 for triangles, or 4 for tetrahedra. The Mass on Rod Spring and high-fidelity rod-based tendon examples provide practical polyline-model references. For higher-level asset preparation, you can also use SuperDex Studio's Model Editor before starting this workflow.

Input Requirements

The model APIs load and validate geometry; they do not provide general mesh preparation. Prepare input data with these requirements in mind:

  • Coordinates must reach simulation in the consuming application's length units and axis convention. Input data in another convention can be transformed with Convert Scale and Coordinate Space. For a known consumer, author assets in that consumer's expected length units and axis convention to minimize friction.
  • A meaningful SDF requires a suitable closed surface with consistent orientation and without severe degeneracies, self-intersections, or ambiguous topology.

Checked loading and model validation enforce the invariants known to the model API. Autocorrection applies only narrowly limited in-place fixes, such as normalizing applicable vectors and weights.

See Shapes for model and shape representations, and Collider Representations for how a baked SDF is used at runtime.

Load and Validate Model Data

Use checked loading for the normal path:

#include <mochi_physics/utils/mochi_model_utils.h>
#include <superdex_physics.h>

superdex::ModelData modelData = superdex::model_utils::LoadFromFile(
"models/prepared_part.obj", superdex::ErrorAssert{});

model_utils::LoadFromFile() / physics.model.load_from_file() parses the file, applies supported autocorrections, and validates the resulting ModelData. These examples fail fast for brevity: C++ uses ErrorAssert{}, while Python allows generated exceptions to propagate.

Unchecked loading is available via model_utils::LoadFromFileUnchecked() / physics.model.load_from_file_unchecked() for advanced use cases where data may be initially invalid. Equivalent byte-loading APIs are model_utils::LoadFromBytes() and model_utils::LoadFromBytesUnchecked() in the C++ model_utils namespace, and physics.model.load_from_bytes() and physics.model.load_from_bytes_unchecked() in Python.

Autocorrect and Validate Explicitly

For data created programmatically, loaded through an unchecked API, or otherwise not validated by checked loading, run C++ model_utils::AutoCorrect() and model_utils::Validate(), or Python physics.model.auto_correct() and physics.model.validate(), before baking an SDF or serializing:

superdex::model_utils::AutoCorrect(modelData, superdex::ErrorAssert{});
superdex::model_utils::Validate(modelData, superdex::ErrorAssert{});

Convert Scale and Coordinate Space

If loaded data does not already use the consuming application's convention, bake the conversion into the model before generating an SDF or saving the asset. Define the source and target CoordinateSpace values from the asset pipeline and consuming application, respectively. The C++ and Python references document the type's fields and named conventions.

superdex::model_utils::BakeCoordinateSpaceTransform(
modelData, sourceSpace, targetSpace, superdex::ErrorAssert{});

model_utils::BakeCoordinateSpaceTransform() / physics.model.bake_coordinate_space_transform() converts both axis convention and units, including winding order when handedness changes. Use model_utils::BakeTransform() / physics.model.bake_transform() instead when an arbitrary scale, rotation, or translation is required.

Bake a Grid SDF

model_utils::BakeSdf() / physics.model.bake_sdf() computes a grid SDF from triangle or tetrahedral mesh data and stores it in ModelData::sdf / model_data.sdf, replacing any SDF already there. The operation may be slow and memory intensive, and it does not condition or repair the source mesh.

Grid generation is controlled by GridSdfParams (C++, Python):

  • resolutionMode / resolution_mode selects the model measurement used to derive grid cell size, or selects explicit grid cell sizing.
  • resolutionDelta / resolution_delta is a per-axis multiplier in derived modes. In explicit mode, it is the maximum grid cell size in the model's length units.
  • boundaryPaddingDist / boundary_padding_dist expands the model bounds in the model's length units so queries remain valid outside the surface.
  • minGridResolution / min_grid_resolution sets the minimum number of grid cells per axis.

The defaults derive grid cell size from mean edge length. They are useful as a starting point, but production assets should select these parameters deliberately. Increasing resolutionDelta / resolution_delta creates larger cells, reducing detail, memory use, and generation time. Decreasing it preserves finer detail at sharply increasing memory and generation cost, approximately cubic in linear resolution. Choose a resolution based on the asset's physical scale, smallest relevant features, intended contact behavior, and available memory.

if (!modelData.mesh ||
(modelData.mesh->nodesPerElement != 3 && modelData.mesh->nodesPerElement != 4)) {
// Report that SDF baking requires a triangle or tetrahedral mesh, then return.
return;
}

superdex::GridSdfParams params{};
superdex::model_utils::BakeSdf(
modelData, params, superdex::ErrorAssert{});

if (!modelData.sdf || modelData.sdf->values.empty()) {
// Report that SDF baking did not produce grid data.
}

Save a .mochi.h5 Asset

Pass the HDF5 format explicitly when saving:

constexpr char const* outputPath = "generated/prepared_part.mochi.h5";
superdex::model_utils::SaveToFile(
modelData,
outputPath,
superdex::FileFormat::H5,
superdex::ErrorAssert{});

FileFormat::H5 / physics.FileFormat.H5 selects the serializer; the filename alone does not. Missing destination directories are created automatically. The saved model contains the model's mesh data and the baked SDF. model_utils::SaveToFile() / physics.model.save_to_file() serializes the supplied data without implicitly autocorrecting or validating it.

Do not blindly overwrite a richer source asset. Some existing model files contain data for unsupported or experimental features that the public ModelData representation cannot preserve when resaved.

Verify the Result

Reload the output through the same standalone model-data API and confirm that both data sets survived serialization:

superdex::ModelData savedModel = superdex::model_utils::LoadFromFile(
outputPath, superdex::ErrorAssert{});

if (!savedModel.mesh || !savedModel.sdf || savedModel.sdf->values.empty()) {
// Report that the saved asset is missing mesh or SDF data.
}

Loading the finished asset as a runtime physics shape is covered in Shapes.

These model-data operations do not require initialization or shutdown. Context initialization is needed when registering runtime shapes and constructing scenes, not when preparing and serializing model data.