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