Implement MeshFoundry pipeline (#77)
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
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
This commit is contained in:
85
crates/libremetaverse-rendering-mesh-foundry/README.md
Normal file
85
crates/libremetaverse-rendering-mesh-foundry/README.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 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
|
||||
|
||||
```console
|
||||
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.
|
||||
Reference in New Issue
Block a user