Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/manifold/src/impl.h
9903 views
1
// Copyright 2021 The Manifold Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#pragma once
16
#include <map>
17
18
#include "collider.h"
19
#include "manifold/common.h"
20
#include "manifold/manifold.h"
21
#include "shared.h"
22
#include "vec.h"
23
24
namespace manifold {
25
26
/** @ingroup Private */
27
struct Manifold::Impl {
28
struct Relation {
29
int originalID = -1;
30
mat3x4 transform = la::identity;
31
bool backSide = false;
32
};
33
struct MeshRelationD {
34
/// The originalID of this Manifold if it is an original; -1 otherwise.
35
int originalID = -1;
36
std::map<int, Relation> meshIDtransform;
37
Vec<TriRef> triRef;
38
};
39
struct BaryIndices {
40
int tri, start4, end4;
41
};
42
43
Box bBox_;
44
double epsilon_ = -1;
45
double tolerance_ = -1;
46
int numProp_ = 0;
47
Error status_ = Error::NoError;
48
Vec<vec3> vertPos_;
49
Vec<Halfedge> halfedge_;
50
Vec<double> properties_;
51
// Note that vertNormal_ is not precise due to the use of an approximated acos
52
// function
53
Vec<vec3> vertNormal_;
54
Vec<vec3> faceNormal_;
55
Vec<vec4> halfedgeTangent_;
56
MeshRelationD meshRelation_;
57
Collider collider_;
58
59
static std::atomic<uint32_t> meshIDCounter_;
60
static uint32_t ReserveIDs(uint32_t);
61
62
Impl() {}
63
enum class Shape { Tetrahedron, Cube, Octahedron };
64
Impl(Shape, const mat3x4 = la::identity);
65
66
template <typename Precision, typename I>
67
Impl(const MeshGLP<Precision, I>& meshGL) {
68
const uint32_t numVert = meshGL.NumVert();
69
const uint32_t numTri = meshGL.NumTri();
70
71
if (meshGL.numProp < 3) {
72
MakeEmpty(Error::MissingPositionProperties);
73
return;
74
}
75
76
if (meshGL.mergeFromVert.size() != meshGL.mergeToVert.size()) {
77
MakeEmpty(Error::MergeVectorsDifferentLengths);
78
return;
79
}
80
81
if (!meshGL.runTransform.empty() &&
82
12 * meshGL.runOriginalID.size() != meshGL.runTransform.size()) {
83
MakeEmpty(Error::TransformWrongLength);
84
return;
85
}
86
87
if (!meshGL.runOriginalID.empty() && !meshGL.runIndex.empty() &&
88
meshGL.runOriginalID.size() + 1 != meshGL.runIndex.size() &&
89
meshGL.runOriginalID.size() != meshGL.runIndex.size()) {
90
MakeEmpty(Error::RunIndexWrongLength);
91
return;
92
}
93
94
if (!meshGL.faceID.empty() && meshGL.faceID.size() != meshGL.NumTri()) {
95
MakeEmpty(Error::FaceIDWrongLength);
96
return;
97
}
98
99
if (!manifold::all_of(meshGL.vertProperties.begin(),
100
meshGL.vertProperties.end(),
101
[](Precision x) { return std::isfinite(x); })) {
102
MakeEmpty(Error::NonFiniteVertex);
103
return;
104
}
105
106
if (!manifold::all_of(meshGL.runTransform.begin(),
107
meshGL.runTransform.end(),
108
[](Precision x) { return std::isfinite(x); })) {
109
MakeEmpty(Error::InvalidConstruction);
110
return;
111
}
112
113
if (!manifold::all_of(meshGL.halfedgeTangent.begin(),
114
meshGL.halfedgeTangent.end(),
115
[](Precision x) { return std::isfinite(x); })) {
116
MakeEmpty(Error::InvalidConstruction);
117
return;
118
}
119
120
std::vector<int> prop2vert;
121
if (!meshGL.mergeFromVert.empty()) {
122
prop2vert.resize(numVert);
123
std::iota(prop2vert.begin(), prop2vert.end(), 0);
124
for (size_t i = 0; i < meshGL.mergeFromVert.size(); ++i) {
125
const uint32_t from = meshGL.mergeFromVert[i];
126
const uint32_t to = meshGL.mergeToVert[i];
127
if (from >= numVert || to >= numVert) {
128
MakeEmpty(Error::MergeIndexOutOfBounds);
129
return;
130
}
131
prop2vert[from] = to;
132
}
133
}
134
135
const auto numProp = meshGL.numProp - 3;
136
numProp_ = numProp;
137
properties_.resize_nofill(meshGL.NumVert() * numProp);
138
tolerance_ = meshGL.tolerance;
139
// This will have unreferenced duplicate positions that will be removed by
140
// Impl::RemoveUnreferencedVerts().
141
vertPos_.resize_nofill(meshGL.NumVert());
142
143
for (size_t i = 0; i < meshGL.NumVert(); ++i) {
144
for (const int j : {0, 1, 2})
145
vertPos_[i][j] = meshGL.vertProperties[meshGL.numProp * i + j];
146
for (size_t j = 0; j < numProp; ++j)
147
properties_[i * numProp + j] =
148
meshGL.vertProperties[meshGL.numProp * i + 3 + j];
149
}
150
151
halfedgeTangent_.resize_nofill(meshGL.halfedgeTangent.size() / 4);
152
for (size_t i = 0; i < halfedgeTangent_.size(); ++i) {
153
for (const int j : {0, 1, 2, 3})
154
halfedgeTangent_[i][j] = meshGL.halfedgeTangent[4 * i + j];
155
}
156
157
Vec<TriRef> triRef;
158
triRef.resize_nofill(meshGL.NumTri());
159
160
auto runIndex = meshGL.runIndex;
161
const auto runEnd = meshGL.triVerts.size();
162
if (runIndex.empty()) {
163
runIndex = {0, static_cast<I>(runEnd)};
164
} else if (runIndex.size() == meshGL.runOriginalID.size()) {
165
runIndex.push_back(runEnd);
166
} else if (runIndex.size() == 1) {
167
runIndex.push_back(runEnd);
168
}
169
170
const auto startID =
171
Impl::ReserveIDs(std::max(1_uz, meshGL.runOriginalID.size()));
172
auto runOriginalID = meshGL.runOriginalID;
173
if (runOriginalID.empty()) {
174
runOriginalID.push_back(startID);
175
}
176
for (size_t i = 0; i < runOriginalID.size(); ++i) {
177
const int meshID = startID + i;
178
const int originalID = runOriginalID[i];
179
for (size_t tri = runIndex[i] / 3; tri < runIndex[i + 1] / 3; ++tri) {
180
TriRef& ref = triRef[tri];
181
ref.meshID = meshID;
182
ref.originalID = originalID;
183
ref.faceID = meshGL.faceID.empty() ? -1 : meshGL.faceID[tri];
184
ref.coplanarID = tri;
185
}
186
187
if (meshGL.runTransform.empty()) {
188
meshRelation_.meshIDtransform[meshID] = {originalID};
189
} else {
190
const Precision* m = meshGL.runTransform.data() + 12 * i;
191
meshRelation_.meshIDtransform[meshID] = {originalID,
192
{{m[0], m[1], m[2]},
193
{m[3], m[4], m[5]},
194
{m[6], m[7], m[8]},
195
{m[9], m[10], m[11]}}};
196
}
197
}
198
199
Vec<ivec3> triProp;
200
triProp.reserve(numTri);
201
Vec<ivec3> triVert;
202
const bool needsPropMap = numProp > 0 && !prop2vert.empty();
203
if (needsPropMap) triVert.reserve(numTri);
204
if (triRef.size() > 0) meshRelation_.triRef.reserve(numTri);
205
for (size_t i = 0; i < numTri; ++i) {
206
ivec3 triP, triV;
207
for (const size_t j : {0, 1, 2}) {
208
uint32_t vert = (uint32_t)meshGL.triVerts[3 * i + j];
209
if (vert >= numVert) {
210
MakeEmpty(Error::VertexOutOfBounds);
211
return;
212
}
213
triP[j] = vert;
214
triV[j] = prop2vert.empty() ? vert : prop2vert[vert];
215
}
216
if (triV[0] != triV[1] && triV[1] != triV[2] && triV[2] != triV[0]) {
217
if (needsPropMap) {
218
triProp.push_back(triP);
219
triVert.push_back(triV);
220
} else {
221
triProp.push_back(triV);
222
}
223
if (triRef.size() > 0) {
224
meshRelation_.triRef.push_back(triRef[i]);
225
}
226
}
227
}
228
229
CreateHalfedges(triProp, triVert);
230
if (!IsManifold()) {
231
MakeEmpty(Error::NotManifold);
232
return;
233
}
234
235
CalculateBBox();
236
SetEpsilon(-1, std::is_same<Precision, float>::value);
237
238
// we need to split pinched verts before calculating vertex normals, because
239
// the algorithm doesn't work with pinched verts
240
CleanupTopology();
241
CalculateNormals();
242
243
DedupePropVerts();
244
MarkCoplanar();
245
246
RemoveDegenerates();
247
RemoveUnreferencedVerts();
248
Finish();
249
250
if (!IsFinite()) {
251
MakeEmpty(Error::NonFiniteVertex);
252
return;
253
}
254
255
// A Manifold created from an input mesh is never an original - the input is
256
// the original.
257
meshRelation_.originalID = -1;
258
}
259
260
template <typename F>
261
inline void ForVert(int halfedge, F func) {
262
int current = halfedge;
263
do {
264
current = NextHalfedge(halfedge_[current].pairedHalfedge);
265
func(current);
266
} while (current != halfedge);
267
}
268
269
template <typename T>
270
void ForVert(
271
int halfedge, std::function<T(int halfedge)> transform,
272
std::function<void(int halfedge, const T& here, T& next)> binaryOp) {
273
T here = transform(halfedge);
274
int current = halfedge;
275
do {
276
const int nextHalfedge = NextHalfedge(halfedge_[current].pairedHalfedge);
277
T next = transform(nextHalfedge);
278
binaryOp(current, here, next);
279
here = next;
280
current = nextHalfedge;
281
} while (current != halfedge);
282
}
283
284
void MarkCoplanar();
285
void DedupePropVerts();
286
void RemoveUnreferencedVerts();
287
void InitializeOriginal(bool keepFaceID = false);
288
void CreateHalfedges(const Vec<ivec3>& triProp,
289
const Vec<ivec3>& triVert = {});
290
void CalculateNormals();
291
void IncrementMeshIDs();
292
293
void Update();
294
void MakeEmpty(Error status);
295
void Warp(std::function<void(vec3&)> warpFunc);
296
void WarpBatch(std::function<void(VecView<vec3>)> warpFunc);
297
Impl Transform(const mat3x4& transform) const;
298
299
bool IsEmpty() const { return NumTri() == 0; }
300
size_t NumVert() const { return vertPos_.size(); }
301
size_t NumEdge() const { return halfedge_.size() / 2; }
302
size_t NumTri() const { return halfedge_.size() / 3; }
303
size_t NumProp() const { return numProp_; }
304
size_t NumPropVert() const {
305
return NumProp() == 0 ? NumVert() : properties_.size() / NumProp();
306
}
307
308
// properties.cpp
309
enum class Property { Volume, SurfaceArea };
310
double GetProperty(Property prop) const;
311
void CalculateCurvature(int gaussianIdx, int meanIdx);
312
void CalculateBBox();
313
bool IsFinite() const;
314
bool IsIndexInBounds(VecView<const ivec3> triVerts) const;
315
void SetEpsilon(double minEpsilon = -1, bool useSingle = false);
316
bool IsManifold() const;
317
bool Is2Manifold() const;
318
bool IsSelfIntersecting() const;
319
bool MatchesTriNormals() const;
320
int NumDegenerateTris() const;
321
double MinGap(const Impl& other, double searchLength) const;
322
323
// sort.cpp
324
void Finish();
325
void SortVerts();
326
void ReindexVerts(const Vec<int>& vertNew2Old, size_t numOldVert);
327
void CompactProps();
328
void GetFaceBoxMorton(Vec<Box>& faceBox, Vec<uint32_t>& faceMorton) const;
329
void SortFaces(Vec<Box>& faceBox, Vec<uint32_t>& faceMorton);
330
void GatherFaces(const Vec<int>& faceNew2Old);
331
void GatherFaces(const Impl& old, const Vec<int>& faceNew2Old);
332
333
// face_op.cpp
334
void Face2Tri(const Vec<int>& faceEdge, const Vec<TriRef>& halfedgeRef,
335
bool allowConvex = false);
336
Polygons Slice(double height) const;
337
Polygons Project() const;
338
339
// edge_op.cpp
340
void CleanupTopology();
341
void SimplifyTopology(int firstNewVert = 0);
342
void RemoveDegenerates(int firstNewVert = 0);
343
void CollapseShortEdges(int firstNewVert = 0);
344
void CollapseColinearEdges(int firstNewVert = 0);
345
void SwapDegenerates(int firstNewVert = 0);
346
void DedupeEdge(int edge);
347
bool CollapseEdge(int edge, std::vector<int>& edges);
348
void RecursiveEdgeSwap(int edge, int& tag, std::vector<int>& visited,
349
std::vector<int>& edgeSwapStack,
350
std::vector<int>& edges);
351
void RemoveIfFolded(int edge);
352
void PairUp(int edge0, int edge1);
353
void UpdateVert(int vert, int startEdge, int endEdge);
354
void FormLoop(int current, int end);
355
void CollapseTri(const ivec3& triEdge);
356
void SplitPinchedVerts();
357
void DedupeEdges();
358
359
// subdivision.cpp
360
int GetNeighbor(int tri) const;
361
ivec4 GetHalfedges(int tri) const;
362
BaryIndices GetIndices(int halfedge) const;
363
void FillRetainedVerts(Vec<Barycentric>& vertBary) const;
364
Vec<Barycentric> Subdivide(std::function<int(vec3, vec4, vec4)>,
365
bool = false);
366
367
// smoothing.cpp
368
bool IsInsideQuad(int halfedge) const;
369
bool IsMarkedInsideQuad(int halfedge) const;
370
vec3 GetNormal(int halfedge, int normalIdx) const;
371
vec4 TangentFromNormal(const vec3& normal, int halfedge) const;
372
std::vector<Smoothness> UpdateSharpenedEdges(
373
const std::vector<Smoothness>&) const;
374
Vec<bool> FlatFaces() const;
375
Vec<int> VertFlatFace(const Vec<bool>&) const;
376
Vec<int> VertHalfedge() const;
377
std::vector<Smoothness> SharpenEdges(double minSharpAngle,
378
double minSmoothness) const;
379
void SharpenTangent(int halfedge, double smoothness);
380
void SetNormals(int normalIdx, double minSharpAngle);
381
void LinearizeFlatTangents();
382
void DistributeTangents(const Vec<bool>& fixedHalfedges);
383
void CreateTangents(int normalIdx);
384
void CreateTangents(std::vector<Smoothness>);
385
void Refine(std::function<int(vec3, vec4, vec4)>, bool = false);
386
387
// quickhull.cpp
388
void Hull(VecView<vec3> vertPos);
389
};
390
391
extern std::mutex dump_lock;
392
std::ostream& operator<<(std::ostream& stream, const Manifold::Impl& impl);
393
} // namespace manifold
394
395