Reading data
Routines for parsing surface grids from files into EBGeometry’s DCEL grids (see Half-edge meshes (DCEL)
for the concept, DCEL for the concrete API) – or directly into BVH-accelerated
signed distance functions, including the triangle-mesh representation described conceptually in
Triangle meshes – are given in the namespace EBGeometry::Parser.
The source code is implemented in Source/EBGeometry_Parser.hpp.
Important
EBGeometry is currently limited to reading STL, PLY, OBJ, and VTK (legacy or XML polydata) files, and then reconstructing DCEL grids from those. PLY and VTK files can contain associated data on the nodes and faces, but this is not automatically populated when constructing the DCEL grids. It is also possible to build DCEL grids from polygon soups read using third-party codes (see Using third-party sources).
Quickstart
Every reader function in EBGeometry::Parser comes in two overloads: one that takes a single
file name, and one that takes a std::vector<std::string> of file names and returns a vector
of results, one per file. If you have one or multiple mesh files, the quickest way to turn them
into BVH-accelerated signed distance fields is
std::vector<std::string> files; // <---- List of file names.
const auto distanceFields = EBGeometry::Parser::readIntoPackedBVH<float>(files);
This will build a DCEL mesh for each input file and wrap it in a MeshSDF, backed by
a SIMD-accelerated PackedBVH over the mesh’s faces. See DCEL mesh SDF with PackedBVH for
further details.
Tip
If the input files consist only of triangles, use the version
std::vector<std::string> files; // <---- List of file names.
const auto distanceFields = EBGeometry::Parser::readIntoTriangleBVH<float>(files);
This version will convert all DCEL polygons to triangles, pack them into SIMD-width groups,
and usually provides a nice code speedup over readIntoPackedBVH.
Reading raw file data
At the lowest level, readPLY<T>, readSTL<T>, readOBJ<T>, and readVTK<T> (each
with a single-filename and a std::vector<std::string> overload) parse a file into a raw,
format-specific data structure (PLY<T>, STL<T>, OBJ<T>, or VTK<T>) holding
nothing more than the vertex coordinates and face index lists as they appear in the file –
no DCEL topology, no signed distance functionality. Two small helpers support this layer:
getFileType inspects a file’s extension to determine which of the four formats it is (or
FileType::Unsupported), and getFileEncoding inspects the file header to determine
whether it is Encoding::ASCII or Encoding::Binary. Most users will not call these raw
readers directly – they exist mainly as the common first step every readInto* function
below builds on – but they are useful if you need the raw vertex/face data without paying for
DCEL construction at all.
Note
If an STL file contains multiple solids (uncommon, but technically valid STL), readSTL
only reads the first one.
For the raw readers’ exact signatures, see the Doxygen entries for readPLY, readSTL, readOBJ, and readVTK.
Reading mesh files
Above the raw per-format readers, EBGeometry offers five ways to turn a file directly into a higher-level representation, each doing progressively more work:
Into a DCEL mesh, with no signed-distance functionality –
readIntoDCEL, see DCEL.Into a bare DCEL signed distance function (
FlatMeshSDF, \(O(N)\) scan, no BVH) –readIntoMesh.Into a signed distance function representation of a DCEL mesh, using a
PackedBVHover DCEL faces (any polygon) –MeshSDF, viareadIntoPackedBVH.Into a signed distance function representation of a triangle mesh, using a
PackedBVHover SoA triangle groups –TriMeshSDF, viareadIntoTriangleBVH.Into a flat, unconnected list of
Triangleobjects (each with precomputed vertex positions, normals, and edge normals, but no half-edge topology linking them) – viareadIntoTriangles. Internally this still parses through a DCEL mesh first and then extracts each face as an independentTriangle; use it when you need per-triangle data as plain values (e.g. to feed your own acceleration structure) rather than any of EBGeometry’s own SDF wrappers.
See Mesh Signed Distance Function Classes for how the three SDF classes (options 2-4 above) compare.
Important
The EBGeometry parser will read input files into internal objects that represent each file type. Conversion of these objects into DCEL meshes is not required, and it is possible to create bounding volume hierarchies directly from the facets. This is useful when only an acceleration structure is needed for looking up facets or triangles, but no signed distance function is otherwise required.
DCEL representation
To read one or multiple files and turn it into DCEL meshes, use readIntoDCEL<T, Meta>(filename)
(or the std::vector<std::string> overload for multiple files at once), returning a
shared_ptr<DCEL::MeshT<T, Meta>> (or a vector thereof).
Note that this will only expose the DCEL mesh, but not include any signed distance functionality.
DCEL mesh SDF
To read one or multiple files and also turn it into a bare (BVH-free) signed distance
representation, use readIntoMesh<T, Meta>(filename), returning a
shared_ptr<FlatMeshSDF<T, Meta>> (or a vector thereof for the multi-file overload).
DCEL mesh SDF with PackedBVH
readIntoPackedBVH<T, Meta, K>(filename, build) wraps a DCEL mesh in a PackedBVH (depth-first
flat layout) with SIMD traversal, returning a shared_ptr<MeshSDF<T, Meta, K>> (or a vector
thereof). It supports any polygon, not just triangles; the BVH branching factor K defaults to
4 and the build strategy a_build defaults to BVH::Build::SAH. For maximum throughput on
triangle-only meshes, prefer readIntoTriangleBVH below.
Triangle meshes with PackedBVH
readIntoTriangleBVH<T, Meta, K, W>(filename, maxLeafGroups, build) converts all DCEL polygons
to triangles, packs them into SoA groups of W, and builds a PackedBVH, returning a
shared_ptr<TriMeshSDF<T, Meta, K, W>> (or a vector thereof). SIMD intrinsics evaluate up to
W triangles per leaf visit. K and W default to the SIMD-optimal values for T on the
current ISA (BVH::DefaultBranchingRatio<T>() and TriangleSoA::DefaultWidth<T>(), see
Mesh Signed Distance Function Classes); maxLeafGroups (default 2) bounds the number of full W-sized
SoA groups per BVH leaf. The code will raise an error if any face is not a triangle.
Flat triangle list
readIntoTriangles<T, Meta>(filename) returns a flat std::vector<shared_ptr<Triangle<T,
Meta>>> (or, for the multi-file overload, one such vector per file) – every face of the
parsed mesh as an independent, self-contained Triangle value, with no DCEL/half-edge
topology connecting them. Use this when some other part of your code wants raw triangle values
(for example, to build a custom acceleration structure) rather than any of EBGeometry’s own SDF
wrappers.
Note
readIntoDCEL, readIntoMesh, readIntoPackedBVH, readIntoTriangleBVH, and
readIntoTriangles are declared inline static in the header, so this project’s current
Doxygen configuration (EXTRACT_STATIC = NO) does not extract them into the generated API
reference individually – their exact signatures are documented via the Doxygen comment on
each function directly in Source/EBGeometry_Parser.hpp. The raw per-format readers
above (readPLY/readSTL/readOBJ/readVTK, declared without static) do not
have this limitation and are linked individually.
From soups to DCEL
EBGeometry also supports the creation of DCEL grids from polygon soups, which can then later be turned into an SDF representation. A triangle soup is represented as
std::vector<Vec3T<T>> vertices;
std::vector<std::vector<size_t>> faces;
Here, vertices contains the \(x,y,z\) coordinates of each vertex, while each entry faces contains a list of vertices for the face.
Turning a soup into a DCEL mesh is a two- (optionally three-) step process, using the functions
in namespace EBGeometry::Soup:
containsDegeneratePolygons(vertices, facets)is an optional up-front check: it returnstrueif any face has fewer than three vertices, or two or more vertices that coincide after lexicographic sorting. Useful for validating a soup produced by an external tool before spending time compressing/converting it.compress(vertices, facets)discards duplicate vertices from the soup in place, updatingfacetsto reference the compressed vertex list.soupToDCEL(mesh, vertices, facets, id)builds the vertices, half-edges, and faces of the (already-compressed) soup into the output DCEL mesh, reconciles pair edges (internally, viareconcilePairEdgesDCEL, which links each half-edge \(u \to v\) to its reverse \(v \to u\)), and runs a mesh sanity check. This also computes the vertex and edge normal vectors.
Note
Every function in EBGeometry::Soup is also declared inline static, so – for the same
reason noted above for the readInto* family – none of them currently appear individually
in the generated Doxygen API reference; the namespace page exists but is effectively empty.
Their exact signatures and contracts are documented via the Doxygen comment on each function
directly in Source/EBGeometry_Soup.hpp.
Warning
soupToDCEL will issue plenty of warnings if the polygon soup is not watertight and orientable.
Using third-party sources
By design, EBGeometry does not include much functionality for parsing files into polygon soups. There are many open source third-party codes for achieving this (and we have tested several of them):
stl_reader for STL files.
tinyobjloader for OBJ files.
In almost every case, the above codes can be read into polygon soups, and one can then turn the soup into a DCEL mesh as described in From soups to DCEL.