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