Cleanup: shadowing (blenkernel)
[blender.git] / source / blender / blenkernel / intern / CCGSubSurf_legacy.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/blenkernel/intern/CCGSubSurf_legacy.c
22  *  \ingroup bke
23  */
24
25 #include "MEM_guardedalloc.h"
26 #include "BLI_sys_types.h" // for intptr_t support
27
28 #include "BLI_utildefines.h" /* for BLI_assert */
29 #include "BLI_math.h"
30
31 #include "CCGSubSurf.h"
32 #include "CCGSubSurf_intern.h"
33
34 #define FACE_calcIFNo(f, lvl, S, x, y, no)  _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
35
36 /* TODO(sergey): Deduplicate the following functions/ */
37 static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize)
38 {
39         int levelBase = ccg_edgebase(lvl);
40         if (v == e->v0) {
41                 return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
42         }
43         else {
44                 return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)];
45         }
46 }
47 /* *************************************************** */
48
49 static int _edge_isBoundary(const CCGEdge *e)
50 {
51         return e->numFaces < 2;
52 }
53
54 static int _vert_isBoundary(const CCGVert *v)
55 {
56         int i;
57         for (i = 0; i < v->numEdges; i++)
58                 if (_edge_isBoundary(v->edges[i]))
59                         return 1;
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, int eY,
78                                 int levels,
79                                 int dataSize,
80                                 int normalDataOffset)
81 {
82         return (float *) ((byte *) ccg_face_getIFCoEdge(f, e, f_ed_idx, lvl, eX, eY, levels, dataSize) + normalDataOffset);
83 }
84
85 static void _face_calcIFNo(CCGFace *f,
86                            int lvl,
87                            int S,
88                            int x, int y,
89                            float no[3],
90                            int levels,
91                            int dataSize)
92 {
93         float *a = ccg_face_getIFCo(f, lvl, S, x + 0, y + 0, levels, dataSize);
94         float *b = ccg_face_getIFCo(f, lvl, S, x + 1, y + 0, levels, dataSize);
95         float *c = ccg_face_getIFCo(f, lvl, S, x + 1, y + 1, levels, dataSize);
96         float *d = ccg_face_getIFCo(f, lvl, S, x + 0, y + 1, levels, dataSize);
97         float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
98         float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
99
100         no[0] = b_dY * a_cZ - b_dZ * a_cY;
101         no[1] = b_dZ * a_cX - b_dX * a_cZ;
102         no[2] = b_dX * a_cY - b_dY * a_cX;
103
104         Normalize(no);
105 }
106
107 static int VERT_seam(const CCGVert *v)
108 {
109         return ((v->flags & Vert_eSeam) != 0);
110 }
111
112 static float EDGE_getSharpness(CCGEdge *e, int lvl)
113 {
114         if (!lvl)
115                 return e->crease;
116         else if (!e->crease)
117                 return 0.0f;
118         else if (e->crease - lvl < 0.0f)
119                 return 0.0f;
120         else
121                 return e->crease - lvl;
122 }
123
124 static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
125                                         CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
126                                         int numEffectedV, int numEffectedE, int numEffectedF)
127 {
128         int i, ptrIdx;
129         int subdivLevels = ss->subdivLevels;
130         int lvl = ss->subdivLevels;
131         int edgeSize = ccg_edgesize(lvl);
132         int gridSize = ccg_gridsize(lvl);
133         int normalDataOffset = ss->normalDataOffset;
134         int vertDataSize = ss->meshIFC.vertDataSize;
135
136 #pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
137         for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
138                 CCGFace *f = (CCGFace *) effectedF[ptrIdx];
139                 int S, x, y;
140                 float no[3];
141
142                 for (S = 0; S < f->numVerts; S++) {
143                         for (y = 0; y < gridSize - 1; y++) {
144                                 for (x = 0; x < gridSize - 1; x++) {
145                                         NormZero(FACE_getIFNo(f, lvl, S, x, y));
146                                 }
147                         }
148
149                         if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) {
150                                 for (x = 0; x < gridSize - 1; x++) {
151                                         NormZero(FACE_getIFNo(f, lvl, S, x, gridSize - 1));
152                                 }
153                         }
154                         if (FACE_getEdges(f)[S]->flags & Edge_eEffected) {
155                                 for (y = 0; y < gridSize - 1; y++) {
156                                         NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, y));
157                                 }
158                         }
159                         if (FACE_getVerts(f)[S]->flags & Vert_eEffected) {
160                                 NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, gridSize - 1));
161                         }
162                 }
163
164                 for (S = 0; S < f->numVerts; S++) {
165                         int yLimit = !(FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected);
166                         int xLimit = !(FACE_getEdges(f)[S]->flags & Edge_eEffected);
167                         int yLimitNext = xLimit;
168                         int xLimitPrev = yLimit;
169                         
170                         for (y = 0; y < gridSize - 1; y++) {
171                                 for (x = 0; x < gridSize - 1; x++) {
172                                         int xPlusOk = (!xLimit || x < gridSize - 2);
173                                         int yPlusOk = (!yLimit || y < gridSize - 2);
174
175                                         FACE_calcIFNo(f, lvl, S, x, y, no);
176
177                                         NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 0), no);
178                                         if (xPlusOk)
179                                                 NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 0), no);
180                                         if (yPlusOk)
181                                                 NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 1), no);
182                                         if (xPlusOk && yPlusOk) {
183                                                 if (x < gridSize - 2 || y < gridSize - 2 || FACE_getVerts(f)[S]->flags & Vert_eEffected) {
184                                                         NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 1), no);
185                                                 }
186                                         }
187
188                                         if (x == 0 && y == 0) {
189                                                 int K;
190
191                                                 if (!yLimitNext || 1 < gridSize - 1)
192                                                         NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, 1), no);
193                                                 if (!xLimitPrev || 1 < gridSize - 1)
194                                                         NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, 1, 0), no);
195
196                                                 for (K = 0; K < f->numVerts; K++) {
197                                                         if (K != S) {
198                                                                 NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
199                                                         }
200                                                 }
201                                         }
202                                         else if (y == 0) {
203                                                 NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x), no);
204                                                 if (!yLimitNext || x < gridSize - 2)
205                                                         NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x + 1), no);
206                                         }
207                                         else if (x == 0) {
208                                                 NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y, 0), no);
209                                                 if (!xLimitPrev || y < gridSize - 2)
210                                                         NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y + 1, 0), no);
211                                         }
212                                 }
213                         }
214                 }
215         }
216         /* XXX can I reduce the number of normalisations here? */
217         for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
218                 CCGVert *v = (CCGVert *) effectedV[ptrIdx];
219                 float *no = VERT_getNo(v, lvl);
220
221                 NormZero(no);
222
223                 for (i = 0; i < v->numFaces; i++) {
224                         CCGFace *f = v->faces[i];
225                         NormAdd(no, FACE_getIFNo(f, lvl, ccg_face_getVertIndex(f, v), gridSize - 1, gridSize - 1));
226                 }
227
228                 if (UNLIKELY(v->numFaces == 0)) {
229                         NormCopy(no, VERT_getCo(v, lvl));
230                 }
231
232                 Normalize(no);
233
234                 for (i = 0; i < v->numFaces; i++) {
235                         CCGFace *f = v->faces[i];
236                         NormCopy(FACE_getIFNo(f, lvl, ccg_face_getVertIndex(f, v), gridSize - 1, gridSize - 1), no);
237                 }
238         }
239         for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
240                 CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
241
242                 if (e->numFaces) {
243                         CCGFace *fLast = e->faces[e->numFaces - 1];
244                         int x;
245
246                         for (i = 0; i < e->numFaces - 1; i++) {
247                                 CCGFace *f = e->faces[i];
248                                 const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
249                                 const int f_ed_idx_last = ccg_face_getEdgeIndex(fLast, e);
250
251                                 for (x = 1; x < edgeSize - 1; x++) {
252                                         NormAdd(_face_getIFNoEdge(fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
253                                                 _face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
254                                 }
255                         }
256
257                         for (i = 0; i < e->numFaces - 1; i++) {
258                                 CCGFace *f = e->faces[i];
259                                 const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
260                                 const int f_ed_idx_last = ccg_face_getEdgeIndex(fLast, e);
261
262                                 for (x = 1; x < edgeSize - 1; x++) {
263                                         NormCopy(_face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
264                                                  _face_getIFNoEdge(fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
265                                 }
266                         }
267                 }
268         }
269
270 #pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
271         for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
272                 CCGFace *f = (CCGFace *) effectedF[ptrIdx];
273                 int S, x, y;
274
275                 for (S = 0; S < f->numVerts; S++) {
276                         NormCopy(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, gridSize - 1),
277                                  FACE_getIFNo(f, lvl, S, gridSize - 1, 0));
278                 }
279
280                 for (S = 0; S < f->numVerts; S++) {
281                         for (y = 0; y < gridSize; y++) {
282                                 for (x = 0; x < gridSize; x++) {
283                                         float *no = FACE_getIFNo(f, lvl, S, x, y);
284                                         Normalize(no);
285                                 }
286                         }
287
288                         VertDataCopy((float *)((byte *)FACE_getCenterData(f) + normalDataOffset),
289                                      FACE_getIFNo(f, lvl, S, 0, 0), ss);
290
291                         for (x = 1; x < gridSize - 1; x++)
292                                 NormCopy(FACE_getIENo(f, lvl, S, x),
293                                          FACE_getIFNo(f, lvl, S, x, 0));
294                 }
295         }
296
297         for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
298                 CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
299
300                 if (e->numFaces) {
301                         CCGFace *f = e->faces[0];
302                         int x;
303                         const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
304
305                         for (x = 0; x < edgeSize; x++)
306                                 NormCopy(EDGE_getNo(e, lvl, x),
307                                          _face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
308                 }
309                 else {
310                         /* set to zero here otherwise the normals are uninitialized memory
311                          * render: tests/animation/knight.blend with valgrind.
312                          * we could be more clever and interpolate vertex normals but these are
313                          * most likely not used so just zero out. */
314                         int x;
315
316                         for (x = 0; x < edgeSize; x++) {
317                                 float *no = EDGE_getNo(e, lvl, x);
318                                 NormCopy(no, EDGE_getCo(e, lvl, x));
319                                 Normalize(no);
320                         }
321                 }
322         }
323 }
324
325 static void ccgSubSurf__calcSubdivLevel(
326         CCGSubSurf *ss,
327         CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
328         const int numEffectedV, const int numEffectedE, const int numEffectedF, const int curLvl)
329 {
330         const int subdivLevels = ss->subdivLevels;
331         const int nextLvl = curLvl + 1;
332         int edgeSize = ccg_edgesize(curLvl);
333         int gridSize = ccg_gridsize(curLvl);
334         int ptrIdx, i;
335         int vertDataSize = ss->meshIFC.vertDataSize;
336         float *q = ss->q, *r = ss->r;
337
338 #pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
339         for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
340                 CCGFace *f = (CCGFace *) effectedF[ptrIdx];
341                 int S, x, y;
342
343                 /* interior face midpoints
344                  * - old interior face points
345                  */
346                 for (S = 0; S < f->numVerts; S++) {
347                         for (y = 0; y < gridSize - 1; y++) {
348                                 for (x = 0; x < gridSize - 1; x++) {
349                                         int fx = 1 + 2 * x;
350                                         int fy = 1 + 2 * y;
351                                         const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y + 0);
352                                         const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y + 0);
353                                         const float *co2 = FACE_getIFCo(f, curLvl, S, x + 1, y + 1);
354                                         const float *co3 = FACE_getIFCo(f, curLvl, S, x + 0, y + 1);
355                                         float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
356
357                                         VertDataAvg4(co, co0, co1, co2, co3, ss);
358                                 }
359                         }
360                 }
361
362                 /* interior edge midpoints
363                  * - old interior edge points
364                  * - new interior face midpoints
365                  */
366                 for (S = 0; S < f->numVerts; S++) {
367                         for (x = 0; x < gridSize - 1; x++) {
368                                 int fx = x * 2 + 1;
369                                 const float *co0 = FACE_getIECo(f, curLvl, S, x + 0);
370                                 const float *co1 = FACE_getIECo(f, curLvl, S, x + 1);
371                                 const float *co2 = FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx);
372                                 const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
373                                 float *co  = FACE_getIECo(f, nextLvl, S, fx);
374                                 
375                                 VertDataAvg4(co, co0, co1, co2, co3, ss);
376                         }
377
378                         /* interior face interior edge midpoints
379                          * - old interior face points
380                          * - new interior face midpoints
381                          */
382
383                         /* vertical */
384                         for (x = 1; x < gridSize - 1; x++) {
385                                 for (y = 0; y < gridSize - 1; y++) {
386                                         int fx = x * 2;
387                                         int fy = y * 2 + 1;
388                                         const float *co0 = FACE_getIFCo(f, curLvl, S, x, y + 0);
389                                         const float *co1 = FACE_getIFCo(f, curLvl, S, x, y + 1);
390                                         const float *co2 = FACE_getIFCo(f, nextLvl, S, fx - 1, fy);
391                                         const float *co3 = FACE_getIFCo(f, nextLvl, S, fx + 1, fy);
392                                         float *co  = FACE_getIFCo(f, nextLvl, S, fx, fy);
393
394                                         VertDataAvg4(co, co0, co1, co2, co3, ss);
395                                 }
396                         }
397
398                         /* horizontal */
399                         for (y = 1; y < gridSize - 1; y++) {
400                                 for (x = 0; x < gridSize - 1; x++) {
401                                         int fx = x * 2 + 1;
402                                         int fy = y * 2;
403                                         const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y);
404                                         const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y);
405                                         const float *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy - 1);
406                                         const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy + 1);
407                                         float *co  = FACE_getIFCo(f, nextLvl, S, fx, fy);
408
409                                         VertDataAvg4(co, co0, co1, co2, co3, ss);
410                                 }
411                         }
412                 }
413         }
414
415         /* exterior edge midpoints
416          * - old exterior edge points
417          * - new interior face midpoints
418          */
419         for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
420                 CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
421                 float sharpness = EDGE_getSharpness(e, curLvl);
422                 int x, j;
423
424                 if (_edge_isBoundary(e) || sharpness > 1.0f) {
425                         for (x = 0; x < edgeSize - 1; x++) {
426                                 int fx = x * 2 + 1;
427                                 const float *co0 = EDGE_getCo(e, curLvl, x + 0);
428                                 const float *co1 = EDGE_getCo(e, curLvl, x + 1);
429                                 float *co  = EDGE_getCo(e, nextLvl, fx);
430
431                                 VertDataCopy(co, co0, ss);
432                                 VertDataAdd(co, co1, ss);
433                                 VertDataMulN(co, 0.5f, ss);
434                         }
435                 }
436                 else {
437                         for (x = 0; x < edgeSize - 1; x++) {
438                                 int fx = x * 2 + 1;
439                                 const float *co0 = EDGE_getCo(e, curLvl, x + 0);
440                                 const float *co1 = EDGE_getCo(e, curLvl, x + 1);
441                                 float *co  = EDGE_getCo(e, nextLvl, fx);
442                                 int numFaces = 0;
443
444                                 VertDataCopy(q, co0, ss);
445                                 VertDataAdd(q, co1, ss);
446
447                                 for (j = 0; j < e->numFaces; j++) {
448                                         CCGFace *f = e->faces[j];
449                                         const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
450                                         VertDataAdd(q, ccg_face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx, 1, subdivLevels, vertDataSize), ss);
451                                         numFaces++;
452                                 }
453
454                                 VertDataMulN(q, 1.0f / (2.0f + numFaces), ss);
455
456                                 VertDataCopy(r, co0, ss);
457                                 VertDataAdd(r, co1, ss);
458                                 VertDataMulN(r, 0.5f, ss);
459
460                                 VertDataCopy(co, q, ss);
461                                 VertDataSub(r, q, ss);
462                                 VertDataMulN(r, sharpness, ss);
463                                 VertDataAdd(co, r, ss);
464                         }
465                 }
466         }
467
468         /* exterior vertex shift
469          * - old vertex points (shifting)
470          * - old exterior edge points
471          * - new interior face midpoints
472          */
473         for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
474                 CCGVert *v = (CCGVert *) effectedV[ptrIdx];
475                 const float *co = VERT_getCo(v, curLvl);
476                 float *nCo = VERT_getCo(v, nextLvl);
477                 int sharpCount = 0, allSharp = 1;
478                 float avgSharpness = 0.0;
479                 int j, seam = VERT_seam(v), seamEdges = 0;
480
481                 for (j = 0; j < v->numEdges; j++) {
482                         CCGEdge *e = v->edges[j];
483                         float sharpness = EDGE_getSharpness(e, curLvl);
484
485                         if (seam && _edge_isBoundary(e))
486                                 seamEdges++;
487
488                         if (sharpness != 0.0f) {
489                                 sharpCount++;
490                                 avgSharpness += sharpness;
491                         }
492                         else {
493                                 allSharp = 0;
494                         }
495                 }
496
497                 if (sharpCount) {
498                         avgSharpness /= sharpCount;
499                         if (avgSharpness > 1.0f) {
500                                 avgSharpness = 1.0f;
501                         }
502                 }
503
504                 if (seamEdges < 2 || seamEdges != v->numEdges)
505                         seam = 0;
506
507                 if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
508                         VertDataCopy(nCo, co, ss);
509                 }
510                 else if (_vert_isBoundary(v)) {
511                         int numBoundary = 0;
512
513                         VertDataZero(r, ss);
514                         for (j = 0; j < v->numEdges; j++) {
515                                 CCGEdge *e = v->edges[j];
516                                 if (_edge_isBoundary(e)) {
517                                         VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
518                                         numBoundary++;
519                                 }
520                         }
521
522                         VertDataCopy(nCo, co, ss);
523                         VertDataMulN(nCo, 0.75f, ss);
524                         VertDataMulN(r, 0.25f / numBoundary, ss);
525                         VertDataAdd(nCo, r, ss);
526                 }
527                 else {
528                         const int cornerIdx = (1 + (1 << (curLvl))) - 2;
529                         int numEdges = 0, numFaces = 0;
530
531                         VertDataZero(q, ss);
532                         for (j = 0; j < v->numFaces; j++) {
533                                 CCGFace *f = v->faces[j];
534                                 VertDataAdd(q, FACE_getIFCo(f, nextLvl, ccg_face_getVertIndex(f, v), cornerIdx, cornerIdx), ss);
535                                 numFaces++;
536                         }
537                         VertDataMulN(q, 1.0f / numFaces, ss);
538                         VertDataZero(r, ss);
539                         for (j = 0; j < v->numEdges; j++) {
540                                 CCGEdge *e = v->edges[j];
541                                 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
542                                 numEdges++;
543                         }
544                         VertDataMulN(r, 1.0f / numEdges, ss);
545
546                         VertDataCopy(nCo, co, ss);
547                         VertDataMulN(nCo, numEdges - 2.0f, ss);
548                         VertDataAdd(nCo, q, ss);
549                         VertDataAdd(nCo, r, ss);
550                         VertDataMulN(nCo, 1.0f / numEdges, ss);
551                 }
552
553                 if ((sharpCount > 1 && v->numFaces) || seam) {
554                         VertDataZero(q, ss);
555
556                         if (seam) {
557                                 avgSharpness = 1.0f;
558                                 sharpCount = seamEdges;
559                                 allSharp = 1;
560                         }
561
562                         for (j = 0; j < v->numEdges; j++) {
563                                 CCGEdge *e = v->edges[j];
564                                 float sharpness = EDGE_getSharpness(e, curLvl);
565
566                                 if (seam) {
567                                         if (_edge_isBoundary(e))
568                                                 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
569                                 }
570                                 else if (sharpness != 0.0f) {
571                                         VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
572                                 }
573                         }
574
575                         VertDataMulN(q, (float) 1 / sharpCount, ss);
576
577                         if (sharpCount != 2 || allSharp) {
578                                 /* q = q + (co - q) * avgSharpness */
579                                 VertDataCopy(r, co, ss);
580                                 VertDataSub(r, q, ss);
581                                 VertDataMulN(r, avgSharpness, ss);
582                                 VertDataAdd(q, r, ss);
583                         }
584
585                         /* r = co * 0.75 + q * 0.25 */
586                         VertDataCopy(r, co, ss);
587                         VertDataMulN(r, 0.75f, ss);
588                         VertDataMulN(q, 0.25f, ss);
589                         VertDataAdd(r, q, ss);
590
591                         /* nCo = nCo + (r - nCo) * avgSharpness */
592                         VertDataSub(r, nCo, ss);
593                         VertDataMulN(r, avgSharpness, ss);
594                         VertDataAdd(nCo, r, ss);
595                 }
596         }
597
598         /* exterior edge interior shift
599          * - old exterior edge midpoints (shifting)
600          * - old exterior edge midpoints
601          * - new interior face midpoints
602          */
603         for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
604                 CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
605                 float sharpness = EDGE_getSharpness(e, curLvl);
606                 int sharpCount = 0;
607                 float avgSharpness = 0.0;
608                 int x, j;
609
610                 if (sharpness != 0.0f) {
611                         sharpCount = 2;
612                         avgSharpness += sharpness;
613
614                         if (avgSharpness > 1.0f) {
615                                 avgSharpness = 1.0f;
616                         }
617                 }
618                 else {
619                         sharpCount = 0;
620                         avgSharpness = 0;
621                 }
622
623                 if (_edge_isBoundary(e)) {
624                         for (x = 1; x < edgeSize - 1; x++) {
625                                 int fx = x * 2;
626                                 const float *co = EDGE_getCo(e, curLvl, x);
627                                 float *nCo = EDGE_getCo(e, nextLvl, fx);
628
629                                 /* Average previous level's endpoints */
630                                 VertDataCopy(r, EDGE_getCo(e, curLvl, x - 1), ss);
631                                 VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
632                                 VertDataMulN(r, 0.5f, ss);
633
634                                 /* nCo = nCo * 0.75 + r * 0.25 */
635                                 VertDataCopy(nCo, co, ss);
636                                 VertDataMulN(nCo, 0.75f, ss);
637                                 VertDataMulN(r, 0.25f, ss);
638                                 VertDataAdd(nCo, r, ss);
639                         }
640                 }
641                 else {
642                         for (x = 1; x < edgeSize - 1; x++) {
643                                 int fx = x * 2;
644                                 const float *co = EDGE_getCo(e, curLvl, x);
645                                 float *nCo = EDGE_getCo(e, nextLvl, fx);
646                                 int numFaces = 0;
647
648                                 VertDataZero(q, ss);
649                                 VertDataZero(r, ss);
650                                 VertDataAdd(r, EDGE_getCo(e, curLvl, x - 1), ss);
651                                 VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
652                                 for (j = 0; j < e->numFaces; j++) {
653                                         CCGFace *f = e->faces[j];
654                                         int f_ed_idx = ccg_face_getEdgeIndex(f, e);
655                                         VertDataAdd(q, ccg_face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx - 1, 1, subdivLevels, vertDataSize), ss);
656                                         VertDataAdd(q, ccg_face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx + 1, 1, subdivLevels, vertDataSize), ss);
657
658                                         VertDataAdd(r, ccg_face_getIFCoEdge(f, e, f_ed_idx, curLvl, x, 1, subdivLevels, vertDataSize), ss);
659                                         numFaces++;
660                                 }
661                                 VertDataMulN(q, 1.0f / (numFaces * 2.0f), ss);
662                                 VertDataMulN(r, 1.0f / (2.0f + numFaces), ss);
663
664                                 VertDataCopy(nCo, co, ss);
665                                 VertDataMulN(nCo, (float) numFaces, ss);
666                                 VertDataAdd(nCo, q, ss);
667                                 VertDataAdd(nCo, r, ss);
668                                 VertDataMulN(nCo, 1.0f / (2 + numFaces), ss);
669
670                                 if (sharpCount == 2) {
671                                         VertDataCopy(q, co, ss);
672                                         VertDataMulN(q, 6.0f, ss);
673                                         VertDataAdd(q, EDGE_getCo(e, curLvl, x - 1), ss);
674                                         VertDataAdd(q, EDGE_getCo(e, curLvl, x + 1), ss);
675                                         VertDataMulN(q, 1 / 8.0f, ss);
676
677                                         VertDataSub(q, nCo, ss);
678                                         VertDataMulN(q, avgSharpness, ss);
679                                         VertDataAdd(nCo, q, ss);
680                                 }
681                         }
682                 }
683         }
684
685 #pragma omp parallel private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
686         {
687 #pragma omp critical
688                 {
689                         q = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf q");
690                         r = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf r");
691                 }
692
693 #pragma omp for schedule(static)
694                 for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
695                         CCGFace *f = (CCGFace *) effectedF[ptrIdx];
696                         int S, x, y;
697
698                         /* interior center point shift
699                          * - old face center point (shifting)
700                          * - old interior edge points
701                          * - new interior face midpoints
702                          */
703                         VertDataZero(q, ss);
704                         for (S = 0; S < f->numVerts; S++) {
705                                 VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1), ss);
706                         }
707                         VertDataMulN(q, 1.0f / f->numVerts, ss);
708                         VertDataZero(r, ss);
709                         for (S = 0; S < f->numVerts; S++) {
710                                 VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1), ss);
711                         }
712                         VertDataMulN(r, 1.0f / f->numVerts, ss);
713
714                         VertDataMulN((float *)FACE_getCenterData(f), f->numVerts - 2.0f, ss);
715                         VertDataAdd((float *)FACE_getCenterData(f), q, ss);
716                         VertDataAdd((float *)FACE_getCenterData(f), r, ss);
717                         VertDataMulN((float *)FACE_getCenterData(f), 1.0f / f->numVerts, ss);
718
719                         for (S = 0; S < f->numVerts; S++) {
720                                 /* interior face shift
721                                  * - old interior face point (shifting)
722                                  * - new interior edge midpoints
723                                  * - new interior face midpoints
724                                  */
725                                 for (x = 1; x < gridSize - 1; x++) {
726                                         for (y = 1; y < gridSize - 1; y++) {
727                                                 int fx = x * 2;
728                                                 int fy = y * 2;
729                                                 const float *co = FACE_getIFCo(f, curLvl, S, x, y);
730                                                 float *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
731                                                 
732                                                 VertDataAvg4(q,
733                                                              FACE_getIFCo(f, nextLvl, S, fx - 1, fy - 1),
734                                                              FACE_getIFCo(f, nextLvl, S, fx + 1, fy - 1),
735                                                              FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 1),
736                                                              FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 1),
737                                                              ss);
738
739                                                 VertDataAvg4(r,
740                                                              FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 0),
741                                                              FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 0),
742                                                              FACE_getIFCo(f, nextLvl, S, fx + 0, fy - 1),
743                                                              FACE_getIFCo(f, nextLvl, S, fx + 0, fy + 1),
744                                                              ss);
745
746                                                 VertDataCopy(nCo, co, ss);
747                                                 VertDataSub(nCo, q, ss);
748                                                 VertDataMulN(nCo, 0.25f, ss);
749                                                 VertDataAdd(nCo, r, ss);
750                                         }
751                                 }
752
753                                 /* interior edge interior shift
754                                  * - old interior edge point (shifting)
755                                  * - new interior edge midpoints
756                                  * - new interior face midpoints
757                                  */
758                                 for (x = 1; x < gridSize - 1; x++) {
759                                         int fx = x * 2;
760                                         const float *co = FACE_getIECo(f, curLvl, S, x);
761                                         float *nCo = FACE_getIECo(f, nextLvl, S, fx);
762                                         
763                                         VertDataAvg4(q,
764                                                      FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx - 1),
765                                                      FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx + 1),
766                                                      FACE_getIFCo(f, nextLvl, S, fx + 1, +1),
767                                                      FACE_getIFCo(f, nextLvl, S, fx - 1, +1), ss);
768
769                                         VertDataAvg4(r,
770                                                      FACE_getIECo(f, nextLvl, S, fx - 1),
771                                                      FACE_getIECo(f, nextLvl, S, fx + 1),
772                                                      FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx),
773                                                      FACE_getIFCo(f, nextLvl, S, fx, 1),
774                                                      ss);
775
776                                         VertDataCopy(nCo, co, ss);
777                                         VertDataSub(nCo, q, ss);
778                                         VertDataMulN(nCo, 0.25f, ss);
779                                         VertDataAdd(nCo, r, ss);
780                                 }
781                         }
782                 }
783
784 #pragma omp critical
785                 {
786                         MEM_freeN(q);
787                         MEM_freeN(r);
788                 }
789         }
790
791         /* copy down */
792         edgeSize = ccg_edgesize(nextLvl);
793         gridSize = ccg_gridsize(nextLvl);
794         const int cornerIdx = gridSize - 1;
795
796 #pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
797         for (i = 0; i < numEffectedE; i++) {
798                 CCGEdge *e = effectedE[i];
799                 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
800                 VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize - 1), VERT_getCo(e->v1, nextLvl), ss);
801         }
802
803 #pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
804         for (i = 0; i < numEffectedF; i++) {
805                 CCGFace *f = effectedF[i];
806                 int S, x;
807
808                 for (S = 0; S < f->numVerts; S++) {
809                         CCGEdge *e = FACE_getEdges(f)[S];
810                         CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
811
812                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
813                         VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
814                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl), ss);
815                         VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx), ss);
816                         for (x = 1; x < gridSize - 1; x++) {
817                                 float *co = FACE_getIECo(f, nextLvl, S, x);
818                                 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co, ss);
819                                 VertDataCopy(FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 0, x), co, ss);
820                         }
821                         for (x = 0; x < gridSize - 1; x++) {
822                                 int eI = gridSize - 1 - x;
823                                 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize), ss);
824                                 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize), ss);
825                         }
826                 }
827         }
828 }
829
830 void ccgSubSurf__sync_legacy(CCGSubSurf *ss)
831 {
832         CCGVert **effectedV;
833         CCGEdge **effectedE;
834         CCGFace **effectedF;
835         int numEffectedV, numEffectedE, numEffectedF;
836         int subdivLevels = ss->subdivLevels;
837         int vertDataSize = ss->meshIFC.vertDataSize;
838         int i, j, ptrIdx, S;
839         int curLvl, nextLvl;
840         void *q = ss->q, *r = ss->r;
841
842         effectedV = MEM_mallocN(sizeof(*effectedV) * ss->vMap->numEntries, "CCGSubsurf effectedV");
843         effectedE = MEM_mallocN(sizeof(*effectedE) * ss->eMap->numEntries, "CCGSubsurf effectedE");
844         effectedF = MEM_mallocN(sizeof(*effectedF) * ss->fMap->numEntries, "CCGSubsurf effectedF");
845         numEffectedV = numEffectedE = numEffectedF = 0;
846         for (i = 0; i < ss->vMap->curSize; i++) {
847                 CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
848                 for (; v; v = v->next) {
849                         if (v->flags & Vert_eEffected) {
850                                 effectedV[numEffectedV++] = v;
851
852                                 for (j = 0; j < v->numEdges; j++) {
853                                         CCGEdge *e = v->edges[j];
854                                         if (!(e->flags & Edge_eEffected)) {
855                                                 effectedE[numEffectedE++] = e;
856                                                 e->flags |= Edge_eEffected;
857                                         }
858                                 }
859
860                                 for (j = 0; j < v->numFaces; j++) {
861                                         CCGFace *f = v->faces[j];
862                                         if (!(f->flags & Face_eEffected)) {
863                                                 effectedF[numEffectedF++] = f;
864                                                 f->flags |= Face_eEffected;
865                                         }
866                                 }
867                         }
868                 }
869         }
870
871         curLvl = 0;
872         nextLvl = curLvl + 1;
873
874         for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
875                 CCGFace *f = effectedF[ptrIdx];
876                 void *co = FACE_getCenterData(f);
877                 VertDataZero(co, ss);
878                 for (i = 0; i < f->numVerts; i++) {
879                         VertDataAdd(co, VERT_getCo(FACE_getVerts(f)[i], curLvl), ss);
880                 }
881                 VertDataMulN(co, 1.0f / f->numVerts, ss);
882
883                 f->flags = 0;
884         }
885         for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
886                 CCGEdge *e = effectedE[ptrIdx];
887                 void *co = EDGE_getCo(e, nextLvl, 1);
888                 float sharpness = EDGE_getSharpness(e, curLvl);
889
890                 if (_edge_isBoundary(e) || sharpness >= 1.0f) {
891                         VertDataCopy(co, VERT_getCo(e->v0, curLvl), ss);
892                         VertDataAdd(co, VERT_getCo(e->v1, curLvl), ss);
893                         VertDataMulN(co, 0.5f, ss);
894                 }
895                 else {
896                         int numFaces = 0;
897                         VertDataCopy(q, VERT_getCo(e->v0, curLvl), ss);
898                         VertDataAdd(q, VERT_getCo(e->v1, curLvl), ss);
899                         for (i = 0; i < e->numFaces; i++) {
900                                 CCGFace *f = e->faces[i];
901                                 VertDataAdd(q, (float *)FACE_getCenterData(f), ss);
902                                 numFaces++;
903                         }
904                         VertDataMulN(q, 1.0f / (2.0f + numFaces), ss);
905
906                         VertDataCopy(r, VERT_getCo(e->v0, curLvl), ss);
907                         VertDataAdd(r, VERT_getCo(e->v1, curLvl), ss);
908                         VertDataMulN(r, 0.5f, ss);
909
910                         VertDataCopy(co, q, ss);
911                         VertDataSub(r, q, ss);
912                         VertDataMulN(r, sharpness, ss);
913                         VertDataAdd(co, r, ss);
914                 }
915
916                 /* edge flags cleared later */
917         }
918         for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
919                 CCGVert *v = effectedV[ptrIdx];
920                 void *co = VERT_getCo(v, curLvl);
921                 void *nCo = VERT_getCo(v, nextLvl);
922                 int sharpCount = 0, allSharp = 1;
923                 float avgSharpness = 0.0;
924                 int seam = VERT_seam(v), seamEdges = 0;
925
926                 for (i = 0; i < v->numEdges; i++) {
927                         CCGEdge *e = v->edges[i];
928                         float sharpness = EDGE_getSharpness(e, curLvl);
929
930                         if (seam && _edge_isBoundary(e))
931                                 seamEdges++;
932
933                         if (sharpness != 0.0f) {
934                                 sharpCount++;
935                                 avgSharpness += sharpness;
936                         }
937                         else {
938                                 allSharp = 0;
939                         }
940                 }
941
942                 if (sharpCount) {
943                         avgSharpness /= sharpCount;
944                         if (avgSharpness > 1.0f) {
945                                 avgSharpness = 1.0f;
946                         }
947                 }
948
949                 if (seamEdges < 2 || seamEdges != v->numEdges)
950                         seam = 0;
951
952                 if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
953                         VertDataCopy(nCo, co, ss);
954                 }
955                 else if (_vert_isBoundary(v)) {
956                         int numBoundary = 0;
957
958                         VertDataZero(r, ss);
959                         for (i = 0; i < v->numEdges; i++) {
960                                 CCGEdge *e = v->edges[i];
961                                 if (_edge_isBoundary(e)) {
962                                         VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
963                                         numBoundary++;
964                                 }
965                         }
966                         VertDataCopy(nCo, co, ss);
967                         VertDataMulN(nCo, 0.75f, ss);
968                         VertDataMulN(r, 0.25f / numBoundary, ss);
969                         VertDataAdd(nCo, r, ss);
970                 }
971                 else {
972                         int numEdges = 0, numFaces = 0;
973
974                         VertDataZero(q, ss);
975                         for (i = 0; i < v->numFaces; i++) {
976                                 CCGFace *f = v->faces[i];
977                                 VertDataAdd(q, (float *)FACE_getCenterData(f), ss);
978                                 numFaces++;
979                         }
980                         VertDataMulN(q, 1.0f / numFaces, ss);
981                         VertDataZero(r, ss);
982                         for (i = 0; i < v->numEdges; i++) {
983                                 CCGEdge *e = v->edges[i];
984                                 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
985                                 numEdges++;
986                         }
987                         VertDataMulN(r, 1.0f / numEdges, ss);
988
989                         VertDataCopy(nCo, co, ss);
990                         VertDataMulN(nCo, numEdges - 2.0f, ss);
991                         VertDataAdd(nCo, q, ss);
992                         VertDataAdd(nCo, r, ss);
993                         VertDataMulN(nCo, 1.0f / numEdges, ss);
994                 }
995
996                 if (sharpCount > 1 || seam) {
997                         VertDataZero(q, ss);
998
999                         if (seam) {
1000                                 avgSharpness = 1.0f;
1001                                 sharpCount = seamEdges;
1002                                 allSharp = 1;
1003                         }
1004
1005                         for (i = 0; i < v->numEdges; i++) {
1006                                 CCGEdge *e = v->edges[i];
1007                                 float sharpness = EDGE_getSharpness(e, curLvl);
1008
1009                                 if (seam) {
1010                                         if (_edge_isBoundary(e)) {
1011                                                 CCGVert *oV = _edge_getOtherVert(e, v);
1012                                                 VertDataAdd(q, VERT_getCo(oV, curLvl), ss);
1013                                         }
1014                                 }
1015                                 else if (sharpness != 0.0f) {
1016                                         CCGVert *oV = _edge_getOtherVert(e, v);
1017                                         VertDataAdd(q, VERT_getCo(oV, curLvl), ss);
1018                                 }
1019                         }
1020
1021                         VertDataMulN(q, (float) 1 / sharpCount, ss);
1022
1023                         if (sharpCount != 2 || allSharp) {
1024                                 /* q = q + (co - q) * avgSharpness */
1025                                 VertDataCopy(r, co, ss);
1026                                 VertDataSub(r, q, ss);
1027                                 VertDataMulN(r, avgSharpness, ss);
1028                                 VertDataAdd(q, r, ss);
1029                         }
1030
1031                         /* r = co * 0.75 + q * 0.25 */
1032                         VertDataCopy(r, co, ss);
1033                         VertDataMulN(r, 0.75f, ss);
1034                         VertDataMulN(q, 0.25f, ss);
1035                         VertDataAdd(r, q, ss);
1036
1037                         /* nCo = nCo + (r - nCo) * avgSharpness */
1038                         VertDataSub(r, nCo, ss);
1039                         VertDataMulN(r, avgSharpness, ss);
1040                         VertDataAdd(nCo, r, ss);
1041                 }
1042
1043                 /* vert flags cleared later */
1044         }
1045
1046         if (ss->useAgeCounts) {
1047                 for (i = 0; i < numEffectedV; i++) {
1048                         CCGVert *v = effectedV[i];
1049                         byte *userData = ccgSubSurf_getVertUserData(ss, v);
1050                         *((int *) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
1051                 }
1052
1053                 for (i = 0; i < numEffectedE; i++) {
1054                         CCGEdge *e = effectedE[i];
1055                         byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
1056                         *((int *) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
1057                 }
1058
1059                 for (i = 0; i < numEffectedF; i++) {
1060                         CCGFace *f = effectedF[i];
1061                         byte *userData = ccgSubSurf_getFaceUserData(ss, f);
1062                         *((int *) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
1063                 }
1064         }
1065
1066         for (i = 0; i < numEffectedE; i++) {
1067                 CCGEdge *e = effectedE[i];
1068                 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
1069                 VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl), ss);
1070         }
1071         for (i = 0; i < numEffectedF; i++) {
1072                 CCGFace *f = effectedF[i];
1073                 for (S = 0; S < f->numVerts; S++) {
1074                         CCGEdge *e = FACE_getEdges(f)[S];
1075                         CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
1076
1077                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
1078                         VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
1079                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl), ss);
1080                         VertDataCopy(FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1), ss);
1081
1082                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize), ss);
1083                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize), ss);
1084                 }
1085         }
1086
1087         for (curLvl = 1; curLvl < subdivLevels; curLvl++)
1088                 ccgSubSurf__calcSubdivLevel(ss,
1089                                             effectedV, effectedE, effectedF,
1090                                             numEffectedV, numEffectedE, numEffectedF, curLvl);
1091
1092         if (ss->calcVertNormals)
1093                 ccgSubSurf__calcVertNormals(ss,
1094                                             effectedV, effectedE, effectedF,
1095                                             numEffectedV, numEffectedE, numEffectedF);
1096
1097         for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
1098                 CCGVert *v = effectedV[ptrIdx];
1099                 v->flags = 0;
1100         }
1101         for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
1102                 CCGEdge *e = effectedE[ptrIdx];
1103                 e->flags = 0;
1104         }
1105
1106         MEM_freeN(effectedF);
1107         MEM_freeN(effectedE);
1108         MEM_freeN(effectedV);
1109
1110 #ifdef DUMP_RESULT_GRIDS
1111         ccgSubSurf__dumpCoords(ss);
1112 #endif
1113 }
1114
1115 /* ** Public API exposed to other areas which depends on old CCG code. ** */
1116
1117 /* Update normals for specified faces. */
1118 CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF)
1119 {
1120         CCGVert **effectedV;
1121         CCGEdge **effectedE;
1122         int i, numEffectedV, numEffectedE, freeF;
1123
1124         ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
1125         ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
1126                                            &effectedV, &numEffectedV, &effectedE, &numEffectedE);
1127
1128         if (ss->calcVertNormals)
1129                 ccgSubSurf__calcVertNormals(ss,
1130                                             effectedV, effectedE, effectedF,
1131                                             numEffectedV, numEffectedE, numEffectedF);
1132
1133         for (i = 0; i < numEffectedV; i++)
1134                 effectedV[i]->flags = 0;
1135         for (i = 0; i < numEffectedE; i++)
1136                 effectedE[i]->flags = 0;
1137         for (i = 0; i < numEffectedF; i++)
1138                 effectedF[i]->flags = 0;
1139
1140         MEM_freeN(effectedE);
1141         MEM_freeN(effectedV);
1142         if (freeF) MEM_freeN(effectedF);
1143
1144         return eCCGError_None;
1145 }
1146
1147 /* compute subdivision levels from a given starting point, used by
1148  * multires subdivide/propagate, by filling in coordinates at a
1149  * certain level, and then subdividing that up to the highest level */
1150 CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
1151 {
1152         CCGVert **effectedV;
1153         CCGEdge **effectedE;
1154         int numEffectedV, numEffectedE, freeF, i;
1155         int curLvl, subdivLevels = ss->subdivLevels;
1156
1157         ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
1158         ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
1159                                            &effectedV, &numEffectedV, &effectedE, &numEffectedE);
1160
1161         for (curLvl = lvl; curLvl < subdivLevels; curLvl++) {
1162                 ccgSubSurf__calcSubdivLevel(ss,
1163                                             effectedV, effectedE, effectedF,
1164                                             numEffectedV, numEffectedE, numEffectedF, curLvl);
1165         }
1166
1167         for (i = 0; i < numEffectedV; i++)
1168                 effectedV[i]->flags = 0;
1169         for (i = 0; i < numEffectedE; i++)
1170                 effectedE[i]->flags = 0;
1171         for (i = 0; i < numEffectedF; i++)
1172                 effectedF[i]->flags = 0;
1173
1174         MEM_freeN(effectedE);
1175         MEM_freeN(effectedV);
1176         if (freeF) MEM_freeN(effectedF);
1177
1178         return eCCGError_None;
1179 }