Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/subdiv/catmullclark_patch.h
9918 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "catmullclark_ring.h"
7
#include "bezier_curve.h"
8
9
namespace embree
10
{
11
template<typename Vertex, typename Vertex_t = Vertex>
12
class __aligned(64) CatmullClarkPatchT
13
{
14
public:
15
typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
16
typedef typename CatmullClark1Ring::Type Type;
17
18
array_t<CatmullClark1RingT<Vertex,Vertex_t>,4> ring;
19
20
public:
21
__forceinline CatmullClarkPatchT () {}
22
23
__forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const char* vertices, size_t stride) {
24
init(first_half_edge,vertices,stride);
25
}
26
27
__forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
28
init(first_half_edge,vertices.getPtr(),vertices.getStride());
29
}
30
31
__forceinline void init (const HalfEdge* first_half_edge, const char* vertices, size_t stride)
32
{
33
for (unsigned i=0; i<4; i++)
34
ring[i].init(first_half_edge+i,vertices,stride);
35
36
assert(verify());
37
}
38
39
__forceinline size_t bytes() const {
40
return ring[0].bytes()+ring[1].bytes()+ring[2].bytes()+ring[3].bytes();
41
}
42
43
__forceinline void serialize(void* ptr, size_t& ofs) const
44
{
45
for (size_t i=0; i<4; i++)
46
ring[i].serialize((char*)ptr,ofs);
47
}
48
49
__forceinline void deserialize(void* ptr)
50
{
51
size_t ofs = 0;
52
for (size_t i=0; i<4; i++)
53
ring[i].deserialize((char*)ptr,ofs);
54
}
55
56
__forceinline BBox3fa bounds() const
57
{
58
BBox3fa bounds (ring[0].bounds());
59
for (size_t i=1; i<4; i++)
60
bounds.extend(ring[i].bounds());
61
return bounds;
62
}
63
64
__forceinline Type type() const
65
{
66
const int ty0 = ring[0].type() ^ CatmullClark1Ring::TYPE_CREASES;
67
const int ty1 = ring[1].type() ^ CatmullClark1Ring::TYPE_CREASES;
68
const int ty2 = ring[2].type() ^ CatmullClark1Ring::TYPE_CREASES;
69
const int ty3 = ring[3].type() ^ CatmullClark1Ring::TYPE_CREASES;
70
return (Type) ((ty0 & ty1 & ty2 & ty3) ^ CatmullClark1Ring::TYPE_CREASES);
71
}
72
73
__forceinline bool isFinalResolution(float res) const {
74
return ring[0].isFinalResolution(res) && ring[1].isFinalResolution(res) && ring[2].isFinalResolution(res) && ring[3].isFinalResolution(res);
75
}
76
77
static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
78
const CatmullClark1RingT<Vertex,Vertex_t>& p1,
79
CatmullClark1RingT<Vertex,Vertex_t>& dest0,
80
CatmullClark1RingT<Vertex,Vertex_t>& dest1)
81
{
82
assert(p1.face_valence > 2);
83
dest1.vertex_level = dest0.vertex_level = p0.edge_level;
84
dest1.face_valence = dest0.face_valence = 4;
85
dest1.edge_valence = dest0.edge_valence = 8;
86
dest1.border_index = dest0.border_index = -1;
87
dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
88
dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
89
90
dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
91
dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
92
dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
93
dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
94
dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
95
dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
96
dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
97
dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
98
99
dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
100
dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
101
dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
102
dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
103
104
if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
105
{
106
dest0.eval_start_index = 3;
107
dest1.eval_start_index = 0;
108
dest0.eval_unique_identifier = p0.eval_unique_identifier;
109
dest1.eval_unique_identifier = p0.eval_unique_identifier;
110
}
111
else
112
{
113
dest0.eval_start_index = 1;
114
dest1.eval_start_index = 2;
115
dest0.eval_unique_identifier = p1.eval_unique_identifier;
116
dest1.eval_unique_identifier = p1.eval_unique_identifier;
117
}
118
}
119
120
static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
121
const CatmullClark1RingT<Vertex,Vertex_t> &p1,
122
CatmullClark1RingT<Vertex,Vertex_t> &dest0,
123
CatmullClark1RingT<Vertex,Vertex_t> &dest1)
124
{
125
dest1.vertex_level = dest0.vertex_level = p0.edge_level;
126
dest1.face_valence = dest0.face_valence = 3;
127
dest1.edge_valence = dest0.edge_valence = 6;
128
dest0.border_index = 2;
129
dest1.border_index = 4;
130
dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
131
dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
132
133
dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
134
dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
135
dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
136
dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
137
dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
138
dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
139
140
dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
141
dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
142
dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
143
144
if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
145
{
146
dest0.eval_start_index = 1;
147
dest1.eval_start_index = 2;
148
dest0.eval_unique_identifier = p0.eval_unique_identifier;
149
dest1.eval_unique_identifier = p0.eval_unique_identifier;
150
}
151
else
152
{
153
dest0.eval_start_index = 2;
154
dest1.eval_start_index = 0;
155
dest0.eval_unique_identifier = p1.eval_unique_identifier;
156
dest1.eval_unique_identifier = p1.eval_unique_identifier;
157
}
158
}
159
160
static __forceinline void init_regular(const Vertex_t &center, const Vertex_t center_ring[8], const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
161
{
162
dest.vertex_level = 0.0f;
163
dest.face_valence = 4;
164
dest.edge_valence = 8;
165
dest.border_index = -1;
166
dest.vtx = (Vertex_t)center;
167
dest.vertex_crease_weight = 0.0f;
168
for (size_t i=0; i<8; i++)
169
dest.ring[i] = (Vertex_t)center_ring[(offset+i)%8];
170
for (size_t i=0; i<4; i++)
171
dest.crease_weight[i] = 0.0f;
172
173
dest.eval_start_index = (8-offset)>>1;
174
if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
175
assert( dest.eval_start_index < dest.face_valence );
176
dest.eval_unique_identifier = 0;
177
}
178
179
__noinline void subdivide(array_t<CatmullClarkPatchT,4>& patch) const
180
{
181
ring[0].subdivide(patch[0].ring[0]);
182
ring[1].subdivide(patch[1].ring[1]);
183
ring[2].subdivide(patch[2].ring[2]);
184
ring[3].subdivide(patch[3].ring[3]);
185
186
patch[0].ring[0].edge_level = 0.5f*ring[0].edge_level;
187
patch[0].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
188
patch[0].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
189
patch[0].ring[3].edge_level = 0.5f*ring[3].edge_level;
190
191
patch[1].ring[0].edge_level = 0.5f*ring[0].edge_level;
192
patch[1].ring[1].edge_level = 0.5f*ring[1].edge_level;
193
patch[1].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
194
patch[1].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
195
196
patch[2].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
197
patch[2].ring[1].edge_level = 0.5f*ring[1].edge_level;
198
patch[2].ring[2].edge_level = 0.5f*ring[2].edge_level;
199
patch[2].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
200
201
patch[3].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
202
patch[3].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
203
patch[3].ring[2].edge_level = 0.5f*ring[2].edge_level;
204
patch[3].ring[3].edge_level = 0.5f*ring[3].edge_level;
205
206
const bool regular0 = ring[0].has_last_face() && ring[1].face_valence > 2;
207
if (likely(regular0))
208
init_regular(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
209
else
210
init_border(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
211
212
const bool regular1 = ring[1].has_last_face() && ring[2].face_valence > 2;
213
if (likely(regular1))
214
init_regular(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
215
else
216
init_border(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
217
218
const bool regular2 = ring[2].has_last_face() && ring[3].face_valence > 2;
219
if (likely(regular2))
220
init_regular(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
221
else
222
init_border(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
223
224
const bool regular3 = ring[3].has_last_face() && ring[0].face_valence > 2;
225
if (likely(regular3))
226
init_regular(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
227
else
228
init_border(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
229
230
Vertex_t center = (ring[0].vtx + ring[1].vtx + ring[2].vtx + ring[3].vtx) * 0.25f;
231
232
Vertex_t center_ring[8];
233
center_ring[0] = (Vertex_t)patch[3].ring[3].ring[0];
234
center_ring[7] = (Vertex_t)patch[3].ring[3].vtx;
235
center_ring[6] = (Vertex_t)patch[2].ring[2].ring[0];
236
center_ring[5] = (Vertex_t)patch[2].ring[2].vtx;
237
center_ring[4] = (Vertex_t)patch[1].ring[1].ring[0];
238
center_ring[3] = (Vertex_t)patch[1].ring[1].vtx;
239
center_ring[2] = (Vertex_t)patch[0].ring[0].ring[0];
240
center_ring[1] = (Vertex_t)patch[0].ring[0].vtx;
241
242
init_regular(center,center_ring,0,patch[0].ring[2]);
243
init_regular(center,center_ring,2,patch[1].ring[3]);
244
init_regular(center,center_ring,4,patch[2].ring[0]);
245
init_regular(center,center_ring,6,patch[3].ring[1]);
246
247
assert(patch[0].verify());
248
assert(patch[1].verify());
249
assert(patch[2].verify());
250
assert(patch[3].verify());
251
}
252
253
bool verify() const {
254
return ring[0].hasValidPositions() && ring[1].hasValidPositions() && ring[2].hasValidPositions() && ring[3].hasValidPositions();
255
}
256
257
__forceinline void init( FinalQuad& quad ) const
258
{
259
quad.vtx[0] = (Vertex_t)ring[0].vtx;
260
quad.vtx[1] = (Vertex_t)ring[1].vtx;
261
quad.vtx[2] = (Vertex_t)ring[2].vtx;
262
quad.vtx[3] = (Vertex_t)ring[3].vtx;
263
};
264
265
friend __forceinline embree_ostream operator<<(embree_ostream o, const CatmullClarkPatchT &p)
266
{
267
o << "CatmullClarkPatch { " << embree_endl;
268
for (size_t i=0; i<4; i++)
269
o << "ring" << i << ": " << p.ring[i] << embree_endl;
270
o << "}" << embree_endl;
271
return o;
272
}
273
};
274
275
typedef CatmullClarkPatchT<Vec3fa,Vec3fa_t> CatmullClarkPatch3fa;
276
277
template<typename Vertex, typename Vertex_t = Vertex>
278
class __aligned(64) GeneralCatmullClarkPatchT
279
{
280
public:
281
typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
282
typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
283
typedef BezierCurveT<Vertex> BezierCurve;
284
285
static const unsigned SIZE = MAX_PATCH_VALENCE;
286
DynamicStackArray<GeneralCatmullClark1RingT<Vertex,Vertex_t>,8,SIZE> ring;
287
unsigned N;
288
289
__forceinline GeneralCatmullClarkPatchT ()
290
: N(0) {}
291
292
GeneralCatmullClarkPatchT (const HalfEdge* h, const char* vertices, size_t stride) {
293
init(h,vertices,stride);
294
}
295
296
__forceinline GeneralCatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
297
init(first_half_edge,vertices.getPtr(),vertices.getStride());
298
}
299
300
__forceinline void init (const HalfEdge* h, const char* vertices, size_t stride)
301
{
302
unsigned int i = 0;
303
const HalfEdge* edge = h;
304
do {
305
ring[i].init(edge,vertices,stride);
306
edge = edge->next();
307
i++;
308
} while ((edge != h) && (i < SIZE));
309
N = i;
310
}
311
312
__forceinline unsigned size() const {
313
return N;
314
}
315
316
__forceinline bool isQuadPatch() const {
317
return (N == 4) && ring[0].only_quads && ring[1].only_quads && ring[2].only_quads && ring[3].only_quads;
318
}
319
320
static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
321
const CatmullClark1RingT<Vertex,Vertex_t>& p1,
322
CatmullClark1RingT<Vertex,Vertex_t>& dest0,
323
CatmullClark1RingT<Vertex,Vertex_t>& dest1)
324
{
325
assert(p1.face_valence > 2);
326
dest1.vertex_level = dest0.vertex_level = p0.edge_level;
327
dest1.face_valence = dest0.face_valence = 4;
328
dest1.edge_valence = dest0.edge_valence = 8;
329
dest1.border_index = dest0.border_index = -1;
330
dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
331
dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
332
333
dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
334
dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
335
dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
336
dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
337
dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
338
dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
339
dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
340
dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
341
342
dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
343
dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
344
dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
345
dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
346
347
if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
348
{
349
dest0.eval_start_index = 3;
350
dest1.eval_start_index = 0;
351
dest0.eval_unique_identifier = p0.eval_unique_identifier;
352
dest1.eval_unique_identifier = p0.eval_unique_identifier;
353
}
354
else
355
{
356
dest0.eval_start_index = 1;
357
dest1.eval_start_index = 2;
358
dest0.eval_unique_identifier = p1.eval_unique_identifier;
359
dest1.eval_unique_identifier = p1.eval_unique_identifier;
360
}
361
}
362
363
364
static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
365
const CatmullClark1RingT<Vertex,Vertex_t> &p1,
366
CatmullClark1RingT<Vertex,Vertex_t> &dest0,
367
CatmullClark1RingT<Vertex,Vertex_t> &dest1)
368
{
369
dest1.vertex_level = dest0.vertex_level = p0.edge_level;
370
dest1.face_valence = dest0.face_valence = 3;
371
dest1.edge_valence = dest0.edge_valence = 6;
372
dest0.border_index = 2;
373
dest1.border_index = 4;
374
dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
375
dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
376
377
dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
378
dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
379
dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
380
dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
381
dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
382
dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
383
384
dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
385
dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
386
dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
387
388
if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
389
{
390
dest0.eval_start_index = 1;
391
dest1.eval_start_index = 2;
392
dest0.eval_unique_identifier = p0.eval_unique_identifier;
393
dest1.eval_unique_identifier = p0.eval_unique_identifier;
394
}
395
else
396
{
397
dest0.eval_start_index = 2;
398
dest1.eval_start_index = 0;
399
dest0.eval_unique_identifier = p1.eval_unique_identifier;
400
dest1.eval_unique_identifier = p1.eval_unique_identifier;
401
}
402
}
403
404
static __forceinline void init_regular(const Vertex_t &center, const array_t<Vertex_t,2*SIZE>& center_ring, const float vertex_level, const unsigned int N, const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
405
{
406
assert(N<(MAX_RING_FACE_VALENCE));
407
assert(2*N<(MAX_RING_EDGE_VALENCE));
408
dest.vertex_level = vertex_level;
409
dest.face_valence = N;
410
dest.edge_valence = 2*N;
411
dest.border_index = -1;
412
dest.vtx = (Vertex_t)center;
413
dest.vertex_crease_weight = 0.0f;
414
for (unsigned i=0; i<2*N; i++) {
415
dest.ring[i] = (Vertex_t)center_ring[(2*N+offset+i-1)%(2*N)];
416
assert(isvalid(dest.ring[i]));
417
}
418
for (unsigned i=0; i<N; i++)
419
dest.crease_weight[i] = 0.0f;
420
421
assert(offset <= 2*N);
422
dest.eval_start_index = (2*N-offset)>>1;
423
if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
424
425
assert( dest.eval_start_index < dest.face_valence );
426
dest.eval_unique_identifier = 0;
427
}
428
429
__noinline void subdivide(array_t<CatmullClarkPatch,SIZE>& patch, unsigned& N_o) const
430
{
431
N_o = N;
432
assert( N );
433
for (unsigned i=0; i<N; i++) {
434
unsigned ip1 = (i+1)%N; // FIXME: %
435
ring[i].subdivide(patch[i].ring[0]);
436
patch[i] .ring[0].edge_level = 0.5f*ring[i].edge_level;
437
patch[ip1].ring[3].edge_level = 0.5f*ring[i].edge_level;
438
439
assert( patch[i].ring[0].hasValidPositions() );
440
441
}
442
assert(N < 2*SIZE);
443
Vertex_t center = Vertex_t(0.0f);
444
array_t<Vertex_t,2*SIZE> center_ring;
445
float center_vertex_level = 2.0f; // guarantees that irregular vertices get always isolated also for non-quads
446
447
for (unsigned i=0; i<N; i++)
448
{
449
unsigned ip1 = (i+1)%N; // FIXME: %
450
unsigned im1 = (i+N-1)%N; // FIXME: %
451
bool regular = ring[i].has_last_face() && ring[ip1].face_valence > 2;
452
if (likely(regular)) init_regular(patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
453
else init_border (patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
454
455
assert( patch[i].ring[1].hasValidPositions() );
456
assert( patch[ip1].ring[3].hasValidPositions() );
457
458
float level = 0.25f*(ring[im1].edge_level+ring[ip1].edge_level);
459
patch[i].ring[1].edge_level = patch[ip1].ring[2].edge_level = level;
460
center_vertex_level = max(center_vertex_level,level);
461
462
center += ring[i].vtx;
463
center_ring[2*i+0] = (Vertex_t)patch[i].ring[0].vtx;
464
center_ring[2*i+1] = (Vertex_t)patch[i].ring[0].ring[0];
465
}
466
center /= float(N);
467
468
for (unsigned int i=0; i<N; i++) {
469
init_regular(center,center_ring,center_vertex_level,N,2*i,patch[i].ring[2]);
470
471
assert( patch[i].ring[2].hasValidPositions() );
472
}
473
}
474
475
void init(CatmullClarkPatch& patch) const
476
{
477
assert(size() == 4);
478
ring[0].convert(patch.ring[0]);
479
ring[1].convert(patch.ring[1]);
480
ring[2].convert(patch.ring[2]);
481
ring[3].convert(patch.ring[3]);
482
}
483
484
static void fix_quad_ring_order (array_t<CatmullClarkPatch,GeneralCatmullClarkPatchT::SIZE>& patches)
485
{
486
CatmullClark1Ring patches1ring1 = patches[1].ring[1];
487
patches[1].ring[1] = patches[1].ring[0]; // FIXME: optimize these assignments
488
patches[1].ring[0] = patches[1].ring[3];
489
patches[1].ring[3] = patches[1].ring[2];
490
patches[1].ring[2] = patches1ring1;
491
492
CatmullClark1Ring patches2ring2 = patches[2].ring[2];
493
patches[2].ring[2] = patches[2].ring[0];
494
patches[2].ring[0] = patches2ring2;
495
CatmullClark1Ring patches2ring3 = patches[2].ring[3];
496
patches[2].ring[3] = patches[2].ring[1];
497
patches[2].ring[1] = patches2ring3;
498
499
CatmullClark1Ring patches3ring3 = patches[3].ring[3];
500
patches[3].ring[3] = patches[3].ring[0];
501
patches[3].ring[0] = patches[3].ring[1];
502
patches[3].ring[1] = patches[3].ring[2];
503
patches[3].ring[2] = patches3ring3;
504
}
505
506
__forceinline void getLimitBorder(BezierCurve curves[GeneralCatmullClarkPatchT::SIZE]) const
507
{
508
Vertex P0 = ring[0].getLimitVertex();
509
for (unsigned i=0; i<N; i++)
510
{
511
const unsigned i0 = i, i1 = i+1==N ? 0 : i+1;
512
const Vertex P1 = madd(1.0f/3.0f,ring[i0].getLimitTangent(),P0);
513
const Vertex P3 = ring[i1].getLimitVertex();
514
const Vertex P2 = madd(1.0f/3.0f,ring[i1].getSecondLimitTangent(),P3);
515
new (&curves[i]) BezierCurve(P0,P1,P2,P3);
516
P0 = P3;
517
}
518
}
519
520
__forceinline void getLimitBorder(BezierCurve curves[2], const unsigned subPatch) const
521
{
522
const unsigned i0 = subPatch;
523
const Vertex t0_p = ring[i0].getLimitTangent();
524
const Vertex t0_m = ring[i0].getSecondLimitTangent();
525
526
const unsigned i1 = subPatch+1 == N ? 0 : subPatch+1;
527
const Vertex t1_p = ring[i1].getLimitTangent();
528
const Vertex t1_m = ring[i1].getSecondLimitTangent();
529
530
const unsigned i2 = subPatch == 0 ? N-1 : subPatch-1;
531
const Vertex t2_p = ring[i2].getLimitTangent();
532
const Vertex t2_m = ring[i2].getSecondLimitTangent();
533
534
const Vertex b00 = ring[i0].getLimitVertex();
535
const Vertex b03 = ring[i1].getLimitVertex();
536
const Vertex b33 = ring[i2].getLimitVertex();
537
538
const Vertex b01 = madd(1.0/3.0f,t0_p,b00);
539
const Vertex b11 = madd(1.0/3.0f,t0_m,b00);
540
541
//const Vertex b13 = madd(1.0/3.0f,t1_p,b03);
542
const Vertex b02 = madd(1.0/3.0f,t1_m,b03);
543
544
const Vertex b22 = madd(1.0/3.0f,t2_p,b33);
545
const Vertex b23 = madd(1.0/3.0f,t2_m,b33);
546
547
new (&curves[0]) BezierCurve(b00,b01,b02,b03);
548
new (&curves[1]) BezierCurve(b33,b22,b11,b00);
549
}
550
551
friend __forceinline embree_ostream operator<<(embree_ostream o, const GeneralCatmullClarkPatchT &p)
552
{
553
o << "GeneralCatmullClarkPatch { " << embree_endl;
554
for (unsigned i=0; i<p.N; i++)
555
o << "ring" << i << ": " << p.ring[i] << embree_endl;
556
o << "}" << embree_endl;
557
return o;
558
}
559
};
560
561
typedef GeneralCatmullClarkPatchT<Vec3fa,Vec3fa_t> GeneralCatmullClarkPatch3fa;
562
}
563
564