Skip to main content

Module mesh

Module mesh 

Source
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.

  1. Overlap. Where solids overlap, the first listed solid owns the space.
  2. 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 a VoxelGrid do. Geometry::locate has no direction; it uses the fixed offset tol * (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.
  3. No re-hit. Crossings at t <= tol along the flight are ignored, so a particle that has just crossed a surface and sits on it (to rounding) does not cross it again.
  4. 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 bvh module source), so no crossing is doubled or lost. Crossings of different solids within tol of 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, u32 count n, then n records of 12 little-endian f32 – normal and three vertices – and a 2-byte attribute) and ASCII (solid … facet normal … vertex x y z …). Binary is recognised by the length 84 + 50 n, not by the header text (binary files often begin with solid). 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] and f with i, i/t, i//n or i/t/n vertices, 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§

MeshGeometry
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.