Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/manifold/src/impl.h
20952 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 (numVert == 0 && numTri == 0) {
72
MakeEmpty(Error::NoError);
73
return;
74
}
75
76
if (numVert < 4 || numTri < 4) {
77
MakeEmpty(Error::NotManifold);
78
return;
79
}
80
81
if (meshGL.numProp < 3) {
82
MakeEmpty(Error::MissingPositionProperties);
83
return;
84
}
85
86
if (meshGL.mergeFromVert.size() != meshGL.mergeToVert.size()) {
87
MakeEmpty(Error::MergeVectorsDifferentLengths);
88
return;
89
}
90
91
if (!meshGL.runTransform.empty() &&
92
12 * meshGL.runOriginalID.size() != meshGL.runTransform.size()) {
93
MakeEmpty(Error::TransformWrongLength);
94
return;
95
}
96
97
if (!meshGL.runOriginalID.empty() && !meshGL.runIndex.empty() &&
98
meshGL.runOriginalID.size() + 1 != meshGL.runIndex.size() &&
99
meshGL.runOriginalID.size() != meshGL.runIndex.size()) {
100
MakeEmpty(Error::RunIndexWrongLength);
101
return;
102
}
103
104
if (!meshGL.faceID.empty() && meshGL.faceID.size() != meshGL.NumTri()) {
105
MakeEmpty(Error::FaceIDWrongLength);
106
return;
107
}
108
109
if (!manifold::all_of(meshGL.vertProperties.begin(),
110
meshGL.vertProperties.end(),
111
[](Precision x) { return std::isfinite(x); })) {
112
MakeEmpty(Error::NonFiniteVertex);
113
return;
114
}
115
116
if (!manifold::all_of(meshGL.runTransform.begin(),
117
meshGL.runTransform.end(),
118
[](Precision x) { return std::isfinite(x); })) {
119
MakeEmpty(Error::InvalidConstruction);
120
return;
121
}
122
123
if (!manifold::all_of(meshGL.halfedgeTangent.begin(),
124
meshGL.halfedgeTangent.end(),
125
[](Precision x) { return std::isfinite(x); })) {
126
MakeEmpty(Error::InvalidConstruction);
127
return;
128
}
129
130
std::vector<int> prop2vert;
131
if (!meshGL.mergeFromVert.empty()) {
132
prop2vert.resize(numVert);
133
std::iota(prop2vert.begin(), prop2vert.end(), 0);
134
for (size_t i = 0; i < meshGL.mergeFromVert.size(); ++i) {
135
const uint32_t from = meshGL.mergeFromVert[i];
136
const uint32_t to = meshGL.mergeToVert[i];
137
if (from >= numVert || to >= numVert) {
138
MakeEmpty(Error::MergeIndexOutOfBounds);
139
return;
140
}
141
prop2vert[from] = to;
142
}
143
}
144
145
const auto numProp = meshGL.numProp - 3;
146
numProp_ = numProp;
147
properties_.resize_nofill(meshGL.NumVert() * numProp);
148
tolerance_ = meshGL.tolerance;
149
// This will have unreferenced duplicate positions that will be removed by
150
// Impl::RemoveUnreferencedVerts().
151
vertPos_.resize_nofill(meshGL.NumVert());
152
153
for (size_t i = 0; i < meshGL.NumVert(); ++i) {
154
for (const int j : {0, 1, 2})
155
vertPos_[i][j] = meshGL.vertProperties[meshGL.numProp * i + j];
156
for (size_t j = 0; j < numProp; ++j)
157
properties_[i * numProp + j] =
158
meshGL.vertProperties[meshGL.numProp * i + 3 + j];
159
}
160
161
halfedgeTangent_.resize_nofill(meshGL.halfedgeTangent.size() / 4);
162
for (size_t i = 0; i < halfedgeTangent_.size(); ++i) {
163
for (const int j : {0, 1, 2, 3})
164
halfedgeTangent_[i][j] = meshGL.halfedgeTangent[4 * i + j];
165
}
166
167
Vec<TriRef> triRef;
168
triRef.resize_nofill(meshGL.NumTri());
169
170
auto runIndex = meshGL.runIndex;
171
const auto runEnd = meshGL.triVerts.size();
172
if (runIndex.empty()) {
173
runIndex = {0, static_cast<I>(runEnd)};
174
} else if (runIndex.size() == meshGL.runOriginalID.size()) {
175
runIndex.push_back(runEnd);
176
} else if (runIndex.size() == 1) {
177
runIndex.push_back(runEnd);
178
}
179
180
const auto startID =
181
Impl::ReserveIDs(std::max(1_uz, meshGL.runOriginalID.size()));
182
auto runOriginalID = meshGL.runOriginalID;
183
if (runOriginalID.empty()) {
184
runOriginalID.push_back(startID);
185
}
186
for (size_t i = 0; i < runOriginalID.size(); ++i) {
187
const int meshID = startID + i;
188
const int originalID = runOriginalID[i];
189
for (size_t tri = runIndex[i] / 3; tri < runIndex[i + 1] / 3; ++tri) {
190
TriRef& ref = triRef[tri];
191
ref.meshID = meshID;
192
ref.originalID = originalID;
193
ref.faceID = meshGL.faceID.empty() ? -1 : meshGL.faceID[tri];
194
ref.coplanarID = tri;
195
}
196
197
if (meshGL.runTransform.empty()) {
198
meshRelation_.meshIDtransform[meshID] = {originalID};
199
} else {
200
const Precision* m = meshGL.runTransform.data() + 12 * i;
201
meshRelation_.meshIDtransform[meshID] = {originalID,
202
{{m[0], m[1], m[2]},
203
{m[3], m[4], m[5]},
204
{m[6], m[7], m[8]},
205
{m[9], m[10], m[11]}}};
206
}
207
}
208
209
Vec<ivec3> triProp;
210
triProp.reserve(numTri);
211
Vec<ivec3> triVert;
212
const bool needsPropMap = numProp > 0 && !prop2vert.empty();
213
if (needsPropMap) triVert.reserve(numTri);
214
if (triRef.size() > 0) meshRelation_.triRef.reserve(numTri);
215
for (size_t i = 0; i < numTri; ++i) {
216
ivec3 triP, triV;
217
for (const size_t j : {0, 1, 2}) {
218
uint32_t vert = (uint32_t)meshGL.triVerts[3 * i + j];
219
if (vert >= numVert) {
220
MakeEmpty(Error::VertexOutOfBounds);
221
return;
222
}
223
triP[j] = vert;
224
triV[j] = prop2vert.empty() ? vert : prop2vert[vert];
225
}
226
if (triV[0] != triV[1] && triV[1] != triV[2] && triV[2] != triV[0]) {
227
if (needsPropMap) {
228
triProp.push_back(triP);
229
triVert.push_back(triV);
230
} else {
231
triProp.push_back(triV);
232
}
233
if (triRef.size() > 0) {
234
meshRelation_.triRef.push_back(triRef[i]);
235
}
236
}
237
}
238
239
CreateHalfedges(triProp, triVert);
240
if (!IsManifold()) {
241
MakeEmpty(Error::NotManifold);
242
return;
243
}
244
245
CalculateBBox();
246
SetEpsilon(-1, std::is_same<Precision, float>::value);
247
248
// we need to split pinched verts before calculating vertex normals, because
249
// the algorithm doesn't work with pinched verts
250
CleanupTopology();
251
CalculateNormals();
252
253
DedupePropVerts();
254
MarkCoplanar();
255
256
RemoveDegenerates();
257
RemoveUnreferencedVerts();
258
Finish();
259
260
if (!IsFinite()) {
261
MakeEmpty(Error::NonFiniteVertex);
262
return;
263
}
264
265
// A Manifold created from an input mesh is never an original - the input is
266
// the original.
267
meshRelation_.originalID = -1;
268
}
269
270
template <typename F>
271
inline void ForVert(int halfedge, F func) {
272
int current = halfedge;
273
do {
274
current = NextHalfedge(halfedge_[current].pairedHalfedge);
275
func(current);
276
} while (current != halfedge);
277
}
278
279
template <typename T>
280
void ForVert(
281
int halfedge, std::function<T(int halfedge)> transform,
282
std::function<void(int halfedge, const T& here, T& next)> binaryOp) {
283
T here = transform(halfedge);
284
int current = halfedge;
285
do {
286
const int nextHalfedge = NextHalfedge(halfedge_[current].pairedHalfedge);
287
T next = transform(nextHalfedge);
288
binaryOp(current, here, next);
289
here = next;
290
current = nextHalfedge;
291
} while (current != halfedge);
292
}
293
294
void MarkCoplanar();
295
void DedupePropVerts();
296
void RemoveUnreferencedVerts();
297
void InitializeOriginal(bool keepFaceID = false);
298
void CreateHalfedges(const Vec<ivec3>& triProp,
299
const Vec<ivec3>& triVert = {});
300
void CalculateNormals();
301
void IncrementMeshIDs();
302
303
void Update();
304
void MakeEmpty(Error status);
305
void Warp(std::function<void(vec3&)> warpFunc);
306
void WarpBatch(std::function<void(VecView<vec3>)> warpFunc);
307
Impl Transform(const mat3x4& transform) const;
308
309
bool IsEmpty() const { return NumTri() == 0; }
310
size_t NumVert() const { return vertPos_.size(); }
311
size_t NumEdge() const { return halfedge_.size() / 2; }
312
size_t NumTri() const { return halfedge_.size() / 3; }
313
size_t NumProp() const { return numProp_; }
314
size_t NumPropVert() const {
315
return NumProp() == 0 ? NumVert() : properties_.size() / NumProp();
316
}
317
318
// properties.cpp
319
enum class Property { Volume, SurfaceArea };
320
double GetProperty(Property prop) const;
321
void CalculateCurvature(int gaussianIdx, int meanIdx);
322
void CalculateBBox();
323
bool IsFinite() const;
324
bool IsIndexInBounds(VecView<const ivec3> triVerts) const;
325
void SetEpsilon(double minEpsilon = -1, bool useSingle = false);
326
bool IsManifold() const;
327
bool Is2Manifold() const;
328
bool IsSelfIntersecting() const;
329
bool MatchesTriNormals() const;
330
int NumDegenerateTris() const;
331
double MinGap(const Impl& other, double searchLength) const;
332
333
// sort.cpp
334
void Finish();
335
void SortVerts();
336
void ReindexVerts(const Vec<int>& vertNew2Old, size_t numOldVert);
337
void CompactProps();
338
void GetFaceBoxMorton(Vec<Box>& faceBox, Vec<uint32_t>& faceMorton) const;
339
void SortFaces(Vec<Box>& faceBox, Vec<uint32_t>& faceMorton);
340
void GatherFaces(const Vec<int>& faceNew2Old);
341
void GatherFaces(const Impl& old, const Vec<int>& faceNew2Old);
342
343
// face_op.cpp
344
void Face2Tri(const Vec<int>& faceEdge, const Vec<TriRef>& halfedgeRef,
345
bool allowConvex = false);
346
Polygons Slice(double height) const;
347
Polygons Project() const;
348
349
// edge_op.cpp
350
void CleanupTopology();
351
void SimplifyTopology(int firstNewVert = 0);
352
void RemoveDegenerates(int firstNewVert = 0);
353
void CollapseShortEdges(int firstNewVert = 0);
354
void CollapseColinearEdges(int firstNewVert = 0);
355
void SwapDegenerates(int firstNewVert = 0);
356
void DedupeEdge(int edge);
357
bool CollapseEdge(int edge, std::vector<int>& edges);
358
void RecursiveEdgeSwap(int edge, int& tag, std::vector<int>& visited,
359
std::vector<int>& edgeSwapStack,
360
std::vector<int>& edges);
361
void RemoveIfFolded(int edge);
362
void PairUp(int edge0, int edge1);
363
void UpdateVert(int vert, int startEdge, int endEdge);
364
void FormLoop(int current, int end);
365
void CollapseTri(const ivec3& triEdge);
366
void SplitPinchedVerts();
367
void DedupeEdges();
368
369
// subdivision.cpp
370
int GetNeighbor(int tri) const;
371
ivec4 GetHalfedges(int tri) const;
372
BaryIndices GetIndices(int halfedge) const;
373
void FillRetainedVerts(Vec<Barycentric>& vertBary) const;
374
Vec<Barycentric> Subdivide(std::function<int(vec3, vec4, vec4)>,
375
bool = false);
376
377
// smoothing.cpp
378
bool IsInsideQuad(int halfedge) const;
379
bool IsMarkedInsideQuad(int halfedge) const;
380
vec3 GetNormal(int halfedge, int normalIdx) const;
381
vec4 TangentFromNormal(const vec3& normal, int halfedge) const;
382
std::vector<Smoothness> UpdateSharpenedEdges(
383
const std::vector<Smoothness>&) const;
384
Vec<bool> FlatFaces() const;
385
Vec<int> VertFlatFace(const Vec<bool>&) const;
386
Vec<int> VertHalfedge() const;
387
std::vector<Smoothness> SharpenEdges(double minSharpAngle,
388
double minSmoothness) const;
389
void SharpenTangent(int halfedge, double smoothness);
390
void SetNormals(int normalIdx, double minSharpAngle);
391
void LinearizeFlatTangents();
392
void DistributeTangents(const Vec<bool>& fixedHalfedges);
393
void CreateTangents(int normalIdx);
394
void CreateTangents(std::vector<Smoothness>);
395
void Refine(std::function<int(vec3, vec4, vec4)>, bool = false);
396
397
// quickhull.cpp
398
void Hull(VecView<vec3> vertPos);
399
};
400
401
extern std::mutex dump_lock;
402
std::ostream& operator<<(std::ostream& stream, const Manifold::Impl& impl);
403
} // namespace manifold
404
405