Classes | |
struct | BaryIndices |
struct | MeshRelationD |
struct | Relation |
Public Types | |
enum class | Shape { Tetrahedron , Cube , Octahedron } |
Static Public Member Functions | |
static uint32_t | ReserveIDs (uint32_t) |
Public Attributes | |
Box | bBox_ |
float | precision_ = -1 |
Error | status_ = Error::NoError |
Vec< glm::vec3 > | vertPos_ |
Vec< Halfedge > | halfedge_ |
Vec< glm::vec3 > | vertNormal_ |
Vec< glm::vec3 > | faceNormal_ |
Vec< glm::vec4 > | halfedgeTangent_ |
MeshRelationD | meshRelation_ |
Collider | collider_ |
Static Public Attributes | |
static std::atomic< uint32_t > | meshIDCounter_ |
struct manifold::Manifold::Impl::MeshRelationD |
struct manifold::Manifold::Impl::Relation |
Create either a unit tetrahedron, cube or octahedron. The cube is in the first octant, while the others are symmetric about the origin.
Create the halfedge_ data structure from an input triVerts array like Mesh.
void CalculateNormals | ( | ) |
If face normals are already present, this function uses them to compute vertex normals (angle-weighted pseudo-normals); otherwise it also computes the face normals. Face normals are only calculated when needed because nearly degenerate faces will accrue rounding error, while the Boolean can retain their original normal, which is more accurate and can help with merging coplanar faces.
If the face normals have been invalidated by an operation like Warp(), ensure you do faceNormal_.resize(0) before calling this function to force recalculation.
void IncrementMeshIDs | ( | ) |
Remaps all the contained meshIDs to new unique values to represent new instances of these meshes.
void Update | ( | ) |
Does a full recalculation of the face bounding boxes, including updating the collider, but does not resort the faces.
SparseIndices EdgeCollisions | ( | const Impl & | Q, |
bool | inverted = false |
||
) | const |
Returns a sparse array of the bounding box overlaps between the edges of the input manifold, Q and the faces of this manifold. Returned indices only point to forward halfedges.
SparseIndices VertexCollisionsZ | ( | VecView< const glm::vec3 > | vertsIn, |
bool | inverted = false |
||
) | const |
Returns a sparse array of the input vertices that project inside the XY bounding boxes of the faces of this manifold.
void CalculateBBox | ( | ) |
Calculates the bounding box of the entire manifold, which is stored internally to short-cut Boolean operations and to serve as the precision range for Morton code calculation. Ignores NaNs.
bool IsFinite | ( | ) | const |
Determines if all verts are finite. Checking just the bounding box dimensions is insufficient as it ignores NaNs.
Checks that the input triVerts array has all indices inside bounds of the vertPos_ array.
Sets the precision based on the bounding box, and limits its minimum value by the optional input.
bool IsManifold | ( | ) | const |
Returns true if this manifold is in fact an oriented even manifold and all of the data structures are consistent.
bool Is2Manifold | ( | ) | const |
Returns true if this manifold is in fact an oriented 2-manifold and all of the data structures are consistent.
bool MatchesTriNormals | ( | ) | const |
Returns true if all triangles are CCW relative to their triNormals_.
int NumDegenerateTris | ( | ) | const |
Returns the number of triangles that are colinear within precision_.
void Finish | ( | ) |
Once halfedge_ has been filled in, this function can be called to create the rest of the internal data structures. This function also removes the verts and halfedges flagged for removal (NaN verts and -1 halfedges).
void SortVerts | ( | ) |
Sorts the vertices according to their Morton code.
Updates the halfedges to point to new vert indices based on a mapping, vertNew2Old. This may be a subset, so the total number of original verts is also given.
void CompactProps | ( | ) |
Removes unreferenced property verts and reindexes triProperties.
Fills the faceBox and faceMorton input with the bounding boxes and Morton codes of the faces, respectively. The Morton code is based on the center of the bounding box.
Sorts the faces of this manifold according to their input Morton code. The bounding box and Morton code arrays are also sorted accordingly.
Creates the halfedge_ vector for this manifold by copying a set of faces from another manifold, given by oldHalfedge. Input faceNew2Old defines the old faces to gather into this.
Triangulates the faces. In this case, the halfedge_ vector is not yet a set of triangles as required by this data structure, but is instead a set of general faces with the input faceEdge vector having length of the number of faces + 1. The values are indicies into the halfedge_ vector for the first edge of each face, with the final value being the length of the halfedge_ vector itself. Upon return, halfedge_ has been lengthened and properly represents the mesh as a set of triangles as usual. In this process the faceNormal_ values are retained, repeated as necessary.
PolygonsIdx Face2Polygons | ( | VecView< Halfedge >::IterC | start, |
VecView< Halfedge >::IterC | end, | ||
glm::mat3x2 | projection | ||
) | const |
Returns a set of 2D polygons formed by the input projection of the vertices of the list of Halfedges, which must be an even-manifold, meaning each vert must be referenced the same number of times as a startVert and endVert.
void SimplifyTopology | ( | ) |
Collapses degenerate triangles by removing edges shorter than precision_ and any edge that is preceeded by an edge that joins the same two face relations. It also performs edge swaps on the long edges of degenerate triangles, though there are some configurations of degenerates that cannot be removed this way.
Before collapsing edges, the mesh is checked for duplicate edges (more than one pair of triangles sharing the same edge), which are removed by duplicating one vert and adding two triangles. These degenerate triangles are likely to be collapsed again in the subsequent simplification.
Note when an edge collapse would result in something non-manifold, the vertices are duplicated in such a way as to remove handles or separate meshes, thus decreasing the Genus(). It only increases when meshes that have collapsed to just a pair of triangles are removed entirely.
Rather than actually removing the edges, this step merely marks them for removal, by setting vertPos to NaN and halfedge to {-1, -1, -1, -1}.
Returns the tri side index (0-2) connected to the other side of this quad if this tri is part of a quad, or -1 otherwise.
glm::ivec4 GetHalfedges | ( | int | tri | ) | const |
For the given triangle index, returns either the three halfedge indices of that triangle and halfedges[3] = -1, or if the triangle is part of a quad, it returns those four indices. If the triangle is part of a quad and is not the lower of the two triangle indices, it returns all -1s.
Manifold::Impl::BaryIndices GetIndices | ( | int | halfedge | ) | const |
Returns the BaryIndices, which gives the tri and indices (0-3), such that GetHalfedges(val.tri)[val.start4] points back to this halfedge, and val.end4 will point to the next one. This function handles this for both triangles and quads. Returns {-1, -1, -1} if the edge is the interior of a quad.
void FillRetainedVerts | ( | Vec< Barycentric > & | vertBary | ) | const |
Retained verts are part of several triangles, and it doesn't matter which one the vertBary refers to. Here, whichever is last will win and it's done on the CPU for simplicity for now. Using AtomicCAS on .tri should work for a GPU version if desired.
Vec< Barycentric > Subdivide | ( | std::function< int(glm::vec3)> | edgeDivisions | ) |
Split each edge into n pieces as defined by calling the edgeDivisions function, and sub-triangulate each triangle accordingly. This function doesn't run Finish(), as that is expensive and it'll need to be run after the new vertices have moved, which is a likely scenario after refinement (smoothing).
Returns true if this halfedge should be marked as the interior of a quad, as defined by its two triangles referring to the same face, and those triangles having no further face neighbors beyond.
Returns true if this halfedge is an interior of a quad, as defined by its halfedge tangent having negative weight.
Get the property normal associated with the startVert of this halfedge, where normalIdx shows the beginning of where normals are stored in the properties.
Sharpen tangents that intersect an edge to sharpen that edge. The weight is unchanged, as this has a squared effect on radius of curvature, except in the case of zero radius, which is marked with weight = 0.
Instead of calculating the internal shared normals like CalculateNormals does, this method fills in vertex properties, unshared across edges that are bent more than minSharpAngle.
void LinearizeFlatTangents | ( | ) |
Tangents get flattened to create sharp edges by setting their weight to zero. This is the natural limit of reducing the weight to increase the sharpness smoothly. This limit gives a decent shape, but it causes the parameterization to be stretched and compresses it near the edges, which is good for resolving tight curvature, but bad for property interpolation. This function fixes the parameter stretch at the limit for sharp edges, since there is no curvature to resolve. Note this also changes the overall shape - making it more evenly curved.
Calculates halfedgeTangent_, allowing the manifold to be refined and smoothed. The tangents form weighted cubic Beziers along each edge. This function creates circular arcs where possible (minimizing maximum curvature), constrained to the indicated property normals. Across edges that form discontinuities in the normals, the tangent vectors are zero-length, allowing the shape to form a sharp corner with minimal oscillation.
void CreateTangents | ( | std::vector< Smoothness > | sharpenedEdges | ) |
Calculates halfedgeTangent_, allowing the manifold to be refined and smoothed. The tangents form weighted cubic Beziers along each edge. This function creates circular arcs where possible (minimizing maximum curvature), constrained to the vertex normals. Where sharpenedEdges are specified, the tangents are shortened that intersect the sharpened edge, concentrating the curvature there, while the tangents of the sharp edges themselves are aligned for continuity.