Manifold 3.0
Robust geometry
 
Loading...
Searching...
No Matches
MeshGLP< Precision, I > Struct Template Reference

Mesh input/output suitable for pushing directly into graphics libraries. More...

#include <manifold.h>

Public Member Functions

NumVert () const
 Number of property vertices.
 
NumTri () const
 Number of triangles.
 
bool Merge ()
 
la::vec< Precision, 3 > GetVertPos (size_t v) const
 
la::vec< I, 3 > GetTriVerts (size_t t) const
 
la::vec< Precision, 4 > GetTangent (size_t h) const
 

Public Attributes

numProp = 3
 Number of properties per vertex, always >= 3.
 
std::vector< Precision > vertProperties
 
std::vector< I > triVerts
 
std::vector< I > mergeFromVert
 
std::vector< I > mergeToVert
 
std::vector< I > runIndex
 
std::vector< uint32_t > runOriginalID
 
std::vector< Precision > runTransform
 
std::vector< I > faceID
 
std::vector< Precision > halfedgeTangent
 
Precision tolerance = 0
 

Detailed Description

template<typename Precision, typename I = uint32_t>
struct manifold::MeshGLP< Precision, I >

Mesh input/output suitable for pushing directly into graphics libraries.

The core (non-optional) parts of MeshGL are the triVerts indices buffer and the vertProperties interleaved vertex buffer, which follow the conventions of OpenGL (and other graphic libraries') buffers and are therefore generally easy to map directly to other applications' data structures.

The triVerts vector has a stride of 3 and specifies triangles as vertex indices. For triVerts = [2, 4, 5, 3, 1, 6, ...], the triangles are [2, 4, 5], [3, 1, 6], etc. and likewise the halfedges are [2, 4], [4, 5], [5, 2], [3, 1], [1, 6], [6, 3], etc.

The triVerts indices should form a manifold mesh: each of the 3 halfedges of each triangle should have exactly one paired halfedge in the list, defined as having the first index of one equal to the second index of the other and vice-versa. However, this is not always possible - consider e.g. a cube with normal-vector properties. Shared vertices would turn the cube into a ball by interpolating normals - the common solution is to duplicate each corner vertex into 3, each with the same position, but different normals corresponding to each face. This is exactly what should be done in MeshGL, however we request two additional vectors in this case: mergeFromVert and mergeToVert. Each vertex mergeFromVert[i] is merged into vertex mergeToVert[i], avoiding unreliable floating-point comparisons to recover the manifold topology. These merges are simply a union, so which is from and to doesn't matter.

If you don't have merge vectors, you can create them with the Merge() method, however this will fail if the mesh is not already manifold within the set tolerance. For maximum reliablility, always store the merge vectors with the mesh, e.g. using the EXT_mesh_manifold extension in glTF.

You can have any number of arbitrary floating-point properties per vertex, and they will all be interpolated as necessary during operations. It is up to you to keep track of which channel represents what type of data. A few of Manifold's methods allow you to specify the channel where normals data starts, in order to update it automatically for transforms and such. This will be easier if your meshes all use the same channels for properties, but this is not a requirement. Operations between meshes with different numbers of peroperties will simply use the larger numProp and pad the smaller one with zeroes.

On output, the triangles are sorted into runs (runIndex, runOriginalID, runTransform) that correspond to different mesh inputs. Other 3D libraries may refer to these runs as primitives of a mesh (as in glTF) or draw calls, as they often represent different materials on different parts of the mesh. It is generally a good idea to maintain a map of OriginalIDs to materials to make it easy to reapply them after a set of Boolean operations. These runs can also be used as input, and thus also ensure a lossless roundtrip of data through MeshGL.

As an example, with runIndex = [0, 6, 18, 21] and runOriginalID = [1, 3, 3], there are 7 triangles, where the first two are from the input mesh with ID 1, the next 4 are from an input mesh with ID 3, and the last triangle is from a different copy (instance) of the input mesh with ID 3. These two instances can be distinguished by their different runTransform matrices.

You can reconstruct polygonal faces by assembling all the triangles that are from the same run and share the same faceID. These faces will be planar within the output tolerance.

The halfedgeTangent vector is used to specify the weighted tangent vectors of each halfedge for the purpose of using the Refine methods to create a smoothly-interpolated surface. They can also be output when calculated automatically by the Smooth functions.

MeshGL is an alias for the standard single-precision version. Use MeshGL64 to output the full double precision that Manifold uses internally.

Member Function Documentation

◆ Merge()

template<typename Precision, typename I = uint32_t>
bool Merge ( )

Updates the mergeFromVert and mergeToVert vectors in order to create a manifold solid. If the MeshGL is already manifold, no change will occur and the function will return false. Otherwise, this will merge verts along open edges within tolerance (the maximum of the MeshGL tolerance and the baseline bounding-box tolerance), keeping any from the existing merge vectors, and return true.

There is no guarantee the result will be manifold - this is a best-effort helper function designed primarily to aid in the case where a manifold multi-material MeshGL was produced, but its merge vectors were lost due to a round-trip through a file format. Constructing a Manifold from the result will report an error status if it is not manifold.

◆ GetVertPos()

template<typename Precision, typename I = uint32_t>
la::vec< Precision, 3 > GetVertPos ( size_t v) const
inline

Returns the x, y, z position of the ith vertex.

Parameters
vvertex index.

◆ GetTriVerts()

template<typename Precision, typename I = uint32_t>
la::vec< I, 3 > GetTriVerts ( size_t t) const
inline

Returns the three vertex indices of the ith triangle.

Parameters
ttriangle index.

◆ GetTangent()

template<typename Precision, typename I = uint32_t>
la::vec< Precision, 4 > GetTangent ( size_t h) const
inline

Returns the x, y, z, w tangent of the ith halfedge.

Parameters
hhalfedge index (3 * triangle_index + [0|1|2]).

Member Data Documentation

◆ vertProperties

template<typename Precision, typename I = uint32_t>
std::vector<Precision> vertProperties

Flat, GL-style interleaved list of all vertex properties: propVal = vertProperties[vert * numProp + propIdx]. The first three properties are always the position x, y, z. The stride of the array is numProp.

◆ triVerts

template<typename Precision, typename I = uint32_t>
std::vector<I> triVerts

The vertex indices of the three triangle corners in CCW (from the outside) order, for each triangle.

◆ mergeFromVert

template<typename Precision, typename I = uint32_t>
std::vector<I> mergeFromVert

Optional: A list of only the vertex indicies that need to be merged to reconstruct the manifold.

◆ mergeToVert

template<typename Precision, typename I = uint32_t>
std::vector<I> mergeToVert

Optional: The same length as mergeFromVert, and the corresponding value contains the vertex to merge with. It will have an identical position, but the other properties may differ.

◆ runIndex

template<typename Precision, typename I = uint32_t>
std::vector<I> runIndex

Optional: Indicates runs of triangles that correspond to a particular input mesh instance. The runs encompass all of triVerts and are sorted by runOriginalID. Run i begins at triVerts[runIndex[i]] and ends at triVerts[runIndex[i+1]]. All runIndex values are divisible by 3. Returned runIndex will always be 1 longer than runOriginalID, but same length is also allowed as input: triVerts.size() will be automatically appended in this case.

◆ runOriginalID

template<typename Precision, typename I = uint32_t>
std::vector<uint32_t> runOriginalID

Optional: The OriginalID of the mesh this triangle run came from. This ID is ideal for reapplying materials to the output mesh. Multiple runs may have the same ID, e.g. representing different copies of the same input mesh. If you create an input MeshGL that you want to be able to reference as one or more originals, be sure to set unique values from ReserveIDs().

◆ runTransform

template<typename Precision, typename I = uint32_t>
std::vector<Precision> runTransform

Optional: For each run, a 3x4 transform is stored representing how the corresponding original mesh was transformed to create this triangle run. This matrix is stored in column-major order and the length of the overall vector is 12 * runOriginalID.size().

◆ faceID

template<typename Precision, typename I = uint32_t>
std::vector<I> faceID

Optional: Length NumTri, contains the source face ID this triangle comes from. When auto-generated, this ID will be a triangle index into the original mesh. This index/ID is purely for external use (e.g. recreating polygonal faces) and will not affect Manifold's algorithms.

◆ halfedgeTangent

template<typename Precision, typename I = uint32_t>
std::vector<Precision> halfedgeTangent

Optional: The X-Y-Z-W weighted tangent vectors for smooth Refine(). If non-empty, must be exactly four times as long as Mesh.triVerts. Indexed as 4 * (3 * tri + i) + j, i < 3, j < 4, representing the tangent value Mesh.triVerts[tri][i] along the CCW edge. If empty, mesh is faceted.

◆ tolerance

template<typename Precision, typename I = uint32_t>
Precision tolerance = 0

Tolerance for mesh simplification. When creating a Manifold, the tolerance used will be the maximum of this and a baseline tolerance from the size of the bounding box. Any edge shorter than tolerance may be collapsed. Tolerance may be enlarged when floating point error accumulates.