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