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