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