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