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