Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/common/scene_subdiv_mesh.h
9905 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "geometry.h"
7
#include "buffer.h"
8
#include "../subdiv/half_edge.h"
9
#include "../subdiv/tessellation_cache.h"
10
#include "../subdiv/catmullclark_coefficients.h"
11
#include "../subdiv/patch.h"
12
13
namespace embree
14
{
15
struct HoleSet;
16
struct VertexCreaseMap;
17
struct EdgeCreaseMap;
18
19
class SubdivMesh : public Geometry
20
{
21
ALIGNED_CLASS_(16);
22
public:
23
24
typedef HalfEdge::Edge Edge;
25
26
/*! type of this geometry */
27
static const Geometry::GTypeMask geom_type = Geometry::MTY_SUBDIV_MESH;
28
29
/*! structure used to sort half edges using radix sort by their key */
30
struct KeyHalfEdge
31
{
32
KeyHalfEdge() {}
33
34
KeyHalfEdge (uint64_t key, HalfEdge* edge)
35
: key(key), edge(edge) {}
36
37
__forceinline operator uint64_t() const {
38
return key;
39
}
40
41
friend __forceinline bool operator<(const KeyHalfEdge& e0, const KeyHalfEdge& e1) {
42
return e0.key < e1.key;
43
}
44
45
public:
46
uint64_t key;
47
HalfEdge* edge;
48
};
49
50
public:
51
52
/*! subdiv mesh construction */
53
SubdivMesh(Device* device);
54
~SubdivMesh();
55
56
public:
57
void setMask (unsigned mask);
58
void setSubdivisionMode (unsigned int topologyID, RTCSubdivisionMode mode);
59
void setVertexAttributeTopology(unsigned int vertexAttribID, unsigned int topologyID);
60
void setNumTimeSteps (unsigned int numTimeSteps);
61
void setVertexAttributeCount (unsigned int N);
62
void setTopologyCount (unsigned int N);
63
void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
64
void* getBufferData(RTCBufferType type, unsigned int slot, BufferDataPointerType pointerType);
65
void updateBuffer(RTCBufferType type, unsigned int slot);
66
void setTessellationRate(float N);
67
bool verify();
68
void commit();
69
void addElementsToCount (GeometryCounts & counts) const;
70
void setDisplacementFunction (RTCDisplacementFunctionN func);
71
unsigned int getFirstHalfEdge(unsigned int faceID);
72
unsigned int getFace(unsigned int edgeID);
73
unsigned int getNextHalfEdge(unsigned int edgeID);
74
unsigned int getPreviousHalfEdge(unsigned int edgeID);
75
unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID);
76
77
public:
78
79
/*! return the number of faces */
80
size_t numFaces() const {
81
return faceVertices.size();
82
}
83
84
/*! return the number of edges */
85
size_t numEdges() const {
86
return topology[0].vertexIndices.size();
87
}
88
89
/*! return the number of vertices */
90
size_t numVertices() const {
91
return vertices[0].size();
92
}
93
94
/*! calculates the bounds of the i'th subdivision patch at the j'th timestep */
95
__forceinline BBox3fa bounds(size_t i, size_t j = 0) const {
96
return topology[0].getHalfEdge(i)->bounds(vertices[j]);
97
}
98
99
/*! check if the i'th primitive is valid */
100
__forceinline bool valid(size_t i) const {
101
return topology[0].valid(i) && !invalidFace(i);
102
}
103
104
/*! check if the i'th primitive is valid for the j'th time range */
105
__forceinline bool valid(size_t i, size_t j) const {
106
return topology[0].valid(i) && !invalidFace(i,j);
107
}
108
109
/*! prints some statistics */
110
void printStatistics();
111
112
/*! initializes the half edge data structure */
113
void initializeHalfEdgeStructures ();
114
115
public:
116
117
/*! returns the vertex buffer for some time step */
118
__forceinline const BufferView<Vec3fa>& getVertexBuffer( const size_t t = 0 ) const {
119
return vertices[t];
120
}
121
122
/* returns tessellation level of edge */
123
__forceinline float getEdgeLevel(const size_t i) const
124
{
125
if (levels) return clamp(levels[i],1.0f,4096.0f); // FIXME: do we want to limit edge level?
126
else return clamp(tessellationRate,1.0f,4096.0f); // FIXME: do we want to limit edge level?
127
}
128
129
public:
130
RTCDisplacementFunctionN displFunc; //!< displacement function
131
132
/*! all buffers in this section are provided by the application */
133
public:
134
135
/*! the topology contains all data that may differ when
136
* interpolating different user data buffers */
137
struct Topology
138
{
139
public:
140
141
/*! Default topology construction */
142
Topology () : halfEdges(nullptr,0) {}
143
144
/*! Topology initialization */
145
Topology (SubdivMesh* mesh);
146
147
/*! make the class movable */
148
public:
149
Topology (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
150
: mesh(std::move(other.mesh)),
151
vertexIndices(std::move(other.vertexIndices)),
152
subdiv_mode(std::move(other.subdiv_mode)),
153
halfEdges(std::move(other.halfEdges)),
154
halfEdges0(std::move(other.halfEdges0)),
155
halfEdges1(std::move(other.halfEdges1)) {}
156
157
Topology& operator= (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
158
{
159
mesh = std::move(other.mesh);
160
vertexIndices = std::move(other.vertexIndices);
161
subdiv_mode = std::move(other.subdiv_mode);
162
halfEdges = std::move(other.halfEdges);
163
halfEdges0 = std::move(other.halfEdges0);
164
halfEdges1 = std::move(other.halfEdges1);
165
return *this;
166
}
167
168
public:
169
/*! check if the i'th primitive is valid in this topology */
170
__forceinline bool valid(size_t i) const
171
{
172
if (unlikely(subdiv_mode == RTC_SUBDIVISION_MODE_NO_BOUNDARY)) {
173
if (getHalfEdge(i)->faceHasBorder()) return false;
174
}
175
return true;
176
}
177
178
/*! updates the interpolation mode for the topology */
179
void setSubdivisionMode (RTCSubdivisionMode mode);
180
181
/*! marks all buffers as modified */
182
void update ();
183
184
/*! verifies index array */
185
bool verify (size_t numVertices);
186
187
/*! initializes the half edge data structure */
188
void initializeHalfEdgeStructures ();
189
190
private:
191
192
/*! recalculates the half edges */
193
void calculateHalfEdges();
194
195
/*! updates half edges when recalculation is not necessary */
196
void updateHalfEdges();
197
198
/*! user input data */
199
public:
200
201
SubdivMesh* mesh;
202
203
/*! indices of the vertices composing each face */
204
BufferView<unsigned int> vertexIndices;
205
206
/*! subdiv interpolation mode */
207
RTCSubdivisionMode subdiv_mode;
208
209
/*! generated data */
210
public:
211
212
/*! returns the start half edge for face f */
213
__forceinline const HalfEdge* getHalfEdge ( const size_t f ) const {
214
return &halfEdges[mesh->faceStartEdge[f]];
215
}
216
217
/*! Half edge structure, generated by initHalfEdgeStructures */
218
mvector<HalfEdge> halfEdges;
219
220
/*! the following data is only required during construction of the
221
* half edge structure and can be cleared for static scenes */
222
private:
223
224
/*! two arrays used to sort the half edges */
225
std::vector<KeyHalfEdge> halfEdges0;
226
std::vector<KeyHalfEdge> halfEdges1;
227
};
228
229
/*! returns the start half edge for topology t and face f */
230
__forceinline const HalfEdge* getHalfEdge ( const size_t t , const size_t f ) const {
231
return topology[t].getHalfEdge(f);
232
}
233
234
/*! buffer containing the number of vertices for each face */
235
BufferView<unsigned int> faceVertices;
236
237
/*! array of topologies */
238
vector<Topology> topology;
239
240
/*! vertex buffer (one buffer for each time step) */
241
vector<BufferView<Vec3fa>> vertices;
242
243
/*! user data buffers */
244
vector<RawBufferView> vertexAttribs;
245
246
/*! edge crease buffer containing edges (pairs of vertices) that carry edge crease weights */
247
BufferView<Edge> edge_creases;
248
249
/*! edge crease weights for each edge of the edge_creases buffer */
250
BufferView<float> edge_crease_weights;
251
252
/*! vertex crease buffer containing all vertices that carry vertex crease weights */
253
BufferView<unsigned int> vertex_creases;
254
255
/*! vertex crease weights for each vertex of the vertex_creases buffer */
256
BufferView<float> vertex_crease_weights;
257
258
/*! subdivision level for each half edge of the vertexIndices buffer */
259
BufferView<float> levels;
260
float tessellationRate; // constant rate that is used when levels is not set
261
262
/*! buffer that marks specific faces as holes */
263
BufferView<unsigned> holes;
264
265
/*! all data in this section is generated by initializeHalfEdgeStructures function */
266
private:
267
268
/*! number of half edges used by faces */
269
size_t numHalfEdges;
270
271
/*! fast lookup table to find the first half edge for some face */
272
mvector<uint32_t> faceStartEdge;
273
274
/*! fast lookup table to find the face for some half edge */
275
mvector<uint32_t> halfEdgeFace;
276
277
/*! set with all holes */
278
std::unique_ptr<HoleSet> holeSet;
279
280
/*! fast lookup table to detect invalid faces */
281
mvector<char> invalid_face;
282
283
/*! test if face i is invalid in timestep j */
284
__forceinline char& invalidFace(size_t i, size_t j = 0) { return invalid_face[i*numTimeSteps+j]; }
285
__forceinline const char& invalidFace(size_t i, size_t j = 0) const { return invalid_face[i*numTimeSteps+j]; }
286
287
/*! interpolation cache */
288
public:
289
static __forceinline size_t numInterpolationSlots4(size_t stride) { return (stride+15)/16; }
290
static __forceinline size_t numInterpolationSlots8(size_t stride) { return (stride+31)/32; }
291
static __forceinline size_t interpolationSlot(size_t prim, size_t slot, size_t stride) {
292
const size_t slots = numInterpolationSlots4(stride);
293
assert(slot < slots);
294
return slots*prim+slot;
295
}
296
std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_buffer_tags;
297
std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_attrib_buffer_tags;
298
std::vector<Patch3fa::Ref> patch_eval_trees;
299
300
/*! the following data is only required during construction of the
301
* half edge structure and can be cleared for static scenes */
302
private:
303
304
/*! map with all vertex creases */
305
std::unique_ptr<VertexCreaseMap> vertexCreaseMap;
306
307
/*! map with all edge creases */
308
std::unique_ptr<EdgeCreaseMap> edgeCreaseMap;
309
310
protected:
311
312
/*! counts number of geometry commits */
313
size_t commitCounter;
314
};
315
316
namespace isa
317
{
318
struct SubdivMeshISA : public SubdivMesh
319
{
320
SubdivMeshISA (Device* device)
321
: SubdivMesh(device) {}
322
323
void interpolate(const RTCInterpolateArguments* const args);
324
void interpolateN(const RTCInterpolateNArguments* const args);
325
};
326
}
327
328
DECLARE_ISA_FUNCTION(SubdivMesh*, createSubdivMesh, Device*);
329
};
330
331