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