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