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