Repository navigation
Introduce displacement extension to lib3mf - #469
vijaiaeroastro wants to merge 4 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #469 +/- ##
===========================================
+ Coverage 60.05% 60.16% +0.10%
===========================================
Files 67 71 +4
Lines 25306 26800 +1494
===========================================
+ Hits 15198 16123 +925
- Misses 10108 10677 +569 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Normal vectors must point strictly outward: a scalar product of exactly 0 with the triangle normal is now rejected, as the spec says. - Allow mirrored build item transforms for displacement meshes. The spec has no such limit. - Reader: d2/d3 without d1, and p2/p3 without p1, no longer fail. As the spec says, the triangle then has no displacement / uses the object property. - SetGeometry and SetTriangle on a displacement mesh now clear the displacements of the replaced triangles, so old data does not stay on the wrong triangle. - MergeFromModel: count source resources once, so merging a model into itself does not loop forever. - Writing a model after removing a texture, normal vector group or coordinate group that is still in use now fails with "Resource not found" instead of a generic error. - Core <triangles> attributes are ignored again, as before this branch, so normal files do not get new warnings. - Mark the displacement extension as required only in model parts that contain displacement content. - Add test files for valid and invalid displacement files, based on the example in the spec repository with its errors corrected.
Each open question in the PR now has a safe behaviour. The questions stay open in the PR description, so the behaviour can still change. - Unknown attributes on displacement elements give a warning instead of stopping the load, as in the rest of lib3mf. - STL export and MergeToModel still refuse a mesh with displacements, but the error now says what to do (write 3MF, or clear the displacements first). - Triangle sets on a displacement mesh are now read and written. Beam lattice and volume data on a displacement mesh are refused on read and write, with a clear error, instead of being dropped. - The displacement extension must be in requiredextensions only when a model part has a displacement mesh. Displacement resources alone no longer need it. - Normal (core) meshes read p1 without a triangle pid as before this branch (the p1 is ignored). Only displacement meshes use the object pid in this case. - The writer refuses a displacement mesh that uses a displacement group from another model part, because our reader cannot read that back.
Proposal: apply displacement to the mesh (follow-up PR)This is a proposal for a follow-up PR, not a change to this PR. It is here so The problemSTL, and a plain 3MF mesh, cannot hold displacement. Today lib3mf refuses to The ideaAdd a step that applies the displacement and creates a normal mesh with many For each displaced triangle:
The exact formulas are in Points that need care:
Proposed APIThe caller gives a maximum edge length in model units. Triangles are split Other options: one triangle per texture pixel (no parameter, but can create Reading the PNGlib3mf cannot read PNG pixels today. The volumetric image stack only stores the The decoder must read every kind of valid PNG (grey, RGB, RGBA, palette; What we checked (October 2026):
To keep the risk low, whichever decoder we choose:
Questions for the team
Until this is done, this PR keeps the current behaviour: STL export of a |
Displacement extension support
lib3mf supports version 1.0.0 of the 3MF Displacement extension at
http://schemas.3mf.io/3dmanufacturing/displacement/2023/10.The public component definition exposes four resource types:
Displacement2Dreferences a PNG texture attachment and stores its channel,U/V tile styles, and filter.
NormVectorGroupstores normalized displacement direction vectors.Disp2DGrouplinks a texture and normal-vector group with height and offset,and stores indexed UV/vector/factor coordinates.
DisplacementMeshObjectextendsMeshObjectwith per-triangle displacementgroup and coordinate indices.
Models provide add, lookup, and iterator methods for each type. Generic object
and mesh lookup preserves the displacement subtype.
MergeFromModelcopies thethree non-object displacement resources and remaps their dependency graph.
The 3MF reader accepts displacement resources and meshes in root and production
model parts. It applies
d1defaults tod2andd3, accepts adiddefault onthe
triangleselement, keeps core material properties on displacementtriangles, reads triangle sets, and requires the displacement namespace in
requiredextensionswhen a part has a displacement mesh.The writer emits dependency-sorted resources, displacement-prefixed mesh data,
triangle sets, the namespace declaration, and the required-extension token.
Validation covers required attributes and resource order, PNG attachments,
enumerations, coordinate and vertex indices, material-resource indices,
nonempty vector and coordinate groups, at least four triangles, manifold and
oriented positive-volume meshes, and strictly positive scalar products between
referenced vectors and face normals (as the spec says). Build item transforms
are not limited, so mirrored displacement meshes are allowed.
Vectors supplied through the API or reader are normalized before storage.
Setting new geometry or replacing a triangle on a displacement mesh clears the
displacement of the replaced triangles. A texture, normal vector group or
coordinate group can be removed while it is still in use, as for other
resource types; writing the model then fails with "Resource not found".
The library preserves displacement data but does not rasterize a displacement
texture into new mesh geometry. Consequently, STL export and
MergeToModelreject meshes with active displacement mappings instead of silently exporting
the undisplaced base surface.
Open questions
These are things we need to agree on before merging. Some need a decision from
us, and some need a clarification in the spec.
For each question below, the code already does the safest thing we could
think of. The "For now" line says what it does. We can still change it.
Decisions for this PR
Unknown attributes on displacement elements. What should the reader do
when it finds an attribute it does not know on a displacement element? The
example files in the spec repository have such an attribute (
contenttype).For now: the reader gives a warning and continues, like the rest of
lib3mf. (Before, it stopped loading the file.)
STL export. STL cannot hold displacement. Exporting the base mesh would
give the wrong shape without telling the user.
creates real triangles? Then STL, or a plain 3MF mesh, could be written
with the correct shape. This would be a separate feature, not part of
this PR.
For now: STL export and
MergeToModelrefuse a mesh withdisplacements. The error says: "Displacement is not applied to the mesh
geometry. Write a 3MF file, or clear the triangle displacements first."
Triangle sets, beam lattice and volume data on a displacement mesh.
Should these be supported?
For now: triangle sets are read and written. Beam lattice and volume
data are refused on read and on write with a clear error, because it is
not clear what they mean on a displaced mesh. (Before, all of them were
dropped without a warning.)
requiredextensionscheck. When mustdbe listed inrequiredextensions?For now: the reader requires it only when a model part has a
displacement mesh. A part with only displacement resources (a texture,
normal vectors or coordinate groups) does not need it. The writer still
lists
din every part that has any displacement content.Triangle
p1withoutpidon normal meshes. The core spec says atriangle with
p1but nopidshould use thepidof the object. lib3mfignores the
p1in this case. Should we fix this for normal meshes, in aseparate PR?
For now: normal meshes work as before this PR (the
p1is ignored).Only displacement meshes use the
pidof the object, as the spec says.Displacement mesh in one model part, groups in another. Should a
displacement mesh in a non-root model part be allowed to use a coordinate
group from another part? Our reader only looks in the same part.
For now: the writer refuses this with a clear error, so lib3mf never
writes a file that it cannot read back.
Questions for the 3MF Consortium
http://schemas.microsoft.com/3dmanufacturing/displacement/2023/10. The specsays
http://schemas.3mf.io/3dmanufacturing/displacement/2023/10.did="8". That id is thenormvectorgroup. It should be7, thedisp2dgroup.contenttypeattribute ondisplacement2d. Theschema does not have this attribute.
disp2dcoords, but the schema calls itdisp2dcoord. We follow the schema.channelattribute lists R, G and B. The text and theschema also allow A. We accept A.