Files
MetaCrate/crates/libremetaverse-rendering-mesh-foundry
Chili Palmer 88408c9680
Some checks failed
Native code generation / deterministic (push) Failing after 1m58s
Imaging and meshing gate / native (push) Failing after 4m10s
JPEG 2000 feature / linux (push) Successful in 3m0s
Native Rust workspace compile / compile (push) Failing after 6m12s
Skia feature / linux (push) Has been cancelled
Implement MeshFoundry pipeline (#77)
2026-08-10 22:37:43 +00:00
..
2026-08-10 22:37:43 +00:00
2026-08-10 22:37:43 +00:00

LibreMetaverse MeshFoundry renderer

libremetaverse-rendering-mesh-foundry is the bounded native renderer for legacy prims, sculpt maps, terrain, and Second Life LLSD mesh assets. It uses the checked SimpleRenderer/PrimMesher path for legacy geometry and the native StructuredData binary codec for mesh containers. It does not wrap, load, or invoke the C# renderer or duplicate the LLSD and image codecs.

Pipelines

The mapped MeshFoundry methods cover:

  • simple and face-grouped legacy prim geometry at every DetailLevel, always retaining finite normals and UVs;
  • plane, cylinder, sphere, and torus sculpt maps;
  • rectangular height-map terrain with generated normals and UVs;
  • packed mesh-asset headers and individually zlib-compressed LLSD sections;
  • requested visual LOD selection (high_lod, medium_lod, low_lod, and lowest_lod) with deterministic highest-to-lowest fallback;
  • single-section simple-mesh extraction and physics convex/bounding hulls; and
  • default or planar texture transforms, repeats, offsets, rotation, and prim scale through the common IRendering contract.

Mesh vertices remain in prim-local coordinates. Quantized positions use each submesh's PositionDomain; normals and tangent components use the format's fixed [-1, 1] domain; UV0 and optional UV1 use their independent domains. Triangle and face order is preserved, while flattened multi-face output rebases indices without reordering vertices. Missing normals and tangents are generated deterministically from triangles and UVs. Degenerate UV gradients receive a stable normal-orthogonal fallback tangent.

The mapped Face type has no tangent field. Mesh tangents are therefore kept without changing the public C# layout in a public MeshFaceAux value stored in Face.user_data; recover it with face.user_data.downcast_ref::<MeshFaceAux>(). Its Vector4.w is the bitangent handedness. UV1 remains in Face.tex_coords1.

Rigged meshes and materials

The skin section decodes bounded joint names, inverse-bind matrices, bind-shape matrix, alternative inverse-bind matrices, pelvis offset, and the joint-position scale lock into the shared MeshSkinData. Per-vertex weight streams accept the protocol's sentinel form and its exactly-four-influence form, validate every joint index, clamp protocol weights, normalize four influences, and bind missing vertices to joint zero. The output is directly consumable by RiggedSkinMath and AnimeshSkinning.

Each submesh retains its original face ID and the effective inherited PrimitiveTextureEntryFace, including texture, legacy material, and render material overrides. NormalizedScale, face bounds, centers, optional UV1, weights, normals, tangents, and winding are kept together. Mesh sculpt mirror and invert flags apply the viewer-compatible reflection, normal inversion, and XOR winding rule to every face and tangent domain.

Bounds and failure contract

Assets and compressed/decompressed sections are capped at 64 MiB. Header sections and submeshes are capped at 256, each face remains within the 16-bit 65,536-vertex index domain, aggregate visual geometry is capped at 1,000,000 vertices and 6,000,000 indices, skins at 512 joints, and convex data at 65,536 hulls and 1,000,000 vertices. All sizes, offsets, index rebasing, buffer strides, and allocation products use checked arithmetic before slicing or allocation.

Malformed LLSD, zlib data, domains, parallel buffers, matrices, weights, offsets, and indices return Error::Rendering with the source primitive UUID and a stable operation context. UnpackMesh has no primitive parameter and uses the zero UUID. This crate performs no asset download, scene traversal, world transform, GPU upload, material shading, texture fetch, or drawing.

Reproducible gates and benchmark

python3 tools/check_milestone_10_issue_77.py
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-compat-tests --test imaging_meshing_semantics --locked -j1
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-rendering-mesh-foundry --locked -j1
CARGO_BUILD_JOBS=1 cargo bench -p libremetaverse-rendering-mesh-foundry --bench mesh_decode --profile benchmark --locked -j1

The named benchmark profile uses bounded-memory moderate optimization because full release optimization of the generated core surface can exceed small Gitea-worker memory before the fixture runs. The non-statistical benchmark builds and decodes a deterministic 57,600-vertex, 342,726-index mesh asset and reports elapsed time plus allocation counts. It is diagnostic evidence for regressions; correctness and malformed-input tests remain the release gates.