Blender V4.3
CCGSubSurf_legacy.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_sys_types.h" /* for intptr_t support */
10#include "MEM_guardedalloc.h"
11
12#include "BLI_task.h"
13#include "BLI_utildefines.h" /* for BLI_assert */
14
15#include "CCGSubSurf.h"
16#include "CCGSubSurf_intern.h"
17
18#define FACE_calcIFNo(f, lvl, S, x, y, no) \
19 _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
20
21/* TODO(sergey): Deduplicate the following functions/ */
22static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize)
23{
24 int levelBase = ccg_edgebase(lvl);
25 if (v == e->v0) {
26 return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
27 }
28 return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)];
29}
30/* *************************************************** */
31
32static int _edge_isBoundary(const CCGEdge *e)
33{
34 return e->numFaces < 2;
35}
36
37static bool _vert_isBoundary(const CCGVert *v)
38{
39 for (int i = 0; i < v->numEdges; i++) {
40 if (_edge_isBoundary(v->edges[i])) {
41 return true;
42 }
43 }
44 return false;
45}
46
48{
49 if (vQ == e->v0) {
50 return e->v1;
51 }
52
53 return e->v0;
54}
55
56static float *_face_getIFNoEdge(CCGFace *f,
57 CCGEdge *e,
58 int f_ed_idx,
59 int lvl,
60 int eX,
61 int eY,
62 int levels,
63 int dataSize,
64 int normalDataOffset)
65{
66 return (float *)((byte *)ccg_face_getIFCoEdge(f, e, f_ed_idx, lvl, eX, eY, levels, dataSize) +
67 normalDataOffset);
68}
69
70static void _face_calcIFNo(
71 CCGFace *f, int lvl, int S, int x, int y, float no[3], int levels, int dataSize)
72{
73 const float *a = static_cast<float *>(
74 ccg_face_getIFCo(f, lvl, S, x + 0, y + 0, levels, dataSize));
75 const float *b = static_cast<float *>(
76 ccg_face_getIFCo(f, lvl, S, x + 1, y + 0, levels, dataSize));
77 const float *c = static_cast<float *>(
78 ccg_face_getIFCo(f, lvl, S, x + 1, y + 1, levels, dataSize));
79 const float *d = static_cast<float *>(
80 ccg_face_getIFCo(f, lvl, S, x + 0, y + 1, levels, dataSize));
81 const float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
82 const float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
83
84 no[0] = b_dY * a_cZ - b_dZ * a_cY;
85 no[1] = b_dZ * a_cX - b_dX * a_cZ;
86 no[2] = b_dX * a_cY - b_dY * a_cX;
87
88 Normalize(no);
89}
90
91static int VERT_seam(const CCGVert *v)
92{
93 return ((v->flags & Vert_eSeam) != 0);
94}
95
96static float EDGE_getSharpness(CCGEdge *e, int lvl)
97{
98 if (!lvl) {
99 return e->crease;
100 }
101 if (!e->crease) {
102 return 0.0f;
103 }
104 if (e->crease - lvl < 0.0f) {
105 return 0.0f;
106 }
107 return e->crease - lvl;
108}
109
121
123 void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict /*tls*/)
124{
125 CCGSubSurfCalcSubdivData *data = static_cast<CCGSubSurfCalcSubdivData *>(userdata);
126
127 CCGSubSurf *ss = data->ss;
128 CCGFace *f = data->effectedF[ptrIdx];
129
130 const int subdivLevels = ss->subdivLevels;
131 const int lvl = ss->subdivLevels;
132 const int gridSize = ccg_gridsize(lvl);
133 const int normalDataOffset = ss->normalDataOffset;
134 const int vertDataSize = ss->meshIFC.vertDataSize;
135
136 int S, x, y;
137 float no[3];
138
139 for (S = 0; S < f->numVerts; S++) {
140 for (y = 0; y < gridSize - 1; y++) {
141 for (x = 0; x < gridSize - 1; x++) {
142 NormZero(FACE_getIFNo(f, lvl, S, x, y));
143 }
144 }
145
146 if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) {
147 for (x = 0; x < gridSize - 1; x++) {
148 NormZero(FACE_getIFNo(f, lvl, S, x, gridSize - 1));
149 }
150 }
151 if (FACE_getEdges(f)[S]->flags & Edge_eEffected) {
152 for (y = 0; y < gridSize - 1; y++) {
153 NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, y));
154 }
155 }
156 if (FACE_getVerts(f)[S]->flags & Vert_eEffected) {
157 NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, gridSize - 1));
158 }
159 }
160
161 for (S = 0; S < f->numVerts; S++) {
162 int yLimit = !(FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected);
163 int xLimit = !(FACE_getEdges(f)[S]->flags & Edge_eEffected);
164 int yLimitNext = xLimit;
165 int xLimitPrev = yLimit;
166
167 for (y = 0; y < gridSize - 1; y++) {
168 for (x = 0; x < gridSize - 1; x++) {
169 int xPlusOk = (!xLimit || x < gridSize - 2);
170 int yPlusOk = (!yLimit || y < gridSize - 2);
171
172 FACE_calcIFNo(f, lvl, S, x, y, no);
173
174 NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 0), no);
175 if (xPlusOk) {
176 NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 0), no);
177 }
178 if (yPlusOk) {
179 NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 1), no);
180 }
181 if (xPlusOk && yPlusOk) {
182 if (x < gridSize - 2 || y < gridSize - 2 || FACE_getVerts(f)[S]->flags & Vert_eEffected)
183 {
184 NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 1), no);
185 }
186 }
187
188 if (x == 0 && y == 0) {
189 int K;
190
191 if (!yLimitNext || 1 < gridSize - 1) {
192 NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, 1), no);
193 }
194 if (!xLimitPrev || 1 < gridSize - 1) {
195 NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, 1, 0), no);
196 }
197
198 for (K = 0; K < f->numVerts; K++) {
199 if (K != S) {
200 NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
201 }
202 }
203 }
204 else if (y == 0) {
205 NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x), no);
206 if (!yLimitNext || x < gridSize - 2) {
207 NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x + 1), no);
208 }
209 }
210 else if (x == 0) {
211 NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y, 0), no);
212 if (!xLimitPrev || y < gridSize - 2) {
213 NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y + 1, 0), no);
214 }
215 }
216 }
217 }
218 }
219}
220
222 void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict /*tls*/)
223{
224 CCGSubSurfCalcSubdivData *data = static_cast<CCGSubSurfCalcSubdivData *>(userdata);
225
226 CCGSubSurf *ss = data->ss;
227 CCGFace *f = data->effectedF[ptrIdx];
228
229 const int subdivLevels = ss->subdivLevels;
230 const int lvl = ss->subdivLevels;
231 const int gridSize = ccg_gridsize(lvl);
232 const int normalDataOffset = ss->normalDataOffset;
233 const int vertDataSize = ss->meshIFC.vertDataSize;
234
235 int S, x, y;
236
237 for (S = 0; S < f->numVerts; S++) {
238 NormCopy(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, gridSize - 1),
239 FACE_getIFNo(f, lvl, S, gridSize - 1, 0));
240 }
241
242 for (S = 0; S < f->numVerts; S++) {
243 for (y = 0; y < gridSize; y++) {
244 for (x = 0; x < gridSize; x++) {
245 float *no = FACE_getIFNo(f, lvl, S, x, y);
246 Normalize(no);
247 }
248 }
249
250 VertDataCopy((float *)((byte *)FACE_getCenterData(f) + normalDataOffset),
251 FACE_getIFNo(f, lvl, S, 0, 0),
252 ss);
253
254 for (x = 1; x < gridSize - 1; x++) {
255 NormCopy(FACE_getIENo(f, lvl, S, x), FACE_getIFNo(f, lvl, S, x, 0));
256 }
257 }
258}
259
261 void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict /*tls*/)
262{
263 CCGSubSurfCalcSubdivData *data = static_cast<CCGSubSurfCalcSubdivData *>(userdata);
264
265 CCGSubSurf *ss = data->ss;
266 CCGEdge *e = data->effectedE[ptrIdx];
267
268 const int subdivLevels = ss->subdivLevels;
269 const int lvl = ss->subdivLevels;
270 const int edgeSize = ccg_edgesize(lvl);
271 const int normalDataOffset = ss->normalDataOffset;
272 const int vertDataSize = ss->meshIFC.vertDataSize;
273
274 if (e->numFaces) {
275 CCGFace *fLast = e->faces[e->numFaces - 1];
276 int x, i;
277
278 for (i = 0; i < e->numFaces - 1; i++) {
279 CCGFace *f = e->faces[i];
280 const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
281 const int f_ed_idx_last = ccg_face_getEdgeIndex(fLast, e);
282
283 for (x = 1; x < edgeSize - 1; x++) {
284 NormAdd(
286 fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
288 f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
289 }
290 }
291
292 for (i = 0; i < e->numFaces - 1; i++) {
293 CCGFace *f = e->faces[i];
294 const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
295 const int f_ed_idx_last = ccg_face_getEdgeIndex(fLast, e);
296
297 for (x = 1; x < edgeSize - 1; x++) {
298 NormCopy(
300 f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
302 fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
303 }
304 }
305 }
306}
307
309 CCGVert **effectedV,
310 CCGEdge **effectedE,
311 CCGFace **effectedF,
312 int numEffectedV,
313 int numEffectedE,
314 int numEffectedF)
315{
316 int i, ptrIdx;
317 const int subdivLevels = ss->subdivLevels;
318 const int lvl = ss->subdivLevels;
319 const int edgeSize = ccg_edgesize(lvl);
320 const int gridSize = ccg_gridsize(lvl);
321 const int normalDataOffset = ss->normalDataOffset;
322 const int vertDataSize = ss->meshIFC.vertDataSize;
323
325 data.ss = ss;
326 data.effectedV = effectedV;
327 data.effectedE = effectedE;
328 data.effectedF = effectedF;
329 data.numEffectedV = numEffectedV;
330 data.numEffectedE = numEffectedE;
331 data.numEffectedF = numEffectedF;
332
333 {
334 TaskParallelSettings settings;
336 settings.min_iter_per_thread = CCG_TASK_LIMIT;
338 0, numEffectedF, &data, ccgSubSurf__calcVertNormals_faces_accumulate_cb, &settings);
339 }
340
341 /* XXX can I reduce the number of normalization calls here? */
342 for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
343 CCGVert *v = (CCGVert *)effectedV[ptrIdx];
344 float *no = VERT_getNo(v, lvl);
345
346 NormZero(no);
347
348 for (i = 0; i < v->numFaces; i++) {
349 CCGFace *f = v->faces[i];
350 NormAdd(no, FACE_getIFNo(f, lvl, ccg_face_getVertIndex(f, v), gridSize - 1, gridSize - 1));
351 }
352
353 if (UNLIKELY(v->numFaces == 0)) {
354 NormCopy(no, VERT_getCo(v, lvl));
355 }
356
357 Normalize(no);
358
359 for (i = 0; i < v->numFaces; i++) {
360 CCGFace *f = v->faces[i];
361 NormCopy(FACE_getIFNo(f, lvl, ccg_face_getVertIndex(f, v), gridSize - 1, gridSize - 1), no);
362 }
363 }
364
365 {
366 TaskParallelSettings settings;
368 settings.min_iter_per_thread = CCG_TASK_LIMIT;
370 0, numEffectedE, &data, ccgSubSurf__calcVertNormals_edges_accumulate_cb, &settings);
371 }
372
373 {
374 TaskParallelSettings settings;
376 settings.min_iter_per_thread = CCG_TASK_LIMIT;
378 0, numEffectedF, &data, ccgSubSurf__calcVertNormals_faces_finalize_cb, &settings);
379 }
380
381 for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
382 CCGEdge *e = (CCGEdge *)effectedE[ptrIdx];
383
384 if (e->numFaces) {
385 CCGFace *f = e->faces[0];
386 int x;
387 const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
388
389 for (x = 0; x < edgeSize; x++) {
390 NormCopy(EDGE_getNo(e, lvl, x),
392 f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
393 }
394 }
395 else {
396 /* set to zero here otherwise the normals are uninitialized memory
397 * render: tests/animation/knight.blend with valgrind.
398 * we could be more clever and interpolate vertex normals but these are
399 * most likely not used so just zero out. */
400 int x;
401
402 for (x = 0; x < edgeSize; x++) {
403 float *no = EDGE_getNo(e, lvl, x);
404 NormCopy(no, EDGE_getCo(e, lvl, x));
405 Normalize(no);
406 }
407 }
408 }
409}
410
412 void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict /*tls*/)
413{
414 CCGSubSurfCalcSubdivData *data = static_cast<CCGSubSurfCalcSubdivData *>(userdata);
415
416 CCGSubSurf *ss = data->ss;
417 CCGFace *f = data->effectedF[ptrIdx];
418
419 const int subdivLevels = ss->subdivLevels;
420 const int curLvl = data->curLvl;
421 const int nextLvl = curLvl + 1;
422 const int gridSize = ccg_gridsize(curLvl);
423 const int vertDataSize = ss->meshIFC.vertDataSize;
424
425 int S, x, y;
426
427 /* interior face midpoints
428 * - old interior face points
429 */
430 for (S = 0; S < f->numVerts; S++) {
431 for (y = 0; y < gridSize - 1; y++) {
432 for (x = 0; x < gridSize - 1; x++) {
433 int fx = 1 + 2 * x;
434 int fy = 1 + 2 * y;
435 const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y + 0);
436 const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y + 0);
437 const float *co2 = FACE_getIFCo(f, curLvl, S, x + 1, y + 1);
438 const float *co3 = FACE_getIFCo(f, curLvl, S, x + 0, y + 1);
439 float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
440
441 VertDataAvg4(co, co0, co1, co2, co3, ss);
442 }
443 }
444 }
445
446 /* interior edge midpoints
447 * - old interior edge points
448 * - new interior face midpoints
449 */
450 for (S = 0; S < f->numVerts; S++) {
451 for (x = 0; x < gridSize - 1; x++) {
452 int fx = x * 2 + 1;
453 const float *co0 = FACE_getIECo(f, curLvl, S, x + 0);
454 const float *co1 = FACE_getIECo(f, curLvl, S, x + 1);
455 const float *co2 = FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx);
456 const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
457 float *co = FACE_getIECo(f, nextLvl, S, fx);
458
459 VertDataAvg4(co, co0, co1, co2, co3, ss);
460 }
461
462 /* interior face interior edge midpoints
463 * - old interior face points
464 * - new interior face midpoints
465 */
466
467 /* vertical */
468 for (x = 1; x < gridSize - 1; x++) {
469 for (y = 0; y < gridSize - 1; y++) {
470 int fx = x * 2;
471 int fy = y * 2 + 1;
472 const float *co0 = FACE_getIFCo(f, curLvl, S, x, y + 0);
473 const float *co1 = FACE_getIFCo(f, curLvl, S, x, y + 1);
474 const float *co2 = FACE_getIFCo(f, nextLvl, S, fx - 1, fy);
475 const float *co3 = FACE_getIFCo(f, nextLvl, S, fx + 1, fy);
476 float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
477
478 VertDataAvg4(co, co0, co1, co2, co3, ss);
479 }
480 }
481
482 /* horizontal */
483 for (y = 1; y < gridSize - 1; y++) {
484 for (x = 0; x < gridSize - 1; x++) {
485 int fx = x * 2 + 1;
486 int fy = y * 2;
487 const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y);
488 const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y);
489 const float *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy - 1);
490 const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy + 1);
491 float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
492
493 VertDataAvg4(co, co0, co1, co2, co3, ss);
494 }
495 }
496 }
497}
498
500 void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict /*tls*/)
501{
502 CCGSubSurfCalcSubdivData *data = static_cast<CCGSubSurfCalcSubdivData *>(userdata);
503
504 CCGSubSurf *ss = data->ss;
505 CCGFace *f = data->effectedF[ptrIdx];
506
507 const int subdivLevels = ss->subdivLevels;
508 const int curLvl = data->curLvl;
509 const int nextLvl = curLvl + 1;
510 const int gridSize = ccg_gridsize(curLvl);
511 const int vertDataSize = ss->meshIFC.vertDataSize;
512
513 float *q_thread = static_cast<float *>(alloca(vertDataSize));
514 float *r_thread = static_cast<float *>(alloca(vertDataSize));
515
516 int S, x, y;
517
518 /* interior center point shift
519 * - old face center point (shifting)
520 * - old interior edge points
521 * - new interior face midpoints
522 */
523 VertDataZero(q_thread, ss);
524 for (S = 0; S < f->numVerts; S++) {
525 VertDataAdd(q_thread, FACE_getIFCo(f, nextLvl, S, 1, 1), ss);
526 }
527 VertDataMulN(q_thread, 1.0f / f->numVerts, ss);
528 VertDataZero(r_thread, ss);
529 for (S = 0; S < f->numVerts; S++) {
530 VertDataAdd(r_thread, FACE_getIECo(f, curLvl, S, 1), ss);
531 }
532 VertDataMulN(r_thread, 1.0f / f->numVerts, ss);
533
534 VertDataMulN((float *)FACE_getCenterData(f), f->numVerts - 2.0f, ss);
535 VertDataAdd((float *)FACE_getCenterData(f), q_thread, ss);
536 VertDataAdd((float *)FACE_getCenterData(f), r_thread, ss);
537 VertDataMulN((float *)FACE_getCenterData(f), 1.0f / f->numVerts, ss);
538
539 for (S = 0; S < f->numVerts; S++) {
540 /* interior face shift
541 * - old interior face point (shifting)
542 * - new interior edge midpoints
543 * - new interior face midpoints
544 */
545 for (x = 1; x < gridSize - 1; x++) {
546 for (y = 1; y < gridSize - 1; y++) {
547 int fx = x * 2;
548 int fy = y * 2;
549 const float *co = FACE_getIFCo(f, curLvl, S, x, y);
550 float *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
551
552 VertDataAvg4(q_thread,
553 FACE_getIFCo(f, nextLvl, S, fx - 1, fy - 1),
554 FACE_getIFCo(f, nextLvl, S, fx + 1, fy - 1),
555 FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 1),
556 FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 1),
557 ss);
558
559 VertDataAvg4(r_thread,
560 FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 0),
561 FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 0),
562 FACE_getIFCo(f, nextLvl, S, fx + 0, fy - 1),
563 FACE_getIFCo(f, nextLvl, S, fx + 0, fy + 1),
564 ss);
565
566 VertDataCopy(nCo, co, ss);
567 VertDataSub(nCo, q_thread, ss);
568 VertDataMulN(nCo, 0.25f, ss);
569 VertDataAdd(nCo, r_thread, ss);
570 }
571 }
572
573 /* interior edge interior shift
574 * - old interior edge point (shifting)
575 * - new interior edge midpoints
576 * - new interior face midpoints
577 */
578 for (x = 1; x < gridSize - 1; x++) {
579 int fx = x * 2;
580 const float *co = FACE_getIECo(f, curLvl, S, x);
581 float *nCo = FACE_getIECo(f, nextLvl, S, fx);
582
583 VertDataAvg4(q_thread,
584 FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx - 1),
585 FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx + 1),
586 FACE_getIFCo(f, nextLvl, S, fx + 1, +1),
587 FACE_getIFCo(f, nextLvl, S, fx - 1, +1),
588 ss);
589
590 VertDataAvg4(r_thread,
591 FACE_getIECo(f, nextLvl, S, fx - 1),
592 FACE_getIECo(f, nextLvl, S, fx + 1),
593 FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx),
594 FACE_getIFCo(f, nextLvl, S, fx, 1),
595 ss);
596
597 VertDataCopy(nCo, co, ss);
598 VertDataSub(nCo, q_thread, ss);
599 VertDataMulN(nCo, 0.25f, ss);
600 VertDataAdd(nCo, r_thread, ss);
601 }
602 }
603}
604
606 void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict /*tls*/)
607{
608 CCGSubSurfCalcSubdivData *data = static_cast<CCGSubSurfCalcSubdivData *>(userdata);
609
610 CCGSubSurf *ss = data->ss;
611 CCGFace *f = data->effectedF[ptrIdx];
612
613 const int subdivLevels = ss->subdivLevels;
614 const int nextLvl = data->curLvl + 1;
615 const int gridSize = ccg_gridsize(nextLvl);
616 const int cornerIdx = gridSize - 1;
617 const int vertDataSize = ss->meshIFC.vertDataSize;
618
619 int S, x;
620
621 for (S = 0; S < f->numVerts; S++) {
622 CCGEdge *e = FACE_getEdges(f)[S];
623 CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
624
625 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
626 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
627 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx),
628 VERT_getCo(FACE_getVerts(f)[S], nextLvl),
629 ss);
630 VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx),
631 EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx),
632 ss);
633 for (x = 1; x < gridSize - 1; x++) {
634 float *co = FACE_getIECo(f, nextLvl, S, x);
635 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co, ss);
636 VertDataCopy(FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 0, x), co, ss);
637 }
638 for (x = 0; x < gridSize - 1; x++) {
639 int eI = gridSize - 1 - x;
640 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x),
641 static_cast<const float *>(
642 _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize)),
643 ss);
644 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx),
645 static_cast<const float *>(
646 _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize)),
647 ss);
648 }
649 }
650}
651
653 CCGVert **effectedV,
654 CCGEdge **effectedE,
655 CCGFace **effectedF,
656 const int numEffectedV,
657 const int numEffectedE,
658 const int numEffectedF,
659 const int curLvl)
660{
661 const int subdivLevels = ss->subdivLevels;
662 const int nextLvl = curLvl + 1;
663 int edgeSize = ccg_edgesize(curLvl);
664 int ptrIdx, i;
665 const int vertDataSize = ss->meshIFC.vertDataSize;
666 float *q = static_cast<float *>(ss->q), *r = static_cast<float *>(ss->r);
667
669 data.ss = ss;
670 data.effectedV = effectedV;
671 data.effectedE = effectedE;
672 data.effectedF = effectedF;
673 data.numEffectedV = numEffectedV;
674 data.numEffectedE = numEffectedE;
675 data.numEffectedF = numEffectedF;
676 data.curLvl = curLvl;
677
678 {
679 TaskParallelSettings settings;
681 settings.min_iter_per_thread = CCG_TASK_LIMIT;
683 numEffectedF,
684 &data,
686 &settings);
687 }
688
689 /* exterior edge midpoints
690 * - old exterior edge points
691 * - new interior face midpoints
692 */
693 /* Not worth parallelizing. */
694 for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
695 CCGEdge *e = (CCGEdge *)effectedE[ptrIdx];
696 float sharpness = EDGE_getSharpness(e, curLvl);
697 int x, j;
698
699 if (_edge_isBoundary(e) || sharpness > 1.0f) {
700 for (x = 0; x < edgeSize - 1; x++) {
701 int fx = x * 2 + 1;
702 const float *co0 = EDGE_getCo(e, curLvl, x + 0);
703 const float *co1 = EDGE_getCo(e, curLvl, x + 1);
704 float *co = EDGE_getCo(e, nextLvl, fx);
705
706 VertDataCopy(co, co0, ss);
707 VertDataAdd(co, co1, ss);
708 VertDataMulN(co, 0.5f, ss);
709 }
710 }
711 else {
712 for (x = 0; x < edgeSize - 1; x++) {
713 int fx = x * 2 + 1;
714 const float *co0 = EDGE_getCo(e, curLvl, x + 0);
715 const float *co1 = EDGE_getCo(e, curLvl, x + 1);
716 float *co = EDGE_getCo(e, nextLvl, fx);
717 int numFaces = 0;
718
719 VertDataCopy(q, co0, ss);
720 VertDataAdd(q, co1, ss);
721
722 for (j = 0; j < e->numFaces; j++) {
723 CCGFace *f = e->faces[j];
724 const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
725 VertDataAdd(q,
726 static_cast<const float *>(ccg_face_getIFCoEdge(
727 f, e, f_ed_idx, nextLvl, fx, 1, subdivLevels, vertDataSize)),
728 ss);
729 numFaces++;
730 }
731
732 VertDataMulN(q, 1.0f / (2.0f + numFaces), ss);
733
734 VertDataCopy(r, co0, ss);
735 VertDataAdd(r, co1, ss);
736 VertDataMulN(r, 0.5f, ss);
737
738 VertDataCopy(co, q, ss);
739 VertDataSub(r, q, ss);
740 VertDataMulN(r, sharpness, ss);
741 VertDataAdd(co, r, ss);
742 }
743 }
744 }
745
746 /* exterior vertex shift
747 * - old vertex points (shifting)
748 * - old exterior edge points
749 * - new interior face midpoints
750 */
751 /* Not worth parallelizing. */
752 for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
753 CCGVert *v = (CCGVert *)effectedV[ptrIdx];
754 const float *co = VERT_getCo(v, curLvl);
755 float *nCo = VERT_getCo(v, nextLvl);
756 int sharpCount = 0, allSharp = 1;
757 float avgSharpness = 0.0;
758 int j, seam = VERT_seam(v), seamEdges = 0;
759
760 for (j = 0; j < v->numEdges; j++) {
761 CCGEdge *e = v->edges[j];
762 float sharpness = EDGE_getSharpness(e, curLvl);
763
764 if (seam && _edge_isBoundary(e)) {
765 seamEdges++;
766 }
767
768 if (sharpness != 0.0f) {
769 sharpCount++;
770 avgSharpness += sharpness;
771 }
772 else {
773 allSharp = 0;
774 }
775 }
776
777 if (sharpCount) {
778 avgSharpness /= sharpCount;
779 if (avgSharpness > 1.0f) {
780 avgSharpness = 1.0f;
781 }
782 }
783
784 if (seamEdges < 2 || seamEdges != v->numEdges) {
785 seam = 0;
786 }
787
788 if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
789 VertDataCopy(nCo, co, ss);
790 }
791 else if (_vert_isBoundary(v)) {
792 int numBoundary = 0;
793
794 VertDataZero(r, ss);
795 for (j = 0; j < v->numEdges; j++) {
796 CCGEdge *e = v->edges[j];
797 if (_edge_isBoundary(e)) {
799 r, static_cast<const float *>(_edge_getCoVert(e, v, curLvl, 1, vertDataSize)), ss);
800 numBoundary++;
801 }
802 }
803
804 VertDataCopy(nCo, co, ss);
805 VertDataMulN(nCo, 0.75f, ss);
806 VertDataMulN(r, 0.25f / numBoundary, ss);
807 VertDataAdd(nCo, r, ss);
808 }
809 else {
810 const int cornerIdx = (1 + (1 << (curLvl))) - 2;
811 int numEdges = 0, numFaces = 0;
812
813 VertDataZero(q, ss);
814 for (j = 0; j < v->numFaces; j++) {
815 CCGFace *f = v->faces[j];
817 q, FACE_getIFCo(f, nextLvl, ccg_face_getVertIndex(f, v), cornerIdx, cornerIdx), ss);
818 numFaces++;
819 }
820 VertDataMulN(q, 1.0f / numFaces, ss);
821 VertDataZero(r, ss);
822 for (j = 0; j < v->numEdges; j++) {
823 CCGEdge *e = v->edges[j];
825 r, static_cast<const float *>(_edge_getCoVert(e, v, curLvl, 1, vertDataSize)), ss);
826 numEdges++;
827 }
828 VertDataMulN(r, 1.0f / numEdges, ss);
829
830 VertDataCopy(nCo, co, ss);
831 VertDataMulN(nCo, numEdges - 2.0f, ss);
832 VertDataAdd(nCo, q, ss);
833 VertDataAdd(nCo, r, ss);
834 VertDataMulN(nCo, 1.0f / numEdges, ss);
835 }
836
837 if ((sharpCount > 1 && v->numFaces) || seam) {
838 VertDataZero(q, ss);
839
840 if (seam) {
841 avgSharpness = 1.0f;
842 sharpCount = seamEdges;
843 allSharp = 1;
844 }
845
846 for (j = 0; j < v->numEdges; j++) {
847 CCGEdge *e = v->edges[j];
848 float sharpness = EDGE_getSharpness(e, curLvl);
849
850 if (seam) {
851 if (_edge_isBoundary(e)) {
853 q, static_cast<const float *>(_edge_getCoVert(e, v, curLvl, 1, vertDataSize)), ss);
854 }
855 }
856 else if (sharpness != 0.0f) {
858 q, static_cast<const float *>(_edge_getCoVert(e, v, curLvl, 1, vertDataSize)), ss);
859 }
860 }
861
862 VertDataMulN(q, float(1) / sharpCount, ss);
863
864 if (sharpCount != 2 || allSharp) {
865 /* q = q + (co - q) * avgSharpness */
866 VertDataCopy(r, co, ss);
867 VertDataSub(r, q, ss);
868 VertDataMulN(r, avgSharpness, ss);
869 VertDataAdd(q, r, ss);
870 }
871
872 /* r = co * 0.75 + q * 0.25 */
873 VertDataCopy(r, co, ss);
874 VertDataMulN(r, 0.75f, ss);
875 VertDataMulN(q, 0.25f, ss);
876 VertDataAdd(r, q, ss);
877
878 /* nCo = nCo + (r - nCo) * avgSharpness */
879 VertDataSub(r, nCo, ss);
880 VertDataMulN(r, avgSharpness, ss);
881 VertDataAdd(nCo, r, ss);
882 }
883 }
884
885 /* exterior edge interior shift
886 * - old exterior edge midpoints (shifting)
887 * - old exterior edge midpoints
888 * - new interior face midpoints
889 */
890 /* Not worth parallelizing. */
891 for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
892 CCGEdge *e = (CCGEdge *)effectedE[ptrIdx];
893 float sharpness = EDGE_getSharpness(e, curLvl);
894 int sharpCount = 0;
895 float avgSharpness = 0.0;
896 int x, j;
897
898 if (sharpness != 0.0f) {
899 sharpCount = 2;
900 avgSharpness += sharpness;
901
902 if (avgSharpness > 1.0f) {
903 avgSharpness = 1.0f;
904 }
905 }
906 else {
907 sharpCount = 0;
908 avgSharpness = 0;
909 }
910
911 if (_edge_isBoundary(e)) {
912 for (x = 1; x < edgeSize - 1; x++) {
913 int fx = x * 2;
914 const float *co = EDGE_getCo(e, curLvl, x);
915 float *nCo = EDGE_getCo(e, nextLvl, fx);
916
917 /* Average previous level's endpoints */
918 VertDataCopy(r, EDGE_getCo(e, curLvl, x - 1), ss);
919 VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
920 VertDataMulN(r, 0.5f, ss);
921
922 /* nCo = nCo * 0.75 + r * 0.25 */
923 VertDataCopy(nCo, co, ss);
924 VertDataMulN(nCo, 0.75f, ss);
925 VertDataMulN(r, 0.25f, ss);
926 VertDataAdd(nCo, r, ss);
927 }
928 }
929 else {
930 for (x = 1; x < edgeSize - 1; x++) {
931 int fx = x * 2;
932 const float *co = EDGE_getCo(e, curLvl, x);
933 float *nCo = EDGE_getCo(e, nextLvl, fx);
934 int numFaces = 0;
935
936 VertDataZero(q, ss);
937 VertDataZero(r, ss);
938 VertDataAdd(r, EDGE_getCo(e, curLvl, x - 1), ss);
939 VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
940 for (j = 0; j < e->numFaces; j++) {
941 CCGFace *f = e->faces[j];
942 int f_ed_idx = ccg_face_getEdgeIndex(f, e);
943 VertDataAdd(q,
944 static_cast<const float *>(ccg_face_getIFCoEdge(
945 f, e, f_ed_idx, nextLvl, fx - 1, 1, subdivLevels, vertDataSize)),
946 ss);
947 VertDataAdd(q,
948 static_cast<const float *>(ccg_face_getIFCoEdge(
949 f, e, f_ed_idx, nextLvl, fx + 1, 1, subdivLevels, vertDataSize)),
950 ss);
951
952 VertDataAdd(r,
953 static_cast<const float *>(ccg_face_getIFCoEdge(
954 f, e, f_ed_idx, curLvl, x, 1, subdivLevels, vertDataSize)),
955 ss);
956 numFaces++;
957 }
958 VertDataMulN(q, 1.0f / (numFaces * 2.0f), ss);
959 VertDataMulN(r, 1.0f / (2.0f + numFaces), ss);
960
961 VertDataCopy(nCo, co, ss);
962 VertDataMulN(nCo, float(numFaces), ss);
963 VertDataAdd(nCo, q, ss);
964 VertDataAdd(nCo, r, ss);
965 VertDataMulN(nCo, 1.0f / (2 + numFaces), ss);
966
967 if (sharpCount == 2) {
968 VertDataCopy(q, co, ss);
969 VertDataMulN(q, 6.0f, ss);
970 VertDataAdd(q, EDGE_getCo(e, curLvl, x - 1), ss);
971 VertDataAdd(q, EDGE_getCo(e, curLvl, x + 1), ss);
972 VertDataMulN(q, 1 / 8.0f, ss);
973
974 VertDataSub(q, nCo, ss);
975 VertDataMulN(q, avgSharpness, ss);
976 VertDataAdd(nCo, q, ss);
977 }
978 }
979 }
980 }
981
982 {
983 TaskParallelSettings settings;
985 settings.min_iter_per_thread = CCG_TASK_LIMIT;
987 numEffectedF,
988 &data,
990 &settings);
991 }
992
993 /* copy down */
994 edgeSize = ccg_edgesize(nextLvl);
995
996 /* Not worth parallelizing. */
997 for (i = 0; i < numEffectedE; i++) {
998 CCGEdge *e = effectedE[i];
999 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
1000 VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize - 1), VERT_getCo(e->v1, nextLvl), ss);
1001 }
1002
1003 {
1004 TaskParallelSettings settings;
1006 settings.min_iter_per_thread = CCG_TASK_LIMIT;
1008 0, numEffectedF, &data, ccgSubSurf__calcSubdivLevel_verts_copydata_cb, &settings);
1009 }
1010}
1011
1013{
1014 CCGVert **effectedV;
1015 CCGEdge **effectedE;
1016 CCGFace **effectedF;
1017 int numEffectedV, numEffectedE, numEffectedF;
1018 int subdivLevels = ss->subdivLevels;
1019 int vertDataSize = ss->meshIFC.vertDataSize;
1020 int i, j, ptrIdx, S;
1021 int curLvl, nextLvl;
1022 void *q = ss->q, *r = ss->r;
1023
1024 effectedV = static_cast<CCGVert **>(
1025 MEM_mallocN(sizeof(*effectedV) * ss->vMap->numEntries, "CCGSubsurf effectedV"));
1026 effectedE = static_cast<CCGEdge **>(
1027 MEM_mallocN(sizeof(*effectedE) * ss->eMap->numEntries, "CCGSubsurf effectedE"));
1028 effectedF = static_cast<CCGFace **>(
1029 MEM_mallocN(sizeof(*effectedF) * ss->fMap->numEntries, "CCGSubsurf effectedF"));
1030 numEffectedV = numEffectedE = numEffectedF = 0;
1031 for (i = 0; i < ss->vMap->curSize; i++) {
1032 CCGVert *v = (CCGVert *)ss->vMap->buckets[i];
1033 for (; v; v = v->next) {
1034 if (v->flags & Vert_eEffected) {
1035 effectedV[numEffectedV++] = v;
1036
1037 for (j = 0; j < v->numEdges; j++) {
1038 CCGEdge *e = v->edges[j];
1039 if (!(e->flags & Edge_eEffected)) {
1040 effectedE[numEffectedE++] = e;
1041 e->flags |= Edge_eEffected;
1042 }
1043 }
1044
1045 for (j = 0; j < v->numFaces; j++) {
1046 CCGFace *f = v->faces[j];
1047 if (!(f->flags & Face_eEffected)) {
1048 effectedF[numEffectedF++] = f;
1049 f->flags |= Face_eEffected;
1050 }
1051 }
1052 }
1053 }
1054 }
1055
1056 curLvl = 0;
1057 nextLvl = curLvl + 1;
1058
1059 for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
1060 CCGFace *f = effectedF[ptrIdx];
1061 void *co = FACE_getCenterData(f);
1062 VertDataZero(static_cast<float *>(co), ss);
1063 for (i = 0; i < f->numVerts; i++) {
1064 VertDataAdd(static_cast<float *>(co), VERT_getCo(FACE_getVerts(f)[i], curLvl), ss);
1065 }
1066 VertDataMulN(static_cast<float *>(co), 1.0f / f->numVerts, ss);
1067
1068 f->flags = 0;
1069 }
1070 for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
1071 CCGEdge *e = effectedE[ptrIdx];
1072 void *co = EDGE_getCo(e, nextLvl, 1);
1073 float sharpness = EDGE_getSharpness(e, curLvl);
1074
1075 if (_edge_isBoundary(e) || sharpness >= 1.0f) {
1076 VertDataCopy(static_cast<float *>(co), VERT_getCo(e->v0, curLvl), ss);
1077 VertDataAdd(static_cast<float *>(co), VERT_getCo(e->v1, curLvl), ss);
1078 VertDataMulN(static_cast<float *>(co), 0.5f, ss);
1079 }
1080 else {
1081 int numFaces = 0;
1082 VertDataCopy(static_cast<float *>(q), VERT_getCo(e->v0, curLvl), ss);
1083 VertDataAdd(static_cast<float *>(q), VERT_getCo(e->v1, curLvl), ss);
1084 for (i = 0; i < e->numFaces; i++) {
1085 CCGFace *f = e->faces[i];
1086 VertDataAdd(static_cast<float *>(q), (float *)FACE_getCenterData(f), ss);
1087 numFaces++;
1088 }
1089 VertDataMulN(static_cast<float *>(q), 1.0f / (2.0f + numFaces), ss);
1090
1091 VertDataCopy(static_cast<float *>(r), VERT_getCo(e->v0, curLvl), ss);
1092 VertDataAdd(static_cast<float *>(r), VERT_getCo(e->v1, curLvl), ss);
1093 VertDataMulN(static_cast<float *>(r), 0.5f, ss);
1094
1095 VertDataCopy(static_cast<float *>(co), static_cast<const float *>(q), ss);
1096 VertDataSub(static_cast<float *>(r), static_cast<const float *>(q), ss);
1097 VertDataMulN(static_cast<float *>(r), sharpness, ss);
1098 VertDataAdd(static_cast<float *>(co), static_cast<const float *>(r), ss);
1099 }
1100
1101 /* edge flags cleared later */
1102 }
1103 for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
1104 CCGVert *v = effectedV[ptrIdx];
1105 void *co = VERT_getCo(v, curLvl);
1106 void *nCo = VERT_getCo(v, nextLvl);
1107 int sharpCount = 0, allSharp = 1;
1108 float avgSharpness = 0.0;
1109 int seam = VERT_seam(v), seamEdges = 0;
1110
1111 for (i = 0; i < v->numEdges; i++) {
1112 CCGEdge *e = v->edges[i];
1113 float sharpness = EDGE_getSharpness(e, curLvl);
1114
1115 if (seam && _edge_isBoundary(e)) {
1116 seamEdges++;
1117 }
1118
1119 if (sharpness != 0.0f) {
1120 sharpCount++;
1121 avgSharpness += sharpness;
1122 }
1123 else {
1124 allSharp = 0;
1125 }
1126 }
1127
1128 if (sharpCount) {
1129 avgSharpness /= sharpCount;
1130 if (avgSharpness > 1.0f) {
1131 avgSharpness = 1.0f;
1132 }
1133 }
1134
1135 if (seamEdges < 2 || seamEdges != v->numEdges) {
1136 seam = 0;
1137 }
1138
1139 if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
1140 VertDataCopy(static_cast<float *>(nCo), static_cast<const float *>(co), ss);
1141 }
1142 else if (_vert_isBoundary(v)) {
1143 int numBoundary = 0;
1144
1145 VertDataZero(static_cast<float *>(r), ss);
1146 for (i = 0; i < v->numEdges; i++) {
1147 CCGEdge *e = v->edges[i];
1148 if (_edge_isBoundary(e)) {
1149 VertDataAdd(static_cast<float *>(r), VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
1150 numBoundary++;
1151 }
1152 }
1153 VertDataCopy(static_cast<float *>(nCo), static_cast<const float *>(co), ss);
1154 VertDataMulN(static_cast<float *>(nCo), 0.75f, ss);
1155 VertDataMulN(static_cast<float *>(r), 0.25f / numBoundary, ss);
1156 VertDataAdd(static_cast<float *>(nCo), static_cast<const float *>(r), ss);
1157 }
1158 else {
1159 int numEdges = 0, numFaces = 0;
1160
1161 VertDataZero(static_cast<float *>(q), ss);
1162 for (i = 0; i < v->numFaces; i++) {
1163 CCGFace *f = v->faces[i];
1164 VertDataAdd(static_cast<float *>(q), (float *)FACE_getCenterData(f), ss);
1165 numFaces++;
1166 }
1167 VertDataMulN(static_cast<float *>(q), 1.0f / numFaces, ss);
1168 VertDataZero(static_cast<float *>(r), ss);
1169 for (i = 0; i < v->numEdges; i++) {
1170 CCGEdge *e = v->edges[i];
1171 VertDataAdd(static_cast<float *>(r), VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
1172 numEdges++;
1173 }
1174 VertDataMulN(static_cast<float *>(r), 1.0f / numEdges, ss);
1175
1176 VertDataCopy(static_cast<float *>(nCo), static_cast<const float *>(co), ss);
1177 VertDataMulN(static_cast<float *>(nCo), numEdges - 2.0f, ss);
1178 VertDataAdd(static_cast<float *>(nCo), static_cast<const float *>(q), ss);
1179 VertDataAdd(static_cast<float *>(nCo), static_cast<const float *>(r), ss);
1180 VertDataMulN(static_cast<float *>(nCo), 1.0f / numEdges, ss);
1181 }
1182
1183 if (sharpCount > 1 || seam) {
1184 VertDataZero(static_cast<float *>(q), ss);
1185
1186 if (seam) {
1187 avgSharpness = 1.0f;
1188 sharpCount = seamEdges;
1189 allSharp = 1;
1190 }
1191
1192 for (i = 0; i < v->numEdges; i++) {
1193 CCGEdge *e = v->edges[i];
1194 float sharpness = EDGE_getSharpness(e, curLvl);
1195
1196 if (seam) {
1197 if (_edge_isBoundary(e)) {
1198 CCGVert *oV = _edge_getOtherVert(e, v);
1199 VertDataAdd(static_cast<float *>(q), VERT_getCo(oV, curLvl), ss);
1200 }
1201 }
1202 else if (sharpness != 0.0f) {
1203 CCGVert *oV = _edge_getOtherVert(e, v);
1204 VertDataAdd(static_cast<float *>(q), VERT_getCo(oV, curLvl), ss);
1205 }
1206 }
1207
1208 VertDataMulN(static_cast<float *>(q), float(1) / sharpCount, ss);
1209
1210 if (sharpCount != 2 || allSharp) {
1211 /* q = q + (co - q) * avgSharpness */
1212 VertDataCopy(static_cast<float *>(r), static_cast<const float *>(co), ss);
1213 VertDataSub(static_cast<float *>(r), static_cast<const float *>(q), ss);
1214 VertDataMulN(static_cast<float *>(r), avgSharpness, ss);
1215 VertDataAdd(static_cast<float *>(q), static_cast<const float *>(r), ss);
1216 }
1217
1218 /* r = co * 0.75 + q * 0.25 */
1219 VertDataCopy(static_cast<float *>(r), static_cast<const float *>(co), ss);
1220 VertDataMulN(static_cast<float *>(r), 0.75f, ss);
1221 VertDataMulN(static_cast<float *>(q), 0.25f, ss);
1222 VertDataAdd(static_cast<float *>(r), static_cast<const float *>(q), ss);
1223
1224 /* nCo = nCo + (r - nCo) * avgSharpness */
1225 VertDataSub(static_cast<float *>(r), static_cast<const float *>(nCo), ss);
1226 VertDataMulN(static_cast<float *>(r), avgSharpness, ss);
1227 VertDataAdd(static_cast<float *>(nCo), static_cast<const float *>(r), ss);
1228 }
1229
1230 /* vert flags cleared later */
1231 }
1232
1233 if (ss->useAgeCounts) {
1234 for (i = 0; i < numEffectedV; i++) {
1235 CCGVert *v = effectedV[i];
1236 byte *user_data = static_cast<byte *>(ccgSubSurf_getVertUserData(ss, v));
1237 *((int *)&user_data[ss->vertUserAgeOffset]) = ss->currentAge;
1238 }
1239
1240 for (i = 0; i < numEffectedE; i++) {
1241 CCGEdge *e = effectedE[i];
1242 byte *user_data = static_cast<byte *>(ccgSubSurf_getEdgeUserData(ss, e));
1243 *((int *)&user_data[ss->edgeUserAgeOffset]) = ss->currentAge;
1244 }
1245
1246 for (i = 0; i < numEffectedF; i++) {
1247 CCGFace *f = effectedF[i];
1248 byte *user_data = static_cast<byte *>(ccgSubSurf_getFaceUserData(ss, f));
1249 *((int *)&user_data[ss->faceUserAgeOffset]) = ss->currentAge;
1250 }
1251 }
1252
1253 for (i = 0; i < numEffectedE; i++) {
1254 CCGEdge *e = effectedE[i];
1255 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
1256 VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl), ss);
1257 }
1258 for (i = 0; i < numEffectedF; i++) {
1259 CCGFace *f = effectedF[i];
1260 for (S = 0; S < f->numVerts; S++) {
1261 CCGEdge *e = FACE_getEdges(f)[S];
1262 CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
1263
1264 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
1265 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
1267 FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl), ss);
1269 FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1), ss);
1270
1271 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0),
1272 static_cast<const float *>(
1273 _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize)),
1274 ss);
1275 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1),
1276 static_cast<const float *>(
1277 _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize)),
1278 ss);
1279 }
1280 }
1281
1282 for (curLvl = 1; curLvl < subdivLevels; curLvl++) {
1284 ss, effectedV, effectedE, effectedF, numEffectedV, numEffectedE, numEffectedF, curLvl);
1285 }
1286
1287 if (ss->calcVertNormals) {
1289 ss, effectedV, effectedE, effectedF, numEffectedV, numEffectedE, numEffectedF);
1290 }
1291
1292 for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
1293 CCGVert *v = effectedV[ptrIdx];
1294 v->flags = 0;
1295 }
1296 for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
1297 CCGEdge *e = effectedE[ptrIdx];
1298 e->flags = 0;
1299 }
1300
1301 MEM_freeN(effectedF);
1302 MEM_freeN(effectedE);
1303 MEM_freeN(effectedV);
1304
1305#ifdef DUMP_RESULT_GRIDS
1306 ccgSubSurf__dumpCoords(ss);
1307#endif
1308}
1309
1310/* ** Public API exposed to other areas which depends on old CCG code. ** */
1311
1312CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF)
1313{
1314 CCGVert **effectedV;
1315 CCGEdge **effectedE;
1316 int i, numEffectedV, numEffectedE, freeF;
1317
1318 ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
1320 ss, effectedF, numEffectedF, &effectedV, &numEffectedV, &effectedE, &numEffectedE);
1321
1322 if (ss->calcVertNormals) {
1324 ss, effectedV, effectedE, effectedF, numEffectedV, numEffectedE, numEffectedF);
1325 }
1326
1327 for (i = 0; i < numEffectedV; i++) {
1328 effectedV[i]->flags = 0;
1329 }
1330 for (i = 0; i < numEffectedE; i++) {
1331 effectedE[i]->flags = 0;
1332 }
1333 for (i = 0; i < numEffectedF; i++) {
1334 effectedF[i]->flags = 0;
1335 }
1336
1337 MEM_freeN(effectedE);
1338 MEM_freeN(effectedV);
1339 if (freeF) {
1340 MEM_freeN(effectedF);
1341 }
1342
1343 return eCCGError_None;
1344}
1345
1346CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
1347{
1348 CCGVert **effectedV;
1349 CCGEdge **effectedE;
1350 int numEffectedV, numEffectedE, freeF, i;
1351 int curLvl, subdivLevels = ss->subdivLevels;
1352
1353 ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
1355 ss, effectedF, numEffectedF, &effectedV, &numEffectedV, &effectedE, &numEffectedE);
1356
1357 for (curLvl = lvl; curLvl < subdivLevels; curLvl++) {
1359 ss, effectedV, effectedE, effectedF, numEffectedV, numEffectedE, numEffectedF, curLvl);
1360 }
1361
1362 for (i = 0; i < numEffectedV; i++) {
1363 effectedV[i]->flags = 0;
1364 }
1365 for (i = 0; i < numEffectedE; i++) {
1366 effectedE[i]->flags = 0;
1367 }
1368 for (i = 0; i < numEffectedF; i++) {
1369 effectedF[i]->flags = 0;
1370 }
1371
1372 MEM_freeN(effectedE);
1373 MEM_freeN(effectedV);
1374 if (freeF) {
1375 MEM_freeN(effectedF);
1376 }
1377
1378 return eCCGError_None;
1379}
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
#define UNLIKELY(x)
void ccgSubSurf__effectedFaceNeighbors(CCGSubSurf *ss, CCGFace **faces, int numFaces, CCGVert ***verts, int *numVerts, CCGEdge ***edges, int *numEdges)
void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces)
void * ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e)
void * ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f)
void * ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v)
#define CCG_TASK_LIMIT
Definition CCGSubSurf.h:62
CCGError
Definition CCGSubSurf.h:52
@ eCCGError_None
Definition CCGSubSurf.h:53
BLI_INLINE int ccg_edgesize(int level)
BLI_INLINE void Normalize(float no[3])
BLI_INLINE CCGVert ** FACE_getVerts(CCGFace *f)
BLI_INLINE int ccg_gridsize(int level)
BLI_INLINE byte * EDGE_getLevelData(CCGEdge *e)
BLI_INLINE void VertDataZero(float v[], const CCGSubSurf *ss)
BLI_INLINE CCGEdge ** FACE_getEdges(CCGFace *f)
BLI_INLINE int ccg_edgebase(int level)
BLI_INLINE int ccg_face_getEdgeIndex(CCGFace *f, CCGEdge *e)
BLI_INLINE void * ccg_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize)
BLI_INLINE void VertDataSub(float a[], const float b[], const CCGSubSurf *ss)
BLI_INLINE void VertDataCopy(float dst[], const float src[], const CCGSubSurf *ss)
BLI_INLINE int ccg_face_getVertIndex(CCGFace *f, CCGVert *v)
BLI_INLINE void VertDataMulN(float v[], float f, const CCGSubSurf *ss)
BLI_INLINE void VertDataAvg4(float v[], const float a[], const float b[], const float c[], const float d[], const CCGSubSurf *ss)
BLI_INLINE void VertDataAdd(float a[], const float b[], const CCGSubSurf *ss)
BLI_INLINE void * ccg_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize)
BLI_INLINE byte * FACE_getCenterData(CCGFace *f)
#define EDGE_getNo(e, lvl, x)
@ Face_eEffected
#define FACE_getIENo(f, lvl, S, x)
#define FACE_getIFNo(f, lvl, S, x, y)
#define NormZero(av)
#define EDGE_getCo(e, lvl, x)
@ Vert_eEffected
@ Vert_eSeam
#define FACE_getIFCo(f, lvl, S, x, y)
#define NormAdd(av, bv)
#define NormCopy(av, bv)
#define VERT_getCo(v, lvl)
@ Edge_eEffected
#define VERT_getNo(v, lvl)
#define FACE_getIECo(f, lvl, S, x)
static void ccgSubSurf__calcSubdivLevel_interior_faces_edges_midpoints_cb(void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict)
static void ccgSubSurf__calcSubdivLevel_interior_faces_edges_centerpoints_shift_cb(void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict)
static CCGVert * _edge_getOtherVert(CCGEdge *e, CCGVert *vQ)
static int _edge_isBoundary(const CCGEdge *e)
#define FACE_calcIFNo(f, lvl, S, x, y, no)
CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF)
static void ccgSubSurf__calcVertNormals_edges_accumulate_cb(void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict)
static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF, int numEffectedV, int numEffectedE, int numEffectedF)
static void ccgSubSurf__calcVertNormals_faces_accumulate_cb(void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict)
CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
static void * _edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize)
static float * _face_getIFNoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset)
static void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float no[3], int levels, int dataSize)
static float EDGE_getSharpness(CCGEdge *e, int lvl)
static void ccgSubSurf__calcSubdivLevel_verts_copydata_cb(void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict)
static int VERT_seam(const CCGVert *v)
static bool _vert_isBoundary(const CCGVert *v)
void ccgSubSurf__sync_legacy(CCGSubSurf *ss)
static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF, const int numEffectedV, const int numEffectedE, const int numEffectedF, const int curLvl)
static void ccgSubSurf__calcVertNormals_faces_finalize_cb(void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict)
#define K(key)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
local_group_size(16, 16) .push_constant(Type b
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
int vertDataSize
Definition CCGSubSurf.h:28
int simpleSubdiv
Definition CCGSubSurf.h:29
CCGMeshIFC meshIFC
EHEntry ** buckets