Expand description
Triangle-mesh solids: loaders (STL, OBJ), the watertightness check, and the
MeshGeometry target built on a BVH.
§Solids and regions
A TriMesh is one closed, outward-oriented triangle surface (possibly
several shells, for example an outer surface and an inward-facing cavity).
A MeshGeometry is an ordered list of solids, each tagged with an index
into a shared material list. One region per solid, in the order listed.
Space outside every solid is vacuum.
§Ownership rules
These are the overlap, boundary and tolerance rules of the mesh target. Other solid representations of the same target (such as a constructive-solid-geometry one) are meant to follow them.
- Overlap. Where solids overlap, the first listed solid owns the space.
- Surface points, directional. A flight is owned, at each point, by the
solid it is heading into. Concretely, the state of a solid at the start
of a flight is its state at
pos + tol * dir, so a start on a surface belongs to the solid on the side the flight enters, as the faces of aVoxelGriddo.Geometry::locatehas no direction; it uses the fixed offsettol * (1, 1, 1) / sqrt(3), so lower faces (and edges, vertices) of an axis-aligned solid belong to it and upper ones do not, exactly as voxel faces do. - No re-hit. Crossings at
t <= tolalong the flight are ignored, so a particle that has just crossed a surface and sits on it (to rounding) does not cross it again. - Edges and vertices. A flight through an edge or vertex shared by
several triangles crosses the surface once: the ray-triangle test
resolves exact ties by a fixed rule that is consistent between
neighbours (see the
bvhmodule source), so no crossing is doubled or lost. Crossings of different solids withintolof each other are one event, so a flight through a surface shared by two solids passes directly from one to the other and never through vacuum between them.
The tolerance is tol = 1e-10 x the diagonal of the bounding box of all
solids (see MeshGeometry::tolerance_m); it is far above rounding
(about 1e-16 of a coordinate) and below any feature worth resolving.
Two crossings of one solid closer than tol cancel.
§Events
Geometry::exit reports Enter { region, pos } when the owner changes
to a solid of a different material (a change between solids of the same
material is not an event, as crossing a voxel face inside one block is
not), and Escape when the flight leaves every solid. Geometry::flight
is overridden to report the solid a clear flight ends in. The Face of an
escape comes from the outward unit normal n of the triangle crossed:
Face::Front if n_x is negative and the largest component in
magnitude, Face::Back if positive and largest, Face::Side
otherwise (for flat axis-aligned faces this is the voxel convention; on a
curved surface the target is split by the dominant axis).
The start state of every other solid costs one unbounded ray query, so a
flight in a scene of n solids costs O(n log m). A single solid takes
the fast path.
§Point in solid
The parity of the number of crossings of a ray from the point to infinity (J. Foley et al., Computer Graphics: Principles and Practice, 2nd ed., Addison-Wesley 1990, section 15.10, ray-casting inside tests). The ray direction is fixed, and exact edge or vertex hits are resolved by the same tie-break as above, so the result is deterministic.
§File formats and units
Lengths are metres at the API. A file’s coordinates are multiplied by the
unit_m argument of the loaders (1e-9 for a file in nm, 1.0 for
metres); neither format records units.
- STL (3D Systems, StereoLithography Interface Specification,
1989): binary (80-byte header,
u32countn, thennrecords of 12 little-endianf32– normal and three vertices – and a 2-byte attribute) and ASCII (solid…facet normal…vertex x y z…). Binary is recognised by the length84 + 50 n, not by the header text (binary files often begin withsolid). The stored normals are ignored: orientation comes from the vertex order (counter-clockwise seen from outside), and is checked. - OBJ (Wavefront; the file format specification of Alias|Wavefront,
1992):
v x y z [w]andfwithi,i/t,i//nori/t/nvertices, 1-based or negative (relative to the vertices read so far). Polygons are fan-triangulated from the first vertex. All faces of a file form one mesh; other statements (vt,vn,o,g,usemtl,s, …) are skipped.
§Watertightness
Vertices are welded by exact coordinate equality (the formats repeat
them). Then every undirected edge must belong to exactly two triangles that
traverse it in opposite directions (a closed, consistently oriented
2-manifold), no triangle may be degenerate (zero area or a repeated
vertex, or a sliver thinner than 1e-12 of its longest edge), and the
signed volume must be positive, which means the normals point outward.
Violations return a GeometryError naming a bad edge by the positions of
its two vertices.
Structs§
- Mesh
Geometry - A target of closed triangle-mesh solids, each tagged with a material, with a BVH per solid. See the module docs for the ownership rules.
- TriMesh
- A closed, watertight, outward-oriented triangle mesh with welded vertices.