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