1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup bke
19  */
20 
21 #include <math.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "BLI_sys_types.h" /* for intptr_t support */
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_utildefines.h" /* for BLI_assert */
29 
30 #include "BKE_ccg.h"
31 #include "BKE_subsurf.h"
32 #include "CCGSubSurf.h"
33 #include "CCGSubSurf_intern.h"
34 
35 /***/
36 
BKE_ccg_gridsize(int level)37 int BKE_ccg_gridsize(int level)
38 {
39   return ccg_gridsize(level);
40 }
41 
BKE_ccg_factor(int low_level,int high_level)42 int BKE_ccg_factor(int low_level, int high_level)
43 {
44   BLI_assert(low_level > 0 && high_level > 0);
45   BLI_assert(low_level <= high_level);
46 
47   return 1 << (high_level - low_level);
48 }
49 
50 /***/
51 
_vert_new(CCGVertHDL vHDL,CCGSubSurf * ss)52 static CCGVert *_vert_new(CCGVertHDL vHDL, CCGSubSurf *ss)
53 {
54   int num_vert_data = ss->subdivLevels + 1;
55   CCGVert *v = CCGSUBSURF_alloc(
56       ss, sizeof(CCGVert) + ss->meshIFC.vertDataSize * num_vert_data + ss->meshIFC.vertUserSize);
57   byte *userData;
58 
59   v->vHDL = vHDL;
60   v->edges = NULL;
61   v->faces = NULL;
62   v->numEdges = v->numFaces = 0;
63   v->flags = 0;
64 
65   userData = ccgSubSurf_getVertUserData(ss, v);
66   memset(userData, 0, ss->meshIFC.vertUserSize);
67   if (ss->useAgeCounts) {
68     *((int *)&userData[ss->vertUserAgeOffset]) = ss->currentAge;
69   }
70 
71   return v;
72 }
_vert_remEdge(CCGVert * v,CCGEdge * e)73 static void _vert_remEdge(CCGVert *v, CCGEdge *e)
74 {
75   for (int i = 0; i < v->numEdges; i++) {
76     if (v->edges[i] == e) {
77       v->edges[i] = v->edges[--v->numEdges];
78       break;
79     }
80   }
81 }
_vert_remFace(CCGVert * v,CCGFace * f)82 static void _vert_remFace(CCGVert *v, CCGFace *f)
83 {
84   for (int i = 0; i < v->numFaces; i++) {
85     if (v->faces[i] == f) {
86       v->faces[i] = v->faces[--v->numFaces];
87       break;
88     }
89   }
90 }
_vert_addEdge(CCGVert * v,CCGEdge * e,CCGSubSurf * ss)91 static void _vert_addEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss)
92 {
93   v->edges = CCGSUBSURF_realloc(
94       ss, v->edges, (v->numEdges + 1) * sizeof(*v->edges), v->numEdges * sizeof(*v->edges));
95   v->edges[v->numEdges++] = e;
96 }
_vert_addFace(CCGVert * v,CCGFace * f,CCGSubSurf * ss)97 static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss)
98 {
99   v->faces = CCGSUBSURF_realloc(
100       ss, v->faces, (v->numFaces + 1) * sizeof(*v->faces), v->numFaces * sizeof(*v->faces));
101   v->faces[v->numFaces++] = f;
102 }
_vert_findEdgeTo(const CCGVert * v,const CCGVert * vQ)103 static CCGEdge *_vert_findEdgeTo(const CCGVert *v, const CCGVert *vQ)
104 {
105   for (int i = 0; i < v->numEdges; i++) {
106     CCGEdge *e = v->edges[v->numEdges - 1 - i];  // XXX, note reverse
107     if ((e->v0 == v && e->v1 == vQ) || (e->v1 == v && e->v0 == vQ)) {
108       return e;
109     }
110   }
111   return NULL;
112 }
_vert_free(CCGVert * v,CCGSubSurf * ss)113 static void _vert_free(CCGVert *v, CCGSubSurf *ss)
114 {
115   if (v->edges) {
116     CCGSUBSURF_free(ss, v->edges);
117   }
118 
119   if (v->faces) {
120     CCGSUBSURF_free(ss, v->faces);
121   }
122 
123   CCGSUBSURF_free(ss, v);
124 }
125 
126 /***/
127 
_edge_new(CCGEdgeHDL eHDL,CCGVert * v0,CCGVert * v1,float crease,CCGSubSurf * ss)128 static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, CCGSubSurf *ss)
129 {
130   int num_edge_data = ccg_edgebase(ss->subdivLevels + 1);
131   CCGEdge *e = CCGSUBSURF_alloc(
132       ss, sizeof(CCGEdge) + ss->meshIFC.vertDataSize * num_edge_data + ss->meshIFC.edgeUserSize);
133   byte *userData;
134 
135   e->eHDL = eHDL;
136   e->v0 = v0;
137   e->v1 = v1;
138   e->crease = crease;
139   e->faces = NULL;
140   e->numFaces = 0;
141   e->flags = 0;
142   _vert_addEdge(v0, e, ss);
143   _vert_addEdge(v1, e, ss);
144 
145   userData = ccgSubSurf_getEdgeUserData(ss, e);
146   memset(userData, 0, ss->meshIFC.edgeUserSize);
147   if (ss->useAgeCounts) {
148     *((int *)&userData[ss->edgeUserAgeOffset]) = ss->currentAge;
149   }
150 
151   return e;
152 }
_edge_remFace(CCGEdge * e,CCGFace * f)153 static void _edge_remFace(CCGEdge *e, CCGFace *f)
154 {
155   for (int i = 0; i < e->numFaces; i++) {
156     if (e->faces[i] == f) {
157       e->faces[i] = e->faces[--e->numFaces];
158       break;
159     }
160   }
161 }
_edge_addFace(CCGEdge * e,CCGFace * f,CCGSubSurf * ss)162 static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss)
163 {
164   e->faces = CCGSUBSURF_realloc(
165       ss, e->faces, (e->numFaces + 1) * sizeof(*e->faces), e->numFaces * sizeof(*e->faces));
166   e->faces[e->numFaces++] = f;
167 }
_edge_getCoVert(CCGEdge * e,CCGVert * v,int lvl,int x,int dataSize)168 static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize)
169 {
170   int levelBase = ccg_edgebase(lvl);
171   if (v == e->v0) {
172     return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
173   }
174   return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)];
175 }
176 
_edge_free(CCGEdge * e,CCGSubSurf * ss)177 static void _edge_free(CCGEdge *e, CCGSubSurf *ss)
178 {
179   if (e->faces) {
180     CCGSUBSURF_free(ss, e->faces);
181   }
182 
183   CCGSUBSURF_free(ss, e);
184 }
_edge_unlinkMarkAndFree(CCGEdge * e,CCGSubSurf * ss)185 static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss)
186 {
187   _vert_remEdge(e->v0, e);
188   _vert_remEdge(e->v1, e);
189   e->v0->flags |= Vert_eEffected;
190   e->v1->flags |= Vert_eEffected;
191   _edge_free(e, ss);
192 }
193 
_face_new(CCGFaceHDL fHDL,CCGVert ** verts,CCGEdge ** edges,int numVerts,CCGSubSurf * ss)194 static CCGFace *_face_new(
195     CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, CCGSubSurf *ss)
196 {
197   int maxGridSize = ccg_gridsize(ss->subdivLevels);
198   int num_face_data = (numVerts * maxGridSize + numVerts * maxGridSize * maxGridSize + 1);
199   CCGFace *f = CCGSUBSURF_alloc(
200       ss,
201       sizeof(CCGFace) + sizeof(CCGVert *) * numVerts + sizeof(CCGEdge *) * numVerts +
202           ss->meshIFC.vertDataSize * num_face_data + ss->meshIFC.faceUserSize);
203   byte *userData;
204 
205   f->numVerts = numVerts;
206   f->fHDL = fHDL;
207   f->flags = 0;
208 
209   for (int i = 0; i < numVerts; i++) {
210     FACE_getVerts(f)[i] = verts[i];
211     FACE_getEdges(f)[i] = edges[i];
212     _vert_addFace(verts[i], f, ss);
213     _edge_addFace(edges[i], f, ss);
214   }
215 
216   userData = ccgSubSurf_getFaceUserData(ss, f);
217   memset(userData, 0, ss->meshIFC.faceUserSize);
218   if (ss->useAgeCounts) {
219     *((int *)&userData[ss->faceUserAgeOffset]) = ss->currentAge;
220   }
221 
222   return f;
223 }
_face_free(CCGFace * f,CCGSubSurf * ss)224 static void _face_free(CCGFace *f, CCGSubSurf *ss)
225 {
226   CCGSUBSURF_free(ss, f);
227 }
_face_unlinkMarkAndFree(CCGFace * f,CCGSubSurf * ss)228 static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss)
229 {
230   int j;
231   for (j = 0; j < f->numVerts; j++) {
232     _vert_remFace(FACE_getVerts(f)[j], f);
233     _edge_remFace(FACE_getEdges(f)[j], f);
234     FACE_getVerts(f)[j]->flags |= Vert_eEffected;
235   }
236   _face_free(f, ss);
237 }
238 
239 /***/
240 
ccgSubSurf_new(CCGMeshIFC * ifc,int subdivLevels,CCGAllocatorIFC * allocatorIFC,CCGAllocatorHDL allocator)241 CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc,
242                            int subdivLevels,
243                            CCGAllocatorIFC *allocatorIFC,
244                            CCGAllocatorHDL allocator)
245 {
246   if (!allocatorIFC) {
247     allocatorIFC = ccg_getStandardAllocatorIFC();
248     allocator = NULL;
249   }
250 
251   if (subdivLevels < 1) {
252     return NULL;
253   }
254 
255   CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss));
256 
257   ss->allocatorIFC = *allocatorIFC;
258   ss->allocator = allocator;
259 
260   ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
261   ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
262   ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
263 
264   ss->meshIFC = *ifc;
265 
266   ss->subdivLevels = subdivLevels;
267   ss->numGrids = 0;
268   ss->allowEdgeCreation = 0;
269   ss->defaultCreaseValue = 0;
270   ss->defaultEdgeUserData = NULL;
271 
272   ss->useAgeCounts = 0;
273   ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
274 
275   ss->calcVertNormals = 0;
276   ss->normalDataOffset = 0;
277 
278   ss->allocMask = 0;
279 
280   ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
281   ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
282 
283   ss->currentAge = 0;
284 
285   ss->syncState = eSyncState_None;
286 
287   ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL;
288   ss->lenTempArrays = 0;
289   ss->tempVerts = NULL;
290   ss->tempEdges = NULL;
291 
292   return ss;
293 }
294 
ccgSubSurf_free(CCGSubSurf * ss)295 void ccgSubSurf_free(CCGSubSurf *ss)
296 {
297   CCGAllocatorIFC allocatorIFC = ss->allocatorIFC;
298   CCGAllocatorHDL allocator = ss->allocator;
299 
300   if (ss->syncState) {
301     ccg_ehash_free(ss->oldFMap, (EHEntryFreeFP)_face_free, ss);
302     ccg_ehash_free(ss->oldEMap, (EHEntryFreeFP)_edge_free, ss);
303     ccg_ehash_free(ss->oldVMap, (EHEntryFreeFP)_vert_free, ss);
304 
305     MEM_freeN(ss->tempVerts);
306     MEM_freeN(ss->tempEdges);
307   }
308 
309   CCGSUBSURF_free(ss, ss->r);
310   CCGSUBSURF_free(ss, ss->q);
311   if (ss->defaultEdgeUserData) {
312     CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
313   }
314 
315   ccg_ehash_free(ss->fMap, (EHEntryFreeFP)_face_free, ss);
316   ccg_ehash_free(ss->eMap, (EHEntryFreeFP)_edge_free, ss);
317   ccg_ehash_free(ss->vMap, (EHEntryFreeFP)_vert_free, ss);
318 
319   CCGSUBSURF_free(ss, ss);
320 
321   if (allocatorIFC.release) {
322     allocatorIFC.release(allocator);
323   }
324 }
325 
ccgSubSurf_setAllowEdgeCreation(CCGSubSurf * ss,int allowEdgeCreation,float defaultCreaseValue,void * defaultUserData)326 CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss,
327                                          int allowEdgeCreation,
328                                          float defaultCreaseValue,
329                                          void *defaultUserData)
330 {
331   if (ss->defaultEdgeUserData) {
332     CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
333   }
334 
335   ss->allowEdgeCreation = !!allowEdgeCreation;
336   ss->defaultCreaseValue = defaultCreaseValue;
337   ss->defaultEdgeUserData = CCGSUBSURF_alloc(ss, ss->meshIFC.edgeUserSize);
338 
339   if (defaultUserData) {
340     memcpy(ss->defaultEdgeUserData, defaultUserData, ss->meshIFC.edgeUserSize);
341   }
342   else {
343     memset(ss->defaultEdgeUserData, 0, ss->meshIFC.edgeUserSize);
344   }
345 
346   return eCCGError_None;
347 }
ccgSubSurf_getAllowEdgeCreation(CCGSubSurf * ss,int * allowEdgeCreation_r,float * defaultCreaseValue_r,void * defaultUserData_r)348 void ccgSubSurf_getAllowEdgeCreation(CCGSubSurf *ss,
349                                      int *allowEdgeCreation_r,
350                                      float *defaultCreaseValue_r,
351                                      void *defaultUserData_r)
352 {
353   if (allowEdgeCreation_r) {
354     *allowEdgeCreation_r = ss->allowEdgeCreation;
355   }
356   if (ss->allowEdgeCreation) {
357     if (defaultCreaseValue_r) {
358       *defaultCreaseValue_r = ss->defaultCreaseValue;
359     }
360     if (defaultUserData_r) {
361       memcpy(defaultUserData_r, ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
362     }
363   }
364 }
365 
ccgSubSurf_setSubdivisionLevels(CCGSubSurf * ss,int subdivisionLevels)366 CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels)
367 {
368   if (subdivisionLevels <= 0) {
369     return eCCGError_InvalidValue;
370   }
371   if (subdivisionLevels != ss->subdivLevels) {
372     ss->numGrids = 0;
373     ss->subdivLevels = subdivisionLevels;
374     ccg_ehash_free(ss->vMap, (EHEntryFreeFP)_vert_free, ss);
375     ccg_ehash_free(ss->eMap, (EHEntryFreeFP)_edge_free, ss);
376     ccg_ehash_free(ss->fMap, (EHEntryFreeFP)_face_free, ss);
377     ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
378     ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
379     ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
380   }
381 
382   return eCCGError_None;
383 }
384 
ccgSubSurf_getUseAgeCounts(CCGSubSurf * ss,int * useAgeCounts_r,int * vertUserOffset_r,int * edgeUserOffset_r,int * faceUserOffset_r)385 void ccgSubSurf_getUseAgeCounts(CCGSubSurf *ss,
386                                 int *useAgeCounts_r,
387                                 int *vertUserOffset_r,
388                                 int *edgeUserOffset_r,
389                                 int *faceUserOffset_r)
390 {
391   *useAgeCounts_r = ss->useAgeCounts;
392 
393   if (vertUserOffset_r) {
394     *vertUserOffset_r = ss->vertUserAgeOffset;
395   }
396   if (edgeUserOffset_r) {
397     *edgeUserOffset_r = ss->edgeUserAgeOffset;
398   }
399   if (faceUserOffset_r) {
400     *faceUserOffset_r = ss->faceUserAgeOffset;
401   }
402 }
403 
ccgSubSurf_setUseAgeCounts(CCGSubSurf * ss,int useAgeCounts,int vertUserOffset,int edgeUserOffset,int faceUserOffset)404 CCGError ccgSubSurf_setUseAgeCounts(
405     CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset)
406 {
407   if (useAgeCounts) {
408     if ((vertUserOffset + 4 > ss->meshIFC.vertUserSize) ||
409         (edgeUserOffset + 4 > ss->meshIFC.edgeUserSize) ||
410         (faceUserOffset + 4 > ss->meshIFC.faceUserSize)) {
411       return eCCGError_InvalidValue;
412     }
413     ss->useAgeCounts = 1;
414     ss->vertUserAgeOffset = vertUserOffset;
415     ss->edgeUserAgeOffset = edgeUserOffset;
416     ss->faceUserAgeOffset = faceUserOffset;
417   }
418   else {
419     ss->useAgeCounts = 0;
420     ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
421   }
422 
423   return eCCGError_None;
424 }
425 
ccgSubSurf_setCalcVertexNormals(CCGSubSurf * ss,int useVertNormals,int normalDataOffset)426 CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset)
427 {
428   if (useVertNormals) {
429     if (normalDataOffset < 0 || normalDataOffset + 12 > ss->meshIFC.vertDataSize) {
430       return eCCGError_InvalidValue;
431     }
432     ss->calcVertNormals = 1;
433     ss->normalDataOffset = normalDataOffset;
434   }
435   else {
436     ss->calcVertNormals = 0;
437     ss->normalDataOffset = 0;
438   }
439 
440   return eCCGError_None;
441 }
442 
ccgSubSurf_setAllocMask(CCGSubSurf * ss,int allocMask,int maskOffset)443 void ccgSubSurf_setAllocMask(CCGSubSurf *ss, int allocMask, int maskOffset)
444 {
445   ss->allocMask = allocMask;
446   ss->maskDataOffset = maskOffset;
447 }
448 
ccgSubSurf_setNumLayers(CCGSubSurf * ss,int numLayers)449 void ccgSubSurf_setNumLayers(CCGSubSurf *ss, int numLayers)
450 {
451   ss->meshIFC.numLayers = numLayers;
452 }
453 
454 /***/
455 
ccgSubSurf_initFullSync(CCGSubSurf * ss)456 CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss)
457 {
458   if (ss->syncState != eSyncState_None) {
459     return eCCGError_InvalidSyncState;
460   }
461 
462   ss->currentAge++;
463 
464   ss->oldVMap = ss->vMap;
465   ss->oldEMap = ss->eMap;
466   ss->oldFMap = ss->fMap;
467 
468   ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
469   ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
470   ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
471 
472   ss->numGrids = 0;
473 
474   ss->lenTempArrays = 12;
475   ss->tempVerts = MEM_mallocN(sizeof(*ss->tempVerts) * ss->lenTempArrays, "CCGSubsurf tempVerts");
476   ss->tempEdges = MEM_mallocN(sizeof(*ss->tempEdges) * ss->lenTempArrays, "CCGSubsurf tempEdges");
477 
478   ss->syncState = eSyncState_Vert;
479 
480   return eCCGError_None;
481 }
482 
ccgSubSurf_initPartialSync(CCGSubSurf * ss)483 CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss)
484 {
485   if (ss->syncState != eSyncState_None) {
486     return eCCGError_InvalidSyncState;
487   }
488 
489   ss->currentAge++;
490 
491   ss->syncState = eSyncState_Partial;
492 
493   return eCCGError_None;
494 }
495 
ccgSubSurf_syncVertDel(CCGSubSurf * ss,CCGVertHDL vHDL)496 CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL)
497 {
498   if (ss->syncState != eSyncState_Partial) {
499     return eCCGError_InvalidSyncState;
500   }
501 
502   void **prevp;
503   CCGVert *v = ccg_ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
504 
505   if (!v || v->numFaces || v->numEdges) {
506     return eCCGError_InvalidValue;
507   }
508 
509   *prevp = v->next;
510   _vert_free(v, ss);
511 
512   return eCCGError_None;
513 }
514 
ccgSubSurf_syncEdgeDel(CCGSubSurf * ss,CCGEdgeHDL eHDL)515 CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL)
516 {
517   if (ss->syncState != eSyncState_Partial) {
518     return eCCGError_InvalidSyncState;
519   }
520 
521   void **prevp;
522   CCGEdge *e = ccg_ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
523 
524   if (!e || e->numFaces) {
525     return eCCGError_InvalidValue;
526   }
527 
528   *prevp = e->next;
529   _edge_unlinkMarkAndFree(e, ss);
530 
531   return eCCGError_None;
532 }
533 
ccgSubSurf_syncFaceDel(CCGSubSurf * ss,CCGFaceHDL fHDL)534 CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL)
535 {
536   if (ss->syncState != eSyncState_Partial) {
537     return eCCGError_InvalidSyncState;
538   }
539 
540   void **prevp;
541   CCGFace *f = ccg_ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
542 
543   if (!f) {
544     return eCCGError_InvalidValue;
545   }
546 
547   *prevp = f->next;
548   _face_unlinkMarkAndFree(f, ss);
549 
550   return eCCGError_None;
551 }
552 
ccgSubSurf_syncVert(CCGSubSurf * ss,CCGVertHDL vHDL,const void * vertData,int seam,CCGVert ** v_r)553 CCGError ccgSubSurf_syncVert(
554     CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r)
555 {
556   void **prevp;
557   CCGVert *v = NULL;
558   short seamflag = (seam) ? Vert_eSeam : 0;
559 
560   if (ss->syncState == eSyncState_Partial) {
561     v = ccg_ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
562     if (!v) {
563       v = _vert_new(vHDL, ss);
564       VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
565       ccg_ehash_insert(ss->vMap, (EHEntry *)v);
566       v->flags = Vert_eEffected | seamflag;
567     }
568     else if (!VertDataEqual(vertData, ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), ss) ||
569              ((v->flags & Vert_eSeam) != seamflag)) {
570       int i, j;
571 
572       VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
573       v->flags = Vert_eEffected | seamflag;
574 
575       for (i = 0; i < v->numEdges; i++) {
576         CCGEdge *e = v->edges[i];
577         e->v0->flags |= Vert_eEffected;
578         e->v1->flags |= Vert_eEffected;
579       }
580       for (i = 0; i < v->numFaces; i++) {
581         CCGFace *f = v->faces[i];
582         for (j = 0; j < f->numVerts; j++) {
583           FACE_getVerts(f)[j]->flags |= Vert_eEffected;
584         }
585       }
586     }
587   }
588   else {
589     if (ss->syncState != eSyncState_Vert) {
590       return eCCGError_InvalidSyncState;
591     }
592 
593     v = ccg_ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp);
594     if (!v) {
595       v = _vert_new(vHDL, ss);
596       VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
597       ccg_ehash_insert(ss->vMap, (EHEntry *)v);
598       v->flags = Vert_eEffected | seamflag;
599     }
600     else if (!VertDataEqual(vertData, ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), ss) ||
601              ((v->flags & Vert_eSeam) != seamflag)) {
602       *prevp = v->next;
603       ccg_ehash_insert(ss->vMap, (EHEntry *)v);
604       VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
605       v->flags = Vert_eEffected | Vert_eChanged | seamflag;
606     }
607     else {
608       *prevp = v->next;
609       ccg_ehash_insert(ss->vMap, (EHEntry *)v);
610       v->flags = 0;
611     }
612   }
613 
614   if (v_r) {
615     *v_r = v;
616   }
617   return eCCGError_None;
618 }
619 
ccgSubSurf_syncEdge(CCGSubSurf * ss,CCGEdgeHDL eHDL,CCGVertHDL e_vHDL0,CCGVertHDL e_vHDL1,float crease,CCGEdge ** e_r)620 CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss,
621                              CCGEdgeHDL eHDL,
622                              CCGVertHDL e_vHDL0,
623                              CCGVertHDL e_vHDL1,
624                              float crease,
625                              CCGEdge **e_r)
626 {
627   void **prevp;
628   CCGEdge *e = NULL, *eNew;
629 
630   if (ss->syncState == eSyncState_Partial) {
631     e = ccg_ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
632     if (!e || e->v0->vHDL != e_vHDL0 || e->v1->vHDL != e_vHDL1 || crease != e->crease) {
633       CCGVert *v0 = ccg_ehash_lookup(ss->vMap, e_vHDL0);
634       CCGVert *v1 = ccg_ehash_lookup(ss->vMap, e_vHDL1);
635 
636       eNew = _edge_new(eHDL, v0, v1, crease, ss);
637 
638       if (e) {
639         *prevp = eNew;
640         eNew->next = e->next;
641 
642         _edge_unlinkMarkAndFree(e, ss);
643       }
644       else {
645         ccg_ehash_insert(ss->eMap, (EHEntry *)eNew);
646       }
647 
648       eNew->v0->flags |= Vert_eEffected;
649       eNew->v1->flags |= Vert_eEffected;
650     }
651   }
652   else {
653     if (ss->syncState == eSyncState_Vert) {
654       ss->syncState = eSyncState_Edge;
655     }
656     else if (ss->syncState != eSyncState_Edge) {
657       return eCCGError_InvalidSyncState;
658     }
659 
660     e = ccg_ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
661     if (!e || e->v0->vHDL != e_vHDL0 || e->v1->vHDL != e_vHDL1 || e->crease != crease) {
662       CCGVert *v0 = ccg_ehash_lookup(ss->vMap, e_vHDL0);
663       CCGVert *v1 = ccg_ehash_lookup(ss->vMap, e_vHDL1);
664       e = _edge_new(eHDL, v0, v1, crease, ss);
665       ccg_ehash_insert(ss->eMap, (EHEntry *)e);
666       e->v0->flags |= Vert_eEffected;
667       e->v1->flags |= Vert_eEffected;
668     }
669     else {
670       *prevp = e->next;
671       ccg_ehash_insert(ss->eMap, (EHEntry *)e);
672       e->flags = 0;
673       if ((e->v0->flags | e->v1->flags) & Vert_eChanged) {
674         e->v0->flags |= Vert_eEffected;
675         e->v1->flags |= Vert_eEffected;
676       }
677     }
678   }
679 
680   if (e_r) {
681     *e_r = e;
682   }
683   return eCCGError_None;
684 }
685 
ccgSubSurf_syncFace(CCGSubSurf * ss,CCGFaceHDL fHDL,int numVerts,CCGVertHDL * vHDLs,CCGFace ** f_r)686 CCGError ccgSubSurf_syncFace(
687     CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r)
688 {
689   void **prevp;
690   CCGFace *f = NULL, *fNew;
691   int j, k, topologyChanged = 0;
692 
693   if (UNLIKELY(numVerts > ss->lenTempArrays)) {
694     ss->lenTempArrays = (numVerts < ss->lenTempArrays * 2) ? ss->lenTempArrays * 2 : numVerts;
695     ss->tempVerts = MEM_reallocN(ss->tempVerts, sizeof(*ss->tempVerts) * ss->lenTempArrays);
696     ss->tempEdges = MEM_reallocN(ss->tempEdges, sizeof(*ss->tempEdges) * ss->lenTempArrays);
697   }
698 
699   if (ss->syncState == eSyncState_Partial) {
700     f = ccg_ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
701 
702     for (k = 0; k < numVerts; k++) {
703       ss->tempVerts[k] = ccg_ehash_lookup(ss->vMap, vHDLs[k]);
704     }
705     for (k = 0; k < numVerts; k++) {
706       ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k + 1) % numVerts]);
707     }
708 
709     if (f) {
710       if (f->numVerts != numVerts ||
711           memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts) * numVerts) != 0 ||
712           memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges) * numVerts) != 0) {
713         topologyChanged = 1;
714       }
715     }
716 
717     if (!f || topologyChanged) {
718       fNew = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss);
719 
720       if (f) {
721         ss->numGrids += numVerts - f->numVerts;
722 
723         *prevp = fNew;
724         fNew->next = f->next;
725 
726         _face_unlinkMarkAndFree(f, ss);
727       }
728       else {
729         ss->numGrids += numVerts;
730         ccg_ehash_insert(ss->fMap, (EHEntry *)fNew);
731       }
732 
733       for (k = 0; k < numVerts; k++) {
734         FACE_getVerts(fNew)[k]->flags |= Vert_eEffected;
735       }
736     }
737   }
738   else {
739     if (ss->syncState == eSyncState_Vert || ss->syncState == eSyncState_Edge) {
740       ss->syncState = eSyncState_Face;
741     }
742     else if (ss->syncState != eSyncState_Face) {
743       return eCCGError_InvalidSyncState;
744     }
745 
746     f = ccg_ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp);
747 
748     for (k = 0; k < numVerts; k++) {
749       ss->tempVerts[k] = ccg_ehash_lookup(ss->vMap, vHDLs[k]);
750 
751       if (!ss->tempVerts[k]) {
752         return eCCGError_InvalidValue;
753       }
754     }
755     for (k = 0; k < numVerts; k++) {
756       ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k + 1) % numVerts]);
757 
758       if (!ss->tempEdges[k]) {
759         if (ss->allowEdgeCreation) {
760           CCGEdge *e = ss->tempEdges[k] = _edge_new((CCGEdgeHDL)-1,
761                                                     ss->tempVerts[k],
762                                                     ss->tempVerts[(k + 1) % numVerts],
763                                                     ss->defaultCreaseValue,
764                                                     ss);
765           ccg_ehash_insert(ss->eMap, (EHEntry *)e);
766           e->v0->flags |= Vert_eEffected;
767           e->v1->flags |= Vert_eEffected;
768           if (ss->meshIFC.edgeUserSize) {
769             memcpy(ccgSubSurf_getEdgeUserData(ss, e),
770                    ss->defaultEdgeUserData,
771                    ss->meshIFC.edgeUserSize);
772           }
773         }
774         else {
775           return eCCGError_InvalidValue;
776         }
777       }
778     }
779 
780     if (f) {
781       if (f->numVerts != numVerts ||
782           memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts) * numVerts) != 0 ||
783           memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges) * numVerts) != 0) {
784         topologyChanged = 1;
785       }
786     }
787 
788     if (!f || topologyChanged) {
789       f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss);
790       ccg_ehash_insert(ss->fMap, (EHEntry *)f);
791       ss->numGrids += numVerts;
792 
793       for (k = 0; k < numVerts; k++) {
794         FACE_getVerts(f)[k]->flags |= Vert_eEffected;
795       }
796     }
797     else {
798       *prevp = f->next;
799       ccg_ehash_insert(ss->fMap, (EHEntry *)f);
800       f->flags = 0;
801       ss->numGrids += f->numVerts;
802 
803       for (j = 0; j < f->numVerts; j++) {
804         if (FACE_getVerts(f)[j]->flags & Vert_eChanged) {
805           for (k = 0; k < f->numVerts; k++) {
806             FACE_getVerts(f)[k]->flags |= Vert_eEffected;
807           }
808           break;
809         }
810       }
811     }
812   }
813 
814   if (f_r) {
815     *f_r = f;
816   }
817   return eCCGError_None;
818 }
819 
ccgSubSurf__sync(CCGSubSurf * ss)820 static void ccgSubSurf__sync(CCGSubSurf *ss)
821 {
822   ccgSubSurf__sync_legacy(ss);
823 }
824 
ccgSubSurf_processSync(CCGSubSurf * ss)825 CCGError ccgSubSurf_processSync(CCGSubSurf *ss)
826 {
827   if (ss->syncState == eSyncState_Partial) {
828     ss->syncState = eSyncState_None;
829 
830     ccgSubSurf__sync(ss);
831   }
832   else if (ss->syncState) {
833     ccg_ehash_free(ss->oldFMap, (EHEntryFreeFP)_face_unlinkMarkAndFree, ss);
834     ccg_ehash_free(ss->oldEMap, (EHEntryFreeFP)_edge_unlinkMarkAndFree, ss);
835     ccg_ehash_free(ss->oldVMap, (EHEntryFreeFP)_vert_free, ss);
836     MEM_freeN(ss->tempEdges);
837     MEM_freeN(ss->tempVerts);
838 
839     ss->lenTempArrays = 0;
840 
841     ss->oldFMap = ss->oldEMap = ss->oldVMap = NULL;
842     ss->tempVerts = NULL;
843     ss->tempEdges = NULL;
844 
845     ss->syncState = eSyncState_None;
846 
847     ccgSubSurf__sync(ss);
848   }
849   else {
850     return eCCGError_InvalidSyncState;
851   }
852 
853   return eCCGError_None;
854 }
855 
ccgSubSurf__allFaces(CCGSubSurf * ss,CCGFace *** faces,int * numFaces,int * freeFaces)856 void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces)
857 {
858   CCGFace **array;
859   int i, num;
860 
861   if (*faces == NULL) {
862     array = MEM_mallocN(sizeof(*array) * ss->fMap->numEntries, "CCGSubsurf allFaces");
863     num = 0;
864     for (i = 0; i < ss->fMap->curSize; i++) {
865       CCGFace *f = (CCGFace *)ss->fMap->buckets[i];
866 
867       for (; f; f = f->next) {
868         array[num++] = f;
869       }
870     }
871 
872     *faces = array;
873     *numFaces = num;
874     *freeFaces = 1;
875   }
876   else {
877     *freeFaces = 0;
878   }
879 }
880 
ccgSubSurf__effectedFaceNeighbors(CCGSubSurf * ss,CCGFace ** faces,int numFaces,CCGVert *** verts,int * numVerts,CCGEdge *** edges,int * numEdges)881 void ccgSubSurf__effectedFaceNeighbors(CCGSubSurf *ss,
882                                        CCGFace **faces,
883                                        int numFaces,
884                                        CCGVert ***verts,
885                                        int *numVerts,
886                                        CCGEdge ***edges,
887                                        int *numEdges)
888 {
889   CCGVert **arrayV;
890   CCGEdge **arrayE;
891   int numV, numE, i, j;
892 
893   arrayV = MEM_mallocN(sizeof(*arrayV) * ss->vMap->numEntries, "CCGSubsurf arrayV");
894   arrayE = MEM_mallocN(sizeof(*arrayE) * ss->eMap->numEntries, "CCGSubsurf arrayV");
895   numV = numE = 0;
896 
897   for (i = 0; i < numFaces; i++) {
898     CCGFace *f = faces[i];
899     f->flags |= Face_eEffected;
900   }
901 
902   for (i = 0; i < ss->vMap->curSize; i++) {
903     CCGVert *v = (CCGVert *)ss->vMap->buckets[i];
904 
905     for (; v; v = v->next) {
906       for (j = 0; j < v->numFaces; j++) {
907         if (!(v->faces[j]->flags & Face_eEffected)) {
908           break;
909         }
910       }
911 
912       if (j == v->numFaces) {
913         arrayV[numV++] = v;
914         v->flags |= Vert_eEffected;
915       }
916     }
917   }
918 
919   for (i = 0; i < ss->eMap->curSize; i++) {
920     CCGEdge *e = (CCGEdge *)ss->eMap->buckets[i];
921 
922     for (; e; e = e->next) {
923       for (j = 0; j < e->numFaces; j++) {
924         if (!(e->faces[j]->flags & Face_eEffected)) {
925           break;
926         }
927       }
928 
929       if (j == e->numFaces) {
930         e->flags |= Edge_eEffected;
931         arrayE[numE++] = e;
932       }
933     }
934   }
935 
936   *verts = arrayV;
937   *numVerts = numV;
938   *edges = arrayE;
939   *numEdges = numE;
940 }
941 
942 /* copy face grid coordinates to other places */
ccgSubSurf_updateFromFaces(CCGSubSurf * ss,int lvl,CCGFace ** effectedF,int numEffectedF)943 CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
944 {
945   int i, S, x, gridSize, cornerIdx, subdivLevels;
946   int vertDataSize = ss->meshIFC.vertDataSize, freeF;
947 
948   subdivLevels = ss->subdivLevels;
949   lvl = (lvl) ? lvl : subdivLevels;
950   gridSize = ccg_gridsize(lvl);
951   cornerIdx = gridSize - 1;
952 
953   ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
954 
955   for (i = 0; i < numEffectedF; i++) {
956     CCGFace *f = effectedF[i];
957 
958     for (S = 0; S < f->numVerts; S++) {
959       CCGEdge *e = FACE_getEdges(f)[S];
960       CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
961 
962       VertDataCopy((float *)FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0), ss);
963       VertDataCopy(
964           VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), ss);
965 
966       for (x = 0; x < gridSize; x++) {
967         VertDataCopy(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0), ss);
968       }
969 
970       for (x = 0; x < gridSize; x++) {
971         int eI = gridSize - 1 - x;
972         VertDataCopy(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
973                      FACE_getIFCo(f, lvl, S, cornerIdx, x),
974                      ss);
975         VertDataCopy(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
976                      FACE_getIFCo(f, lvl, S, x, cornerIdx),
977                      ss);
978       }
979     }
980   }
981 
982   if (freeF) {
983     MEM_freeN(effectedF);
984   }
985 
986   return eCCGError_None;
987 }
988 
989 /* copy other places to face grid coordinates */
ccgSubSurf_updateToFaces(CCGSubSurf * ss,int lvl,CCGFace ** effectedF,int numEffectedF)990 CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
991 {
992   int i, S, x, gridSize, cornerIdx, subdivLevels;
993   int vertDataSize = ss->meshIFC.vertDataSize, freeF;
994 
995   subdivLevels = ss->subdivLevels;
996   lvl = (lvl) ? lvl : subdivLevels;
997   gridSize = ccg_gridsize(lvl);
998   cornerIdx = gridSize - 1;
999 
1000   ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
1001 
1002   for (i = 0; i < numEffectedF; i++) {
1003     CCGFace *f = effectedF[i];
1004 
1005     for (S = 0; S < f->numVerts; S++) {
1006       int prevS = (S + f->numVerts - 1) % f->numVerts;
1007       CCGEdge *e = FACE_getEdges(f)[S];
1008       CCGEdge *prevE = FACE_getEdges(f)[prevS];
1009 
1010       for (x = 0; x < gridSize; x++) {
1011         int eI = gridSize - 1 - x;
1012         VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, x),
1013                      _edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
1014                      ss);
1015         VertDataCopy(FACE_getIFCo(f, lvl, S, x, cornerIdx),
1016                      _edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
1017                      ss);
1018       }
1019 
1020       for (x = 1; x < gridSize - 1; x++) {
1021         VertDataCopy(FACE_getIFCo(f, lvl, S, 0, x), FACE_getIECo(f, lvl, prevS, x), ss);
1022         VertDataCopy(FACE_getIFCo(f, lvl, S, x, 0), FACE_getIECo(f, lvl, S, x), ss);
1023       }
1024 
1025       VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
1026       VertDataCopy(
1027           FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl), ss);
1028     }
1029   }
1030 
1031   if (freeF) {
1032     MEM_freeN(effectedF);
1033   }
1034 
1035   return eCCGError_None;
1036 }
1037 
1038 /* stitch together face grids, averaging coordinates at edges
1039  * and vertices, for multires displacements */
ccgSubSurf_stitchFaces(CCGSubSurf * ss,int lvl,CCGFace ** effectedF,int numEffectedF)1040 CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
1041 {
1042   CCGVert **effectedV;
1043   CCGEdge **effectedE;
1044   int numEffectedV, numEffectedE, freeF;
1045   int i, S, x, gridSize, cornerIdx, subdivLevels, edgeSize;
1046   int vertDataSize = ss->meshIFC.vertDataSize;
1047 
1048   subdivLevels = ss->subdivLevels;
1049   lvl = (lvl) ? lvl : subdivLevels;
1050   gridSize = ccg_gridsize(lvl);
1051   edgeSize = ccg_edgesize(lvl);
1052   cornerIdx = gridSize - 1;
1053 
1054   ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
1055   ccgSubSurf__effectedFaceNeighbors(
1056       ss, effectedF, numEffectedF, &effectedV, &numEffectedV, &effectedE, &numEffectedE);
1057 
1058   /* zero */
1059   for (i = 0; i < numEffectedV; i++) {
1060     CCGVert *v = effectedV[i];
1061     if (v->numFaces) {
1062       VertDataZero(VERT_getCo(v, lvl), ss);
1063     }
1064   }
1065 
1066   for (i = 0; i < numEffectedE; i++) {
1067     CCGEdge *e = effectedE[i];
1068 
1069     if (e->numFaces) {
1070       for (x = 0; x < edgeSize; x++) {
1071         VertDataZero(EDGE_getCo(e, lvl, x), ss);
1072       }
1073     }
1074   }
1075 
1076   /* add */
1077   for (i = 0; i < numEffectedF; i++) {
1078     CCGFace *f = effectedF[i];
1079 
1080     VertDataZero((float *)FACE_getCenterData(f), ss);
1081 
1082     for (S = 0; S < f->numVerts; S++) {
1083       for (x = 0; x < gridSize; x++) {
1084         VertDataZero(FACE_getIECo(f, lvl, S, x), ss);
1085       }
1086     }
1087 
1088     for (S = 0; S < f->numVerts; S++) {
1089       int prevS = (S + f->numVerts - 1) % f->numVerts;
1090       CCGEdge *e = FACE_getEdges(f)[S];
1091       CCGEdge *prevE = FACE_getEdges(f)[prevS];
1092 
1093       VertDataAdd((float *)FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0), ss);
1094       if (FACE_getVerts(f)[S]->flags & Vert_eEffected) {
1095         VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl),
1096                     FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx),
1097                     ss);
1098       }
1099 
1100       for (x = 1; x < gridSize - 1; x++) {
1101         VertDataAdd(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0), ss);
1102         VertDataAdd(FACE_getIECo(f, lvl, prevS, x), FACE_getIFCo(f, lvl, S, 0, x), ss);
1103       }
1104 
1105       for (x = 0; x < gridSize - 1; x++) {
1106         int eI = gridSize - 1 - x;
1107         if (FACE_getEdges(f)[S]->flags & Edge_eEffected) {
1108           VertDataAdd(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
1109                       FACE_getIFCo(f, lvl, S, cornerIdx, x),
1110                       ss);
1111         }
1112         if (FACE_getEdges(f)[prevS]->flags & Edge_eEffected) {
1113           if (x != 0) {
1114             VertDataAdd(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
1115                         FACE_getIFCo(f, lvl, S, x, cornerIdx),
1116                         ss);
1117           }
1118         }
1119       }
1120     }
1121   }
1122 
1123   /* average */
1124   for (i = 0; i < numEffectedV; i++) {
1125     CCGVert *v = effectedV[i];
1126     if (v->numFaces) {
1127       VertDataMulN(VERT_getCo(v, lvl), 1.0f / v->numFaces, ss);
1128     }
1129   }
1130 
1131   for (i = 0; i < numEffectedE; i++) {
1132     CCGEdge *e = effectedE[i];
1133 
1134     VertDataCopy(EDGE_getCo(e, lvl, 0), VERT_getCo(e->v0, lvl), ss);
1135     VertDataCopy(EDGE_getCo(e, lvl, edgeSize - 1), VERT_getCo(e->v1, lvl), ss);
1136 
1137     if (e->numFaces) {
1138       for (x = 1; x < edgeSize - 1; x++) {
1139         VertDataMulN(EDGE_getCo(e, lvl, x), 1.0f / e->numFaces, ss);
1140       }
1141     }
1142   }
1143 
1144   /* copy */
1145   for (i = 0; i < numEffectedF; i++) {
1146     CCGFace *f = effectedF[i];
1147 
1148     VertDataMulN((float *)FACE_getCenterData(f), 1.0f / f->numVerts, ss);
1149 
1150     for (S = 0; S < f->numVerts; S++) {
1151       for (x = 1; x < gridSize - 1; x++) {
1152         VertDataMulN(FACE_getIECo(f, lvl, S, x), 0.5f, ss);
1153       }
1154     }
1155 
1156     for (S = 0; S < f->numVerts; S++) {
1157       int prevS = (S + f->numVerts - 1) % f->numVerts;
1158       CCGEdge *e = FACE_getEdges(f)[S];
1159       CCGEdge *prevE = FACE_getEdges(f)[prevS];
1160 
1161       VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
1162       VertDataCopy(
1163           FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl), ss);
1164 
1165       for (x = 1; x < gridSize - 1; x++) {
1166         VertDataCopy(FACE_getIFCo(f, lvl, S, x, 0), FACE_getIECo(f, lvl, S, x), ss);
1167         VertDataCopy(FACE_getIFCo(f, lvl, S, 0, x), FACE_getIECo(f, lvl, prevS, x), ss);
1168       }
1169 
1170       for (x = 0; x < gridSize - 1; x++) {
1171         int eI = gridSize - 1 - x;
1172 
1173         VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, x),
1174                      _edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
1175                      ss);
1176         VertDataCopy(FACE_getIFCo(f, lvl, S, x, cornerIdx),
1177                      _edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI, vertDataSize),
1178                      ss);
1179       }
1180 
1181       VertDataCopy(FACE_getIECo(f, lvl, S, 0), (float *)FACE_getCenterData(f), ss);
1182       VertDataCopy(
1183           FACE_getIECo(f, lvl, S, gridSize - 1), FACE_getIFCo(f, lvl, S, gridSize - 1, 0), ss);
1184     }
1185   }
1186 
1187   for (i = 0; i < numEffectedV; i++) {
1188     effectedV[i]->flags = 0;
1189   }
1190   for (i = 0; i < numEffectedE; i++) {
1191     effectedE[i]->flags = 0;
1192   }
1193   for (i = 0; i < numEffectedF; i++) {
1194     effectedF[i]->flags = 0;
1195   }
1196 
1197   MEM_freeN(effectedE);
1198   MEM_freeN(effectedV);
1199   if (freeF) {
1200     MEM_freeN(effectedF);
1201   }
1202 
1203   return eCCGError_None;
1204 }
1205 
1206 /*** External API accessor functions ***/
1207 
ccgSubSurf_getNumVerts(const CCGSubSurf * ss)1208 int ccgSubSurf_getNumVerts(const CCGSubSurf *ss)
1209 {
1210   return ss->vMap->numEntries;
1211 }
ccgSubSurf_getNumEdges(const CCGSubSurf * ss)1212 int ccgSubSurf_getNumEdges(const CCGSubSurf *ss)
1213 {
1214   return ss->eMap->numEntries;
1215 }
ccgSubSurf_getNumFaces(const CCGSubSurf * ss)1216 int ccgSubSurf_getNumFaces(const CCGSubSurf *ss)
1217 {
1218   return ss->fMap->numEntries;
1219 }
1220 
ccgSubSurf_getVert(CCGSubSurf * ss,CCGVertHDL v)1221 CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v)
1222 {
1223   return (CCGVert *)ccg_ehash_lookup(ss->vMap, v);
1224 }
ccgSubSurf_getEdge(CCGSubSurf * ss,CCGEdgeHDL e)1225 CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e)
1226 {
1227   return (CCGEdge *)ccg_ehash_lookup(ss->eMap, e);
1228 }
ccgSubSurf_getFace(CCGSubSurf * ss,CCGFaceHDL f)1229 CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f)
1230 {
1231   return (CCGFace *)ccg_ehash_lookup(ss->fMap, f);
1232 }
1233 
ccgSubSurf_getSubdivisionLevels(const CCGSubSurf * ss)1234 int ccgSubSurf_getSubdivisionLevels(const CCGSubSurf *ss)
1235 {
1236   return ss->subdivLevels;
1237 }
ccgSubSurf_getEdgeSize(const CCGSubSurf * ss)1238 int ccgSubSurf_getEdgeSize(const CCGSubSurf *ss)
1239 {
1240   return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels);
1241 }
ccgSubSurf_getEdgeLevelSize(const CCGSubSurf * ss,int level)1242 int ccgSubSurf_getEdgeLevelSize(const CCGSubSurf *ss, int level)
1243 {
1244   if (level < 1 || level > ss->subdivLevels) {
1245     return -1;
1246   }
1247   return ccg_edgesize(level);
1248 }
ccgSubSurf_getGridSize(const CCGSubSurf * ss)1249 int ccgSubSurf_getGridSize(const CCGSubSurf *ss)
1250 {
1251   return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels);
1252 }
ccgSubSurf_getGridLevelSize(const CCGSubSurf * ss,int level)1253 int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level)
1254 {
1255   if (level < 1 || level > ss->subdivLevels) {
1256     return -1;
1257   }
1258   return ccg_gridsize(level);
1259 }
1260 
ccgSubSurf_getSimpleSubdiv(const CCGSubSurf * ss)1261 int ccgSubSurf_getSimpleSubdiv(const CCGSubSurf *ss)
1262 {
1263   return ss->meshIFC.simpleSubdiv;
1264 }
1265 
1266 /* Vert accessors */
1267 
ccgSubSurf_getVertVertHandle(CCGVert * v)1268 CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v)
1269 {
1270   return v->vHDL;
1271 }
ccgSubSurf_getVertAge(CCGSubSurf * ss,CCGVert * v)1272 int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v)
1273 {
1274   if (ss->useAgeCounts) {
1275     byte *userData = ccgSubSurf_getVertUserData(ss, v);
1276     return ss->currentAge - *((int *)&userData[ss->vertUserAgeOffset]);
1277   }
1278   return 0;
1279 }
ccgSubSurf_getVertUserData(CCGSubSurf * ss,CCGVert * v)1280 void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v)
1281 {
1282   return VERT_getLevelData(v) + ss->meshIFC.vertDataSize * (ss->subdivLevels + 1);
1283 }
ccgSubSurf_getVertNumFaces(CCGVert * v)1284 int ccgSubSurf_getVertNumFaces(CCGVert *v)
1285 {
1286   return v->numFaces;
1287 }
ccgSubSurf_getVertFace(CCGVert * v,int index)1288 CCGFace *ccgSubSurf_getVertFace(CCGVert *v, int index)
1289 {
1290   if (index < 0 || index >= v->numFaces) {
1291     return NULL;
1292   }
1293   return v->faces[index];
1294 }
ccgSubSurf_getVertNumEdges(CCGVert * v)1295 int ccgSubSurf_getVertNumEdges(CCGVert *v)
1296 {
1297   return v->numEdges;
1298 }
ccgSubSurf_getVertEdge(CCGVert * v,int index)1299 CCGEdge *ccgSubSurf_getVertEdge(CCGVert *v, int index)
1300 {
1301   if (index < 0 || index >= v->numEdges) {
1302     return NULL;
1303   }
1304   return v->edges[index];
1305 }
ccgSubSurf_getVertData(CCGSubSurf * ss,CCGVert * v)1306 void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v)
1307 {
1308   return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels);
1309 }
ccgSubSurf_getVertLevelData(CCGSubSurf * ss,CCGVert * v,int level)1310 void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level)
1311 {
1312   if (level < 0 || level > ss->subdivLevels) {
1313     return NULL;
1314   }
1315   return ccg_vert_getCo(v, level, ss->meshIFC.vertDataSize);
1316 }
1317 
1318 /* Edge accessors */
1319 
ccgSubSurf_getEdgeEdgeHandle(CCGEdge * e)1320 CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGEdge *e)
1321 {
1322   return e->eHDL;
1323 }
ccgSubSurf_getEdgeAge(CCGSubSurf * ss,CCGEdge * e)1324 int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e)
1325 {
1326   if (ss->useAgeCounts) {
1327     byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
1328     return ss->currentAge - *((int *)&userData[ss->edgeUserAgeOffset]);
1329   }
1330   return 0;
1331 }
ccgSubSurf_getEdgeUserData(CCGSubSurf * ss,CCGEdge * e)1332 void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e)
1333 {
1334   return (EDGE_getLevelData(e) + ss->meshIFC.vertDataSize * ccg_edgebase(ss->subdivLevels + 1));
1335 }
ccgSubSurf_getEdgeNumFaces(CCGEdge * e)1336 int ccgSubSurf_getEdgeNumFaces(CCGEdge *e)
1337 {
1338   return e->numFaces;
1339 }
ccgSubSurf_getEdgeFace(CCGEdge * e,int index)1340 CCGFace *ccgSubSurf_getEdgeFace(CCGEdge *e, int index)
1341 {
1342   if (index < 0 || index >= e->numFaces) {
1343     return NULL;
1344   }
1345   return e->faces[index];
1346 }
ccgSubSurf_getEdgeVert0(CCGEdge * e)1347 CCGVert *ccgSubSurf_getEdgeVert0(CCGEdge *e)
1348 {
1349   return e->v0;
1350 }
ccgSubSurf_getEdgeVert1(CCGEdge * e)1351 CCGVert *ccgSubSurf_getEdgeVert1(CCGEdge *e)
1352 {
1353   return e->v1;
1354 }
ccgSubSurf_getEdgeDataArray(CCGSubSurf * ss,CCGEdge * e)1355 void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e)
1356 {
1357   return ccgSubSurf_getEdgeData(ss, e, 0);
1358 }
ccgSubSurf_getEdgeData(CCGSubSurf * ss,CCGEdge * e,int x)1359 void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x)
1360 {
1361   return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels);
1362 }
ccgSubSurf_getEdgeLevelData(CCGSubSurf * ss,CCGEdge * e,int x,int level)1363 void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level)
1364 {
1365   if (level < 0 || level > ss->subdivLevels) {
1366     return NULL;
1367   }
1368   return ccg_edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
1369 }
ccgSubSurf_getEdgeCrease(CCGEdge * e)1370 float ccgSubSurf_getEdgeCrease(CCGEdge *e)
1371 {
1372   return e->crease;
1373 }
1374 
1375 /* Face accessors */
1376 
ccgSubSurf_getFaceFaceHandle(CCGFace * f)1377 CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGFace *f)
1378 {
1379   return f->fHDL;
1380 }
ccgSubSurf_getFaceAge(CCGSubSurf * ss,CCGFace * f)1381 int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f)
1382 {
1383   if (ss->useAgeCounts) {
1384     byte *userData = ccgSubSurf_getFaceUserData(ss, f);
1385     return ss->currentAge - *((int *)&userData[ss->faceUserAgeOffset]);
1386   }
1387   return 0;
1388 }
ccgSubSurf_getFaceUserData(CCGSubSurf * ss,CCGFace * f)1389 void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f)
1390 {
1391   int maxGridSize = ccg_gridsize(ss->subdivLevels);
1392   return FACE_getCenterData(f) +
1393          ss->meshIFC.vertDataSize *
1394              (1 + f->numVerts * maxGridSize + f->numVerts * maxGridSize * maxGridSize);
1395 }
ccgSubSurf_getFaceNumVerts(CCGFace * f)1396 int ccgSubSurf_getFaceNumVerts(CCGFace *f)
1397 {
1398   return f->numVerts;
1399 }
ccgSubSurf_getFaceVert(CCGFace * f,int index)1400 CCGVert *ccgSubSurf_getFaceVert(CCGFace *f, int index)
1401 {
1402   if (index < 0 || index >= f->numVerts) {
1403     return NULL;
1404   }
1405   return FACE_getVerts(f)[index];
1406 }
ccgSubSurf_getFaceEdge(CCGFace * f,int index)1407 CCGEdge *ccgSubSurf_getFaceEdge(CCGFace *f, int index)
1408 {
1409   if (index < 0 || index >= f->numVerts) {
1410     return NULL;
1411   }
1412   return FACE_getEdges(f)[index];
1413 }
ccgSubSurf_getFaceEdgeIndex(CCGFace * f,CCGEdge * e)1414 int ccgSubSurf_getFaceEdgeIndex(CCGFace *f, CCGEdge *e)
1415 {
1416   for (int i = 0; i < f->numVerts; i++) {
1417     if (FACE_getEdges(f)[i] == e) {
1418       return i;
1419     }
1420   }
1421   return -1;
1422 }
ccgSubSurf_getFaceCenterData(CCGFace * f)1423 void *ccgSubSurf_getFaceCenterData(CCGFace *f)
1424 {
1425   return FACE_getCenterData(f);
1426 }
ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf * ss,CCGFace * f,int gridIndex)1427 void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex)
1428 {
1429   return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0);
1430 }
ccgSubSurf_getFaceGridEdgeData(CCGSubSurf * ss,CCGFace * f,int gridIndex,int x)1431 void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x)
1432 {
1433   return ccg_face_getIECo(
1434       f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
1435 }
ccgSubSurf_getFaceGridDataArray(CCGSubSurf * ss,CCGFace * f,int gridIndex)1436 void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex)
1437 {
1438   return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0);
1439 }
ccgSubSurf_getFaceGridData(CCGSubSurf * ss,CCGFace * f,int gridIndex,int x,int y)1440 void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y)
1441 {
1442   return ccg_face_getIFCo(
1443       f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
1444 }
1445 
1446 /*** External API iterator functions ***/
1447 
ccgSubSurf_initVertIterator(CCGSubSurf * ss,CCGVertIterator * viter)1448 void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter)
1449 {
1450   ccg_ehashIterator_init(ss->vMap, viter);
1451 }
ccgSubSurf_initEdgeIterator(CCGSubSurf * ss,CCGEdgeIterator * eiter)1452 void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter)
1453 {
1454   ccg_ehashIterator_init(ss->eMap, eiter);
1455 }
ccgSubSurf_initFaceIterator(CCGSubSurf * ss,CCGFaceIterator * fiter)1456 void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter)
1457 {
1458   ccg_ehashIterator_init(ss->fMap, fiter);
1459 }
1460 
ccgVertIterator_getCurrent(CCGVertIterator * vi)1461 CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi)
1462 {
1463   return (CCGVert *)ccg_ehashIterator_getCurrent((EHashIterator *)vi);
1464 }
ccgVertIterator_isStopped(CCGVertIterator * vi)1465 int ccgVertIterator_isStopped(CCGVertIterator *vi)
1466 {
1467   return ccg_ehashIterator_isStopped((EHashIterator *)vi);
1468 }
ccgVertIterator_next(CCGVertIterator * vi)1469 void ccgVertIterator_next(CCGVertIterator *vi)
1470 {
1471   ccg_ehashIterator_next((EHashIterator *)vi);
1472 }
1473 
ccgEdgeIterator_getCurrent(CCGEdgeIterator * ei)1474 CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *ei)
1475 {
1476   return (CCGEdge *)ccg_ehashIterator_getCurrent((EHashIterator *)ei);
1477 }
ccgEdgeIterator_isStopped(CCGEdgeIterator * ei)1478 int ccgEdgeIterator_isStopped(CCGEdgeIterator *ei)
1479 {
1480   return ccg_ehashIterator_isStopped((EHashIterator *)ei);
1481 }
ccgEdgeIterator_next(CCGEdgeIterator * ei)1482 void ccgEdgeIterator_next(CCGEdgeIterator *ei)
1483 {
1484   ccg_ehashIterator_next((EHashIterator *)ei);
1485 }
1486 
ccgFaceIterator_getCurrent(CCGFaceIterator * fi)1487 CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *fi)
1488 {
1489   return (CCGFace *)ccg_ehashIterator_getCurrent((EHashIterator *)fi);
1490 }
ccgFaceIterator_isStopped(CCGFaceIterator * fi)1491 int ccgFaceIterator_isStopped(CCGFaceIterator *fi)
1492 {
1493   return ccg_ehashIterator_isStopped((EHashIterator *)fi);
1494 }
ccgFaceIterator_next(CCGFaceIterator * fi)1495 void ccgFaceIterator_next(CCGFaceIterator *fi)
1496 {
1497   ccg_ehashIterator_next((EHashIterator *)fi);
1498 }
1499 
1500 /*** Extern API final vert/edge/face interface ***/
1501 
ccgSubSurf_getNumFinalVerts(const CCGSubSurf * ss)1502 int ccgSubSurf_getNumFinalVerts(const CCGSubSurf *ss)
1503 {
1504   int edgeSize = ccg_edgesize(ss->subdivLevels);
1505   int gridSize = ccg_gridsize(ss->subdivLevels);
1506   int numFinalVerts = (ss->vMap->numEntries + ss->eMap->numEntries * (edgeSize - 2) +
1507                        ss->fMap->numEntries +
1508                        ss->numGrids * ((gridSize - 2) + ((gridSize - 2) * (gridSize - 2))));
1509 
1510   return numFinalVerts;
1511 }
ccgSubSurf_getNumFinalEdges(const CCGSubSurf * ss)1512 int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss)
1513 {
1514   int edgeSize = ccg_edgesize(ss->subdivLevels);
1515   int gridSize = ccg_gridsize(ss->subdivLevels);
1516   int numFinalEdges = (ss->eMap->numEntries * (edgeSize - 1) +
1517                        ss->numGrids * ((gridSize - 1) + 2 * ((gridSize - 2) * (gridSize - 1))));
1518   return numFinalEdges;
1519 }
ccgSubSurf_getNumFinalFaces(const CCGSubSurf * ss)1520 int ccgSubSurf_getNumFinalFaces(const CCGSubSurf *ss)
1521 {
1522   int gridSize = ccg_gridsize(ss->subdivLevels);
1523   int numFinalFaces = ss->numGrids * ((gridSize - 1) * (gridSize - 1));
1524   return numFinalFaces;
1525 }
1526 
1527 /***/
1528 
CCG_key(CCGKey * key,const CCGSubSurf * ss,int level)1529 void CCG_key(CCGKey *key, const CCGSubSurf *ss, int level)
1530 {
1531   key->level = level;
1532 
1533   key->elem_size = ss->meshIFC.vertDataSize;
1534   key->has_normals = ss->calcVertNormals;
1535 
1536   /* if normals are present, always the last three floats of an
1537    * element */
1538   if (key->has_normals) {
1539     key->normal_offset = key->elem_size - sizeof(float[3]);
1540   }
1541   else {
1542     key->normal_offset = -1;
1543   }
1544 
1545   key->grid_size = ccgSubSurf_getGridLevelSize(ss, level);
1546   key->grid_area = key->grid_size * key->grid_size;
1547   key->grid_bytes = key->elem_size * key->grid_area;
1548 
1549   key->has_mask = ss->allocMask;
1550   if (key->has_mask) {
1551     key->mask_offset = ss->maskDataOffset;
1552   }
1553   else {
1554     key->mask_offset = -1;
1555   }
1556 }
1557 
CCG_key_top_level(CCGKey * key,const CCGSubSurf * ss)1558 void CCG_key_top_level(CCGKey *key, const CCGSubSurf *ss)
1559 {
1560   CCG_key(key, ss, ccgSubSurf_getSubdivisionLevels(ss));
1561 }
1562