Blender V4.3
subsurf_ccg.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cfloat>
10#include <cmath>
11#include <cstdio>
12#include <cstdlib>
13#include <cstring>
14
15#include "atomic_ops.h"
16
17#include "MEM_guardedalloc.h"
18
19#include "DNA_mesh_types.h"
20#include "DNA_meshdata_types.h"
21#include "DNA_modifier_types.h"
22#include "DNA_object_types.h"
23#include "DNA_scene_types.h"
24
25#include "BLI_bitmap.h"
26#include "BLI_memarena.h"
27#include "BLI_ordered_edge.hh"
28#include "BLI_set.hh"
29#include "BLI_task.h"
30#include "BLI_threads.h"
31#include "BLI_utildefines.h"
32#include "BLI_vector.hh"
33
34#include "BKE_ccg.hh"
35#include "BKE_customdata.hh"
37#include "BKE_mesh_mapping.hh"
38#include "BKE_multires.hh"
39#include "BKE_scene.hh"
40#include "BKE_subsurf.hh"
41
42#include "CCGSubSurf.h"
43
45 int drawInteriorEdges,
46 int useSubsurfUv,
47 DerivedMesh *dm);
49
50static void *arena_alloc(CCGAllocatorHDL a, int numBytes)
51{
52 return BLI_memarena_alloc(reinterpret_cast<MemArena *>(a), numBytes);
53}
54
55static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize)
56{
57 void *p2 = BLI_memarena_alloc(reinterpret_cast<MemArena *>(a), newSize);
58 if (ptr) {
59 memcpy(p2, ptr, oldSize);
60 }
61 return p2;
62}
63
64static void arena_free(CCGAllocatorHDL /*a*/, void * /*ptr*/)
65{
66 /* do nothing */
67}
68
70{
71 BLI_memarena_free(reinterpret_cast<MemArena *>(a));
72}
73
78 /* add an extra four bytes for a mask layer */
81};
83
84static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int numLayers, CCGFlags flags)
85{
86 CCGMeshIFC ifc;
87 CCGSubSurf *ccgSS;
88 int useAging = !!(flags & CCG_USE_AGING);
89 int useArena = flags & CCG_USE_ARENA;
90 int normalOffset = 0;
91
92 /* (subdivLevels == 0) is not allowed */
93 subdivLevels = std::max(subdivLevels, 1);
94
95 if (prevSS) {
96 int oldUseAging;
97
98 ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, nullptr, nullptr, nullptr);
99
100 if ((oldUseAging != useAging) ||
101 (ccgSubSurf_getSimpleSubdiv(prevSS) != !!(flags & CCG_SIMPLE_SUBDIV)))
102 {
103 ccgSubSurf_free(prevSS);
104 }
105 else {
106 ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
107
108 return prevSS;
109 }
110 }
111
112 if (useAging) {
113 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 12;
114 }
115 else {
116 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
117 }
118 ifc.numLayers = numLayers;
119 ifc.vertDataSize = sizeof(float) * numLayers;
120 normalOffset += sizeof(float) * numLayers;
121 if (flags & CCG_CALC_NORMALS) {
122 ifc.vertDataSize += sizeof(float[3]);
123 }
124 if (flags & CCG_ALLOC_MASK) {
125 ifc.vertDataSize += sizeof(float);
126 }
127 ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV);
128
129 if (useArena) {
130 CCGAllocatorIFC allocatorIFC;
131 CCGAllocatorHDL allocator = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "subsurf arena");
132
133 allocatorIFC.alloc = arena_alloc;
134 allocatorIFC.realloc = arena_realloc;
135 allocatorIFC.free = arena_free;
136 allocatorIFC.release = arena_release;
137
138 ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
139 }
140 else {
141 ccgSS = ccgSubSurf_new(&ifc, subdivLevels, nullptr, nullptr);
142 }
143
144 if (useAging) {
145 ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
146 }
147
148 if (flags & CCG_ALLOC_MASK) {
149 normalOffset += sizeof(float);
150 /* mask is allocated after regular layers */
151 ccgSubSurf_setAllocMask(ccgSS, 1, sizeof(float) * numLayers);
152 }
153
154 if (flags & CCG_CALC_NORMALS) {
155 ccgSubSurf_setCalcVertexNormals(ccgSS, 1, normalOffset);
156 }
157 else {
159 }
160
161 return ccgSS;
162}
163
164static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize)
165{
168 int v0idx = *((int *)ccgSubSurf_getVertUserData(ss, v0));
169 int v1idx = *((int *)ccgSubSurf_getVertUserData(ss, v1));
170 int edgeBase = *((int *)ccgSubSurf_getEdgeUserData(ss, e));
171
172 if (x == 0) {
173 return v0idx;
174 }
175 if (x == edgeSize - 1) {
176 return v1idx;
177 }
178
179 return edgeBase + x - 1;
180}
181
182static int getFaceIndex(
183 CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize)
184{
185 int faceBase = *((int *)ccgSubSurf_getFaceUserData(ss, f));
186 int numVerts = ccgSubSurf_getFaceNumVerts(f);
187
188 if (x == gridSize - 1 && y == gridSize - 1) {
190 return *((int *)ccgSubSurf_getVertUserData(ss, v));
191 }
192 if (x == gridSize - 1) {
195 int edgeBase = *((int *)ccgSubSurf_getEdgeUserData(ss, e));
196 if (v == ccgSubSurf_getEdgeVert0(e)) {
197 return edgeBase + (gridSize - 1 - y) - 1;
198 }
199
200 return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - y) - 1);
201 }
202 if (y == gridSize - 1) {
204 CCGEdge *e = ccgSubSurf_getFaceEdge(f, (S + numVerts - 1) % numVerts);
205 int edgeBase = *((int *)ccgSubSurf_getEdgeUserData(ss, e));
206 if (v == ccgSubSurf_getEdgeVert0(e)) {
207 return edgeBase + (gridSize - 1 - x) - 1;
208 }
209
210 return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - x) - 1);
211 }
212 if (x == 0 && y == 0) {
213 return faceBase;
214 }
215 if (x == 0) {
216 S = (S + numVerts - 1) % numVerts;
217 return faceBase + 1 + (gridSize - 2) * S + (y - 1);
218 }
219 if (y == 0) {
220 return faceBase + 1 + (gridSize - 2) * S + (x - 1);
221 }
222
223 return faceBase + 1 + (gridSize - 2) * numVerts + S * (gridSize - 2) * (gridSize - 2) +
224 (y - 1) * (gridSize - 2) + (x - 1);
225}
226
228 const blender::OffsetIndices<int> faces,
229 const int *face_verts,
230 int fi,
231 CCGVertHDL *fverts)
232{
233 UvMapVert *v, *nv;
234 int j, nverts = faces[fi].size();
235
236 for (j = 0; j < nverts; j++) {
237 for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, face_verts[j]); v; v = v->next) {
238 if (v->separate) {
239 nv = v;
240 }
241 if (v->face_index == fi) {
242 break;
243 }
244 }
245
246 fverts[j] = POINTER_FROM_UINT(faces[nv->face_index].start() + nv->loop_of_face_index);
247 }
248}
249
251 CCGSubSurf *origss,
252 DerivedMesh *dm,
253 const float (*mloopuv)[2])
254{
256 int *corner_verts = dm->getCornerVertArray(dm);
257 int totvert = dm->getNumVerts(dm);
258 int totface = dm->getNumPolys(dm);
259 int i, seam;
260 UvMapVert *v;
261 UvVertMap *vmap;
263 float limit[2];
264 float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
265
266 limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
267 /* previous behavior here is without accounting for winding, however this causes stretching in
268 * UV map in really simple cases with mirror + subsurf, see second part of #44530.
269 * Also, initially intention is to treat merged vertices from mirror modifier as seams.
270 * This fixes a very old regression (2.49 was correct here) */
272 faces, nullptr, nullptr, corner_verts, mloopuv, totvert, limit, false, true);
273 if (!vmap) {
274 return 0;
275 }
276
278
279 /* create vertices */
280 for (i = 0; i < totvert; i++) {
281 if (!BKE_mesh_uv_vert_map_get_vert(vmap, i)) {
282 continue;
283 }
284
285 for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i)->next; v; v = v->next) {
286 if (v->separate) {
287 break;
288 }
289 }
290
291 seam = (v != nullptr);
292
293 for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i); v; v = v->next) {
294 if (v->separate) {
295 CCGVert *ssv;
296 int loopid = faces[v->face_index].start() + v->loop_of_face_index;
297 CCGVertHDL vhdl = POINTER_FROM_INT(loopid);
298
299 copy_v2_v2(uv, mloopuv[loopid]);
300
301 ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
302 }
303 }
304 }
305
306 /* create edges */
308 eset.reserve(totface);
309
310 for (i = 0; i < totface; i++) {
311 const blender::IndexRange face = faces[i];
312 int nverts = face.size();
313 int j, j_next;
314 CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i));
315 // uint *fv = &face.v1;
316
317 fverts.reinitialize(nverts);
318
319 get_face_uv_map_vert(vmap, faces, &corner_verts[face.start()], i, fverts.data());
320
321 for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) {
322 uint v0 = POINTER_AS_UINT(fverts[j_next]);
323 uint v1 = POINTER_AS_UINT(fverts[j]);
324
325 if (eset.add({v0, v1})) {
326 CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next);
327 CCGEdgeHDL ehdl = POINTER_FROM_INT(face[j_next]);
328 float crease = ccgSubSurf_getEdgeCrease(orige);
329
330 ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e);
331 }
332 }
333 }
334
335 /* create faces */
336 for (i = 0; i < totface; i++) {
337 const blender::IndexRange face = faces[i];
338 int nverts = face.size();
339 CCGFace *f;
340
341 fverts.reinitialize(nverts);
342
343 get_face_uv_map_vert(vmap, faces, &corner_verts[face.start()], i, fverts.data());
344 ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts.data(), &f);
345 }
346
349
350 return 1;
351}
352
353static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
354{
356 int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
357 const float(*dmloopuv)[2] = static_cast<const float(*)[2]>(
359 /* need to update both CD_MTFACE & CD_PROP_FLOAT2, hrmf, we could get away with
360 * just tface except applying the modifier then looses subsurf UV */
361 MTFace *tface = static_cast<MTFace *>(
362 CustomData_get_layer_n_for_write(&result->faceData, CD_MTFACE, n, result->numTessFaceData));
363 float(*mloopuv)[2] = static_cast<float(*)[2]>(CustomData_get_layer_n_for_write(
364 &result->loopData, CD_PROP_FLOAT2, n, result->getNumLoops(result)));
365
366 if (!dmloopuv || (!tface && !mloopuv)) {
367 return;
368 }
369
370 /* create a CCGSubSurf from uv's */
372
373 if (!ss_sync_from_uv(uvss, ss, dm, dmloopuv)) {
374 ccgSubSurf_free(uvss);
375 return;
376 }
377
378 /* get some info from CCGSubSurf */
379 totface = ccgSubSurf_getNumFaces(uvss);
380 // edgeSize = ccgSubSurf_getEdgeSize(uvss); /* UNUSED */
381 gridSize = ccgSubSurf_getGridSize(uvss);
382 gridFaces = gridSize - 1;
383
384 /* make a map from original faces to CCGFaces */
385 CCGFace **faceMap = static_cast<CCGFace **>(
386 MEM_mallocN(totface * sizeof(*faceMap), "facemapuv"));
389 {
392 }
393
394 /* load coordinates from uvss into tface */
395 MTFace *tf = tface;
396 float(*mluv)[2] = mloopuv;
397
398 for (index = 0; index < totface; index++) {
399 CCGFace *f = faceMap[index];
400 int numVerts = ccgSubSurf_getFaceNumVerts(f);
401
402 for (S = 0; S < numVerts; S++) {
403 float(*faceGridData)[2] = static_cast<float(*)[2]>(
405
406 for (y = 0; y < gridFaces; y++) {
407 for (x = 0; x < gridFaces; x++) {
408 float *a = faceGridData[(y + 0) * gridSize + x + 0];
409 float *b = faceGridData[(y + 0) * gridSize + x + 1];
410 float *c = faceGridData[(y + 1) * gridSize + x + 1];
411 float *d = faceGridData[(y + 1) * gridSize + x + 0];
412
413 if (tf) {
414 copy_v2_v2(tf->uv[0], a);
415 copy_v2_v2(tf->uv[1], d);
416 copy_v2_v2(tf->uv[2], c);
417 copy_v2_v2(tf->uv[3], b);
418 tf++;
419 }
420
421 if (mluv) {
422 copy_v2_v2(mluv[0], a);
423 copy_v2_v2(mluv[1], d);
424 copy_v2_v2(mluv[2], c);
425 copy_v2_v2(mluv[3], b);
426 mluv += 4;
427 }
428 }
429 }
430 }
431 }
432
433 ccgSubSurf_free(uvss);
435}
436
437static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int layer_index)
438{
439 set_subsurf_legacy_uv(ss, dm, result, layer_index);
440}
441
442/* face weighting */
443#define SUB_ELEMS_FACE 50
445
451
456
457static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
458{
459 int x, y, i, j;
460 float *w, w1, w2, w4, fac, fac2, fx, fy;
461
462 if (wtable->len <= faceLen) {
463 void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry) * (faceLen + 1), "weight table alloc 2");
464
465 if (wtable->len) {
466 memcpy(tmp, wtable->weight_table, sizeof(FaceVertWeightEntry) * wtable->len);
467 MEM_freeN(wtable->weight_table);
468 }
469
470 wtable->weight_table = static_cast<FaceVertWeightEntry *>(tmp);
471 wtable->len = faceLen + 1;
472 }
473
474 if (!wtable->weight_table[faceLen].valid) {
475 wtable->weight_table[faceLen].valid = 1;
476 wtable->weight_table[faceLen].w = w = static_cast<float *>(
477 MEM_callocN(sizeof(float) * faceLen * faceLen * (gridCuts + 2) * (gridCuts + 2),
478 "weight table alloc"));
479 fac = 1.0f / float(faceLen);
480
481 for (i = 0; i < faceLen; i++) {
482 for (x = 0; x < gridCuts + 2; x++) {
483 for (y = 0; y < gridCuts + 2; y++) {
484 fx = 0.5f - float(x) / float(gridCuts + 1) / 2.0f;
485 fy = 0.5f - float(y) / float(gridCuts + 1) / 2.0f;
486
487 fac2 = faceLen - 4;
488 w1 = (1.0f - fx) * (1.0f - fy) + (-fac2 * fx * fy * fac);
489 w2 = (1.0f - fx + fac2 * fx * -fac) * (fy);
490 w4 = (fx) * (1.0f - fy + -fac2 * fy * fac);
491
492 /* These values aren't used for triangles and cause divide by zero. */
493 if (faceLen > 3) {
494 fac2 = 1.0f - (w1 + w2 + w4);
495 fac2 = fac2 / float(faceLen - 3);
496 for (j = 0; j < faceLen; j++) {
497 w[j] = fac2;
498 }
499 }
500
501 w[i] = w1;
502 w[(i - 1 + faceLen) % faceLen] = w2;
503 w[(i + 1) % faceLen] = w4;
504
505 w += faceLen;
506 }
507 }
508 }
509 }
510
511 return wtable->weight_table[faceLen].w;
512}
513
514static void free_ss_weights(WeightTable *wtable)
515{
516 int i;
517
518 for (i = 0; i < wtable->len; i++) {
519 if (wtable->weight_table[i].valid) {
520 MEM_freeN(wtable->weight_table[i].w);
521 }
522 }
523
524 if (wtable->weight_table) {
525 MEM_freeN(wtable->weight_table);
526 }
527}
528
530 DerivedMesh *dm,
531 float (*vertexCos)[3],
532 int useFlatSubdiv)
533{
534 float creaseFactor = float(ccgSubSurf_getSubdivisionLevels(ss));
536 float(*positions)[3] = (float(*)[3])dm->getVertArray(dm);
537 const blender::int2 *edges = reinterpret_cast<const blender::int2 *>(dm->getEdgeArray(dm));
538 int *corner_verts = dm->getCornerVertArray(dm);
540 int totvert = dm->getNumVerts(dm);
541 int totedge = dm->getNumEdges(dm);
542 int i, j;
543 int *index;
544
546
547 index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
548 for (i = 0; i < totvert; i++) {
549 CCGVert *v;
550
551 if (vertexCos) {
552 ccgSubSurf_syncVert(ss, POINTER_FROM_INT(i), vertexCos[i], 0, &v);
553 }
554 else {
555 ccgSubSurf_syncVert(ss, POINTER_FROM_INT(i), positions[i], 0, &v);
556 }
557
558 ((int *)ccgSubSurf_getVertUserData(ss, v))[1] = (index) ? *index++ : i;
559 }
560
561 index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX);
562 const float *creases = (const float *)CustomData_get_layer_named(
563 &dm->edgeData, CD_PROP_FLOAT, "crease_edge");
564 for (i = 0; i < totedge; i++) {
565 CCGEdge *e;
566 float crease;
567
568 crease = useFlatSubdiv ? creaseFactor : (creases ? creases[i] * creaseFactor : 0.0f);
569
572 POINTER_FROM_UINT(edges[i][0]),
573 POINTER_FROM_UINT(edges[i][1]),
574 crease,
575 &e);
576
577 ((int *)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index) ? *index++ : i;
578 }
579
580 index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
581 for (i = 0; i < dm->numPolyData; i++) {
582 const blender::IndexRange face = faces[i];
583
584 CCGFace *f;
585
586 fverts.reinitialize(face.size());
587
588 for (j = 0; j < face.size(); j++) {
589 fverts[j] = POINTER_FROM_UINT(corner_verts[face[j]]);
590 }
591
592 /* This is very bad, means mesh is internally inconsistent.
593 * it is not really possible to continue without modifying
594 * other parts of code significantly to handle missing faces.
595 * since this really shouldn't even be possible we just bail. */
596 if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), face.size(), fverts.data(), &f) ==
598 {
599 static int hasGivenError = 0;
600
601 if (!hasGivenError) {
602 // XXX error("Unrecoverable error in SubSurf calculation,"
603 // " mesh is inconsistent.");
604
605 hasGivenError = 1;
606 }
607
608 return;
609 }
610
611 ((int *)ccgSubSurf_getFaceUserData(ss, f))[1] = (index) ? *index++ : i;
612 }
613
615}
616
618 DerivedMesh *dm,
619 float (*vertexCos)[3],
620 int use_flat_subdiv,
621 bool /*use_subdiv_uvs*/)
622{
623 ss_sync_ccg_from_derivedmesh(ss, dm, vertexCos, use_flat_subdiv);
624}
625
626/***/
627
629{
630 return ((int *)ccgSubSurf_getVertUserData(ss, v))[1];
631}
632
634{
635 return ((int *)ccgSubSurf_getEdgeUserData(ss, e))[1];
636}
637
639{
640 return ((int *)ccgSubSurf_getFaceUserData(ss, f))[1];
641}
642
644{
645 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
646
647 return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
648}
649
651{
652 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
653
654 return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
655}
656
658{
659 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
660
661 return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
662}
663
665{
666 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
667
668 /* All subsurf faces are quads */
669 return 4 * ccgSubSurf_getNumFinalFaces(ccgdm->ss);
670}
671
672/* utility function */
673BLI_INLINE void ccgDM_to_MVert(float mv[3], const CCGKey *key, CCGElem *elem)
674{
675 copy_v3_v3(mv, CCG_elem_co(*key, elem));
676}
677
678static void ccgDM_copyFinalVertArray(DerivedMesh *dm, float (*r_positions)[3])
679{
680 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
681 CCGSubSurf *ss = ccgdm->ss;
682 CCGElem *vd;
683 CCGKey key;
684 int index;
685 int totvert, totedge, totface;
686 int gridSize = ccgSubSurf_getGridSize(ss);
687 int edgeSize = ccgSubSurf_getEdgeSize(ss);
688 uint i = 0;
689
690 CCG_key_top_level(&key, ss);
691
692 totface = ccgSubSurf_getNumFaces(ss);
693 for (index = 0; index < totface; index++) {
694 CCGFace *f = ccgdm->faceMap[index].face;
695 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
696
697 vd = static_cast<CCGElem *>(ccgSubSurf_getFaceCenterData(f));
698 ccgDM_to_MVert(r_positions[i++], &key, vd);
699
700 for (S = 0; S < numVerts; S++) {
701 for (x = 1; x < gridSize - 1; x++) {
702 vd = static_cast<CCGElem *>(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
703 ccgDM_to_MVert(r_positions[i++], &key, vd);
704 }
705 }
706
707 for (S = 0; S < numVerts; S++) {
708 for (y = 1; y < gridSize - 1; y++) {
709 for (x = 1; x < gridSize - 1; x++) {
710 vd = static_cast<CCGElem *>(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
711 ccgDM_to_MVert(r_positions[i++], &key, vd);
712 }
713 }
714 }
715 }
716
717 totedge = ccgSubSurf_getNumEdges(ss);
718 for (index = 0; index < totedge; index++) {
719 CCGEdge *e = ccgdm->edgeMap[index].edge;
720 int x;
721
722 for (x = 1; x < edgeSize - 1; x++) {
723 /* NOTE(@ideasman42): This gives errors with `--debug-fpe` the normals don't seem to be
724 * unit length. This is most likely caused by edges with no faces which are now zeroed out,
725 * see comment in: `ccgSubSurf__calcVertNormals()`. */
726 vd = static_cast<CCGElem *>(ccgSubSurf_getEdgeData(ss, e, x));
727 ccgDM_to_MVert(r_positions[i++], &key, vd);
728 }
729 }
730
731 totvert = ccgSubSurf_getNumVerts(ss);
732 for (index = 0; index < totvert; index++) {
733 CCGVert *v = ccgdm->vertMap[index].vert;
734
735 vd = static_cast<CCGElem *>(ccgSubSurf_getVertData(ss, v));
736 ccgDM_to_MVert(r_positions[i++], &key, vd);
737 }
738}
739
740/* utility function */
741BLI_INLINE void ccgDM_to_MEdge(blender::int2 *edge, const int v1, const int v2)
742{
743 edge->x = v1;
744 edge->y = v2;
745}
746
748{
749 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
750 CCGSubSurf *ss = ccgdm->ss;
751 int index;
752 int totedge, totface;
753 int gridSize = ccgSubSurf_getGridSize(ss);
754 int edgeSize = ccgSubSurf_getEdgeSize(ss);
755 uint i = 0;
756
757 totface = ccgSubSurf_getNumFaces(ss);
758 for (index = 0; index < totface; index++) {
759 CCGFace *f = ccgdm->faceMap[index].face;
760 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
761
762 for (S = 0; S < numVerts; S++) {
763 for (x = 0; x < gridSize - 1; x++) {
764 ccgDM_to_MEdge(&edges[i++],
765 getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize),
766 getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize));
767 }
768
769 for (x = 1; x < gridSize - 1; x++) {
770 for (y = 0; y < gridSize - 1; y++) {
771 ccgDM_to_MEdge(&edges[i++],
772 getFaceIndex(ss, f, S, x, y, edgeSize, gridSize),
773 getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize));
774 ccgDM_to_MEdge(&edges[i++],
775 getFaceIndex(ss, f, S, y, x, edgeSize, gridSize),
776 getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize));
777 }
778 }
779 }
780 }
781
782 totedge = ccgSubSurf_getNumEdges(ss);
783 for (index = 0; index < totedge; index++) {
784 CCGEdge *e = ccgdm->edgeMap[index].edge;
785 for (int x = 0; x < edgeSize - 1; x++) {
787 &edges[i++], getEdgeIndex(ss, e, x, edgeSize), getEdgeIndex(ss, e, x + 1, edgeSize));
788 }
789 }
790}
791
800
801static void copyFinalLoopArray_task_cb(void *__restrict userdata,
802 const int iter,
803 const TaskParallelTLS *__restrict /*tls*/)
804{
805 CopyFinalLoopArrayData *data = static_cast<CopyFinalLoopArrayData *>(userdata);
806 CCGDerivedMesh *ccgdm = data->ccgdm;
807 CCGSubSurf *ss = ccgdm->ss;
808 const int grid_size = data->grid_size;
809 const int edge_size = data->edge_size;
810 CCGFace *f = ccgdm->faceMap[iter].face;
811 const int num_verts = ccgSubSurf_getFaceNumVerts(f);
812 const int grid_index = data->grid_offset[iter];
813 int *corner_verts = data->corner_verts;
814 int *corner_edges = data->corner_edges;
815
816 size_t loop_i = 4 * size_t(grid_index) * (grid_size - 1) * (grid_size - 1);
817 for (int S = 0; S < num_verts; S++) {
818 for (int y = 0; y < grid_size - 1; y++) {
819 for (int x = 0; x < grid_size - 1; x++) {
820
821 const int v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size);
822 const int v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size);
823 const int v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size);
824 const int v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size);
825
826 if (corner_verts) {
827 corner_verts[loop_i + 0] = v1;
828 corner_verts[loop_i + 1] = v2;
829 corner_verts[loop_i + 2] = v3;
830 corner_verts[loop_i + 3] = v4;
831 }
832 if (corner_edges) {
833 corner_edges[loop_i + 0] = ccgdm->ehash->index_of({v1, v2});
834 corner_edges[loop_i + 1] = ccgdm->ehash->index_of({v2, v3});
835 corner_edges[loop_i + 2] = ccgdm->ehash->index_of({v3, v4});
836 corner_edges[loop_i + 3] = ccgdm->ehash->index_of({v4, v1});
837 }
838
839 loop_i += 4;
840 }
841 }
842 }
843}
844
845static void ccgDM_copyFinalCornerVertArray(DerivedMesh *dm, int *r_corner_verts)
846{
847 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
848 CCGSubSurf *ss = ccgdm->ss;
849
851 data.ccgdm = ccgdm;
852 data.corner_verts = r_corner_verts;
853 data.corner_edges = nullptr;
854 data.grid_size = ccgSubSurf_getGridSize(ss);
855 data.grid_offset = dm->getGridOffset(dm);
856 data.edge_size = ccgSubSurf_getEdgeSize(ss);
857
858 TaskParallelSettings settings;
860 settings.min_iter_per_thread = 1;
861
863 0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings);
864}
865
866static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges)
867{
868 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
869 CCGSubSurf *ss = ccgdm->ss;
870
871 if (!ccgdm->ehash) {
873 if (!ccgdm->ehash) {
875 ehash->reserve(ccgdm->dm.numEdgeData);
876
877 const blender::int2 *medge = reinterpret_cast<const blender::int2 *>(
878 ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm));
879
880 for (int i = 0; i < ccgdm->dm.numEdgeData; i++) {
881 ehash->add({medge[i][0], medge[i][1]});
882 }
883
884 atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash);
885 }
887 }
888
890 data.ccgdm = ccgdm;
891 data.corner_verts = nullptr;
892 data.corner_edges = r_corner_edges;
893 data.grid_size = ccgSubSurf_getGridSize(ss);
894 data.grid_offset = dm->getGridOffset(dm);
895 data.edge_size = ccgSubSurf_getEdgeSize(ss);
896
897 TaskParallelSettings settings;
899 settings.min_iter_per_thread = 1;
900
902 0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings);
903}
904
905static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, int *r_face_offsets)
906{
907 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
908 CCGSubSurf *ss = ccgdm->ss;
909 int index;
910 int totface;
911 int gridSize = ccgSubSurf_getGridSize(ss);
912 // int edgeSize = ccgSubSurf_getEdgeSize(ss); /* UNUSED. */
913 int i = 0, k = 0;
914
915 totface = ccgSubSurf_getNumFaces(ss);
916 for (index = 0; index < totface; index++) {
917 CCGFace *f = ccgdm->faceMap[index].face;
918 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
919
920 for (S = 0; S < numVerts; S++) {
921 for (y = 0; y < gridSize - 1; y++) {
922 for (x = 0; x < gridSize - 1; x++) {
923 r_face_offsets[i] = k;
924 k += 4;
925 i++;
926 }
927 }
928 }
929 }
930 r_face_offsets[i] = k;
931}
932
934{
935 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
936
937 DM_release(dm);
938 /* Before freeing, need to update the displacement map */
939 if (ccgdm->multires.modified_flags) {
940 /* Check that mmd still exists */
941 if (!ccgdm->multires.local_mmd &&
942 BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) == -1)
943 {
944 ccgdm->multires.mmd = nullptr;
945 }
946
947 if (ccgdm->multires.mmd) {
950 }
953 }
954 }
955 }
956
957 delete ccgdm->ehash;
958
959 if (ccgdm->gridFaces) {
960 MEM_freeN(ccgdm->gridFaces);
961 }
962 if (ccgdm->gridData) {
963 MEM_freeN(ccgdm->gridData);
964 }
965 if (ccgdm->gridOffset) {
966 MEM_freeN(ccgdm->gridOffset);
967 }
968 if (ccgdm->gridHidden) {
969 /* Using dm->getNumGrids(dm) accesses freed memory */
970 uint numGrids = ccgdm->numGrid;
971 for (uint i = 0; i < numGrids; i++) {
972 if (ccgdm->gridHidden[i]) {
973 MEM_freeN(ccgdm->gridHidden[i]);
974 }
975 }
976 MEM_freeN(ccgdm->gridHidden);
977 }
978 if (ccgdm->freeSS) {
979 ccgSubSurf_free(ccgdm->ss);
980 }
981 MEM_freeN(ccgdm->vertMap);
982 MEM_freeN(ccgdm->edgeMap);
983 MEM_freeN(ccgdm->faceMap);
984
987
988 MEM_freeN(ccgdm);
989}
990
992{
993 if (type == CD_ORIGINDEX) {
994 /* create origindex on demand to save memory */
995 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
996 CCGSubSurf *ss = ccgdm->ss;
997 int *origindex;
998 int a, index, totnone, totorig;
999
1000 /* Avoid re-creation if the layer exists already */
1002 origindex = static_cast<int *>(DM_get_vert_data_layer(dm, CD_ORIGINDEX));
1004 if (origindex) {
1005 return origindex;
1006 }
1007
1009
1010 origindex = static_cast<int *>(
1012
1013 totorig = ccgSubSurf_getNumVerts(ss);
1014 totnone = dm->numVertData - totorig;
1015
1016 /* original vertices are at the end */
1017 for (a = 0; a < totnone; a++) {
1018 origindex[a] = ORIGINDEX_NONE;
1019 }
1020
1021 for (index = 0; index < totorig; index++, a++) {
1022 CCGVert *v = ccgdm->vertMap[index].vert;
1023 origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
1024 }
1026
1027 return origindex;
1028 }
1029
1030 return DM_get_vert_data_layer(dm, type);
1031}
1032
1034{
1035 if (type == CD_ORIGINDEX) {
1036 /* create origindex on demand to save memory */
1037 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1038 CCGSubSurf *ss = ccgdm->ss;
1039 int *origindex;
1040 int a, i, index, totnone, totorig, totedge;
1041 int edgeSize = ccgSubSurf_getEdgeSize(ss);
1042
1043 /* Avoid re-creation if the layer exists already */
1044 origindex = static_cast<int *>(DM_get_edge_data_layer(dm, CD_ORIGINDEX));
1045 if (origindex) {
1046 return origindex;
1047 }
1048
1049 origindex = static_cast<int *>(
1051
1052 totedge = ccgSubSurf_getNumEdges(ss);
1053 totorig = totedge * (edgeSize - 1);
1054 totnone = dm->numEdgeData - totorig;
1055
1056 /* original edges are at the end */
1057 for (a = 0; a < totnone; a++) {
1058 origindex[a] = ORIGINDEX_NONE;
1059 }
1060
1061 for (index = 0; index < totedge; index++) {
1062 CCGEdge *e = ccgdm->edgeMap[index].edge;
1063 int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
1064
1065 for (i = 0; i < edgeSize - 1; i++, a++) {
1066 origindex[a] = mapIndex;
1067 }
1068 }
1069
1070 return origindex;
1071 }
1072
1073 return DM_get_edge_data_layer(dm, type);
1074}
1075
1077{
1078 if (type == CD_ORIGINDEX) {
1079 /* create origindex on demand to save memory */
1080 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1081 CCGSubSurf *ss = ccgdm->ss;
1082 int *origindex;
1083 int a, i, index, totface;
1084 int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
1085
1086 /* Avoid re-creation if the layer exists already */
1087 origindex = static_cast<int *>(DM_get_poly_data_layer(dm, CD_ORIGINDEX));
1088 if (origindex) {
1089 return origindex;
1090 }
1091
1092 origindex = static_cast<int *>(
1094
1095 totface = ccgSubSurf_getNumFaces(ss);
1096
1097 for (a = 0, index = 0; index < totface; index++) {
1098 CCGFace *f = ccgdm->faceMap[index].face;
1099 int numVerts = ccgSubSurf_getFaceNumVerts(f);
1100 int mapIndex = ccgDM_getFaceMapIndex(ss, f);
1101
1102 for (i = 0; i < gridFaces * gridFaces * numVerts; i++, a++) {
1103 origindex[a] = mapIndex;
1104 }
1105 }
1106
1107 return origindex;
1108 }
1109
1110 return DM_get_poly_data_layer(dm, type);
1111}
1112
1114{
1115 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1116 int index, numFaces, numGrids;
1117
1118 numFaces = ccgSubSurf_getNumFaces(ccgdm->ss);
1119 numGrids = 0;
1120
1121 for (index = 0; index < numFaces; index++) {
1122 CCGFace *f = ccgdm->faceMap[index].face;
1123 numGrids += ccgSubSurf_getFaceNumVerts(f);
1124 }
1125
1126 return numGrids;
1127}
1128
1130{
1131 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1132 return ccgSubSurf_getGridSize(ccgdm->ss);
1133}
1134
1136{
1137 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1138 CCGSubSurf *ss = ccgdm->ss;
1139 CCGElem **gridData;
1140 CCGFace **gridFaces;
1141 int *gridOffset;
1142 int index, numFaces, numGrids, S, gIndex /*, gridSize */;
1143
1144 if (ccgdm->gridData) {
1145 return;
1146 }
1147
1148 numGrids = ccgDM_getNumGrids(dm);
1149 numFaces = ccgSubSurf_getNumFaces(ss);
1150 // gridSize = ccgDM_getGridSize(dm); /* UNUSED */
1151
1152 /* compute offset into grid array for each face */
1153 gridOffset = static_cast<int *>(MEM_mallocN(sizeof(int) * numFaces, "ccgdm.gridOffset"));
1154
1155 for (gIndex = 0, index = 0; index < numFaces; index++) {
1156 CCGFace *f = ccgdm->faceMap[index].face;
1157 int numVerts = ccgSubSurf_getFaceNumVerts(f);
1158
1159 gridOffset[index] = gIndex;
1160 gIndex += numVerts;
1161 }
1162
1163 /* compute grid data */
1164 gridData = static_cast<CCGElem **>(MEM_mallocN(sizeof(CCGElem *) * numGrids, "ccgdm.gridData"));
1165 gridFaces = static_cast<CCGFace **>(
1166 MEM_mallocN(sizeof(CCGFace *) * numGrids, "ccgdm.gridFaces"));
1167
1168 ccgdm->gridHidden = static_cast<uint **>(
1169 MEM_callocN(sizeof(*ccgdm->gridHidden) * numGrids, "ccgdm.gridHidden"));
1170
1171 for (gIndex = 0, index = 0; index < numFaces; index++) {
1172 CCGFace *f = ccgdm->faceMap[index].face;
1173 int numVerts = ccgSubSurf_getFaceNumVerts(f);
1174
1175 for (S = 0; S < numVerts; S++, gIndex++) {
1176 gridData[gIndex] = static_cast<CCGElem *>(ccgSubSurf_getFaceGridDataArray(ss, f, S));
1177 gridFaces[gIndex] = f;
1178 }
1179 }
1180
1181 ccgdm->gridData = gridData;
1182 ccgdm->gridFaces = gridFaces;
1183 ccgdm->gridOffset = gridOffset;
1184 ccgdm->numGrid = numGrids;
1185}
1186
1187static CCGElem **ccgDM_getGridData(DerivedMesh *dm)
1188{
1189 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1190
1192 return ccgdm->gridData;
1193}
1194
1196{
1197 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1198
1200 return ccgdm->gridOffset;
1201}
1202
1204{
1205 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1206 CCG_key_top_level(key, ccgdm->ss);
1207}
1208
1233
1235{
1236 CCGVertIterator vi;
1237 CCGEdgeIterator ei;
1238 CCGFaceIterator fi;
1239 int totvert, totedge, totface;
1240
1241 totvert = ccgSubSurf_getNumVerts(ss);
1242 ccgdm->vertMap = static_cast<decltype(CCGDerivedMesh::vertMap)>(
1243 MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap"));
1246 {
1248
1250 }
1251
1252 totedge = ccgSubSurf_getNumEdges(ss);
1253 ccgdm->edgeMap = static_cast<decltype(CCGDerivedMesh::edgeMap)>(
1254 MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap"));
1257 {
1259
1261 }
1262
1263 totface = ccgSubSurf_getNumFaces(ss);
1264 ccgdm->faceMap = static_cast<decltype(CCGDerivedMesh::faceMap)>(
1265 MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap"));
1268 {
1270
1272 }
1273}
1274
1275/* Fill in all geometry arrays making it possible to access any
1276 * hires data from the CPU.
1277 */
1279 CCGSubSurf *ss,
1280 DerivedMesh *dm,
1281 bool useSubsurfUv)
1282{
1283 const int totvert = ccgSubSurf_getNumVerts(ss);
1284 const int totedge = ccgSubSurf_getNumEdges(ss);
1285 const int totface = ccgSubSurf_getNumFaces(ss);
1286 int index;
1287 int i;
1288 int vertNum = 0, edgeNum = 0, faceNum = 0;
1289 int *polyidx = nullptr;
1292 int loopindex, loopindex2;
1293 int edgeSize;
1294 int gridSize;
1295 int gridFaces, gridCuts;
1296 int gridSideEdges;
1297 int gridInternalEdges;
1298 WeightTable wtable = {nullptr};
1299 bool has_edge_cd;
1300
1301 edgeSize = ccgSubSurf_getEdgeSize(ss);
1302 gridSize = ccgSubSurf_getGridSize(ss);
1303 gridFaces = gridSize - 1;
1304 gridCuts = gridSize - 2;
1305 // gridInternalVerts = gridSideVerts * gridSideVerts; /* As yet, unused. */
1306 gridSideEdges = gridSize - 1;
1307 gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
1308
1309 const int *base_polyOrigIndex = static_cast<const int *>(
1311
1312 int *vertOrigIndex = static_cast<int *>(DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX));
1313 int *edgeOrigIndex = static_cast<int *>(DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX));
1314 int *polyOrigIndex = static_cast<int *>(DM_get_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX));
1315
1316 has_edge_cd = ((ccgdm->dm.edgeData.totlayer - (edgeOrigIndex ? 1 : 0)) != 0);
1317
1318 loopindex = loopindex2 = 0; /* current loop index */
1319 for (index = 0; index < totface; index++) {
1320 CCGFace *f = ccgdm->faceMap[index].face;
1321 int numVerts = ccgSubSurf_getFaceNumVerts(f);
1322 int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
1323 int origIndex = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
1324 int g2_wid = gridCuts + 2;
1325 float *w, *w2;
1326 int s, x, y;
1327
1328 w = get_ss_weights(&wtable, gridCuts, numVerts);
1329
1330 ccgdm->faceMap[index].startVert = vertNum;
1331 ccgdm->faceMap[index].startEdge = edgeNum;
1332 ccgdm->faceMap[index].startFace = faceNum;
1333
1334 /* set the face base vert */
1335 *((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
1336
1337 loopidx.reinitialize(numVerts);
1338 for (s = 0; s < numVerts; s++) {
1339 loopidx[s] = loopindex++;
1340 }
1341
1342 vertidx.reinitialize(numVerts);
1343 for (s = 0; s < numVerts; s++) {
1346 }
1347
1348 /* I think this is for interpolating the center vert? */
1349 w2 = w; // + numVerts*(g2_wid-1) * (g2_wid-1); //numVerts*((g2_wid-1) * g2_wid+g2_wid-1);
1350 DM_interp_vert_data(dm, &ccgdm->dm, vertidx.data(), w2, numVerts, vertNum);
1351 if (vertOrigIndex) {
1352 *vertOrigIndex = ORIGINDEX_NONE;
1353 vertOrigIndex++;
1354 }
1355
1356 vertNum++;
1357
1358 /* Interpolate per-vert data. */
1359 for (s = 0; s < numVerts; s++) {
1360 for (x = 1; x < gridFaces; x++) {
1361 w2 = w + s * numVerts * g2_wid * g2_wid + x * numVerts;
1362 DM_interp_vert_data(dm, &ccgdm->dm, vertidx.data(), w2, numVerts, vertNum);
1363
1364 if (vertOrigIndex) {
1365 *vertOrigIndex = ORIGINDEX_NONE;
1366 vertOrigIndex++;
1367 }
1368
1369 vertNum++;
1370 }
1371 }
1372
1373 /* Interpolate per-vert data. */
1374 for (s = 0; s < numVerts; s++) {
1375 for (y = 1; y < gridFaces; y++) {
1376 for (x = 1; x < gridFaces; x++) {
1377 w2 = w + s * numVerts * g2_wid * g2_wid + (y * g2_wid + x) * numVerts;
1378 DM_interp_vert_data(dm, &ccgdm->dm, vertidx.data(), w2, numVerts, vertNum);
1379
1380 if (vertOrigIndex) {
1381 *vertOrigIndex = ORIGINDEX_NONE;
1382 vertOrigIndex++;
1383 }
1384
1385 vertNum++;
1386 }
1387 }
1388 }
1389
1390 if (edgeOrigIndex) {
1391 for (i = 0; i < numFinalEdges; i++) {
1392 edgeOrigIndex[edgeNum + i] = ORIGINDEX_NONE;
1393 }
1394 }
1395
1396 for (s = 0; s < numVerts; s++) {
1397 /* Interpolate per-face data. */
1398 for (y = 0; y < gridFaces; y++) {
1399 for (x = 0; x < gridFaces; x++) {
1400 w2 = w + s * numVerts * g2_wid * g2_wid + (y * g2_wid + x) * numVerts;
1402 &ccgdm->dm.loopData,
1403 loopidx.data(),
1404 w2,
1405 nullptr,
1406 numVerts,
1407 loopindex2);
1408 loopindex2++;
1409
1410 w2 = w + s * numVerts * g2_wid * g2_wid + ((y + 1) * g2_wid + (x)) * numVerts;
1412 &ccgdm->dm.loopData,
1413 loopidx.data(),
1414 w2,
1415 nullptr,
1416 numVerts,
1417 loopindex2);
1418 loopindex2++;
1419
1420 w2 = w + s * numVerts * g2_wid * g2_wid + ((y + 1) * g2_wid + (x + 1)) * numVerts;
1422 &ccgdm->dm.loopData,
1423 loopidx.data(),
1424 w2,
1425 nullptr,
1426 numVerts,
1427 loopindex2);
1428 loopindex2++;
1429
1430 w2 = w + s * numVerts * g2_wid * g2_wid + ((y)*g2_wid + (x + 1)) * numVerts;
1432 &ccgdm->dm.loopData,
1433 loopidx.data(),
1434 w2,
1435 nullptr,
1436 numVerts,
1437 loopindex2);
1438 loopindex2++;
1439
1440 CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
1441
1442 if (polyOrigIndex) {
1443 *polyOrigIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
1444 polyOrigIndex++;
1445 }
1446
1447 /* This is a simple one to one mapping, here... */
1448 if (polyidx) {
1449 polyidx[faceNum] = faceNum;
1450 }
1451
1452 faceNum++;
1453 }
1454 }
1455 }
1456
1457 edgeNum += numFinalEdges;
1458 }
1459
1460 for (index = 0; index < totedge; index++) {
1461 CCGEdge *e = ccgdm->edgeMap[index].edge;
1462 int numFinalEdges = edgeSize - 1;
1463 int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
1464 int x;
1465 int vertIdx[2];
1467
1468 CCGVert *v;
1473
1474 ccgdm->edgeMap[index].startVert = vertNum;
1475 ccgdm->edgeMap[index].startEdge = edgeNum;
1476
1477 /* set the edge base vert */
1478 *((int *)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
1479
1480 for (x = 1; x < edgeSize - 1; x++) {
1481 float w[2];
1482 w[1] = float(x) / (edgeSize - 1);
1483 w[0] = 1 - w[1];
1484 DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
1485 if (vertOrigIndex) {
1486 *vertOrigIndex = ORIGINDEX_NONE;
1487 vertOrigIndex++;
1488 }
1489 vertNum++;
1490 }
1491
1492 if (has_edge_cd) {
1493 BLI_assert(edgeIdx >= 0 && edgeIdx < dm->getNumEdges(dm));
1494 for (i = 0; i < numFinalEdges; i++) {
1495 CustomData_copy_data(&dm->edgeData, &ccgdm->dm.edgeData, edgeIdx, edgeNum + i, 1);
1496 }
1497 }
1498
1499 if (edgeOrigIndex) {
1500 for (i = 0; i < numFinalEdges; i++) {
1501 edgeOrigIndex[edgeNum + i] = mapIndex;
1502 }
1503 }
1504
1505 edgeNum += numFinalEdges;
1506 }
1507
1508 if (useSubsurfUv) {
1509 CustomData *loop_data = &ccgdm->dm.loopData;
1510 CustomData *dmldata = &dm->loopData;
1511 int numlayer = CustomData_number_of_layers(loop_data, CD_PROP_FLOAT2);
1512 int dmnumlayer = CustomData_number_of_layers(dmldata, CD_PROP_FLOAT2);
1513
1514 for (i = 0; i < numlayer && i < dmnumlayer; i++) {
1515 set_subsurf_uv(ss, dm, &ccgdm->dm, i);
1516 }
1517 }
1518
1519 for (index = 0; index < totvert; index++) {
1520 CCGVert *v = ccgdm->vertMap[index].vert;
1521 int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v);
1522 int vertIdx;
1523
1525
1526 ccgdm->vertMap[index].startVert = vertNum;
1527
1528 /* set the vert base vert */
1529 *((int *)ccgSubSurf_getVertUserData(ss, v)) = vertNum;
1530
1531 DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
1532
1533 if (vertOrigIndex) {
1534 *vertOrigIndex = mapIndex;
1535 vertOrigIndex++;
1536 }
1537 vertNum++;
1538 }
1539
1540 free_ss_weights(&wtable);
1541
1544 BLI_assert(loopindex2 == ccgSubSurf_getNumFinalFaces(ss) * 4);
1546}
1547
1549 int drawInteriorEdges,
1550 int useSubsurfUv,
1551 DerivedMesh *dm)
1552{
1553 CCGDerivedMesh *ccgdm = MEM_cnew<CCGDerivedMesh>(__func__);
1554 DM_from_template(&ccgdm->dm,
1555 dm,
1559 0,
1565 &ccgdm->dm.loopData, ".corner_vert", ccgSubSurf_getNumFinalFaces(ss) * 4);
1567 &ccgdm->dm.loopData, ".corner_edge", ccgSubSurf_getNumFinalFaces(ss) * 4);
1569
1570 create_ccgdm_maps(ccgdm, ss);
1571
1573
1574 ccgdm->ss = ss;
1575 ccgdm->drawInteriorEdges = drawInteriorEdges;
1576 ccgdm->useSubsurfUv = useSubsurfUv;
1577
1578 set_ccgdm_all_geometry(ccgdm, ss, dm, useSubsurfUv != 0);
1579
1583 ccgdm->dm.numLoopData = ccgdm->dm.numPolyData * 4;
1584 ccgdm->dm.numTessFaceData = 0;
1585
1588
1589 return ccgdm;
1590}
1591
1592/***/
1593
1596 const Scene *scene,
1597 float (*vertCos)[3],
1598 SubsurfFlags flags)
1599{
1600 const CCGFlags useSimple = (smd->subdivType == ME_SIMPLE_SUBSURF) ? CCG_SIMPLE_SUBDIV :
1601 CCGFlags(0);
1602 const CCGFlags useAging = (smd->flags & eSubsurfModifierFlag_DebugIncr) ? CCG_USE_AGING :
1603 CCGFlags(0);
1604 const int useSubsurfUv = (smd->uv_smooth != SUBSURF_UV_SMOOTH_NONE);
1605 const int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
1606 const bool ignore_simplify = (flags & SUBSURF_IGNORE_SIMPLIFY);
1608
1609 /* NOTE: editmode calculation can only run once per
1610 * modifier stack evaluation (uses freed cache) #36299. */
1611 if (flags & SUBSURF_FOR_EDIT_MODE) {
1612 int levels = (scene != nullptr && !ignore_simplify) ?
1613 get_render_subsurf_level(&scene->r, smd->levels, false) :
1614 smd->levels;
1615
1616 /* TODO(sergey): Same as emCache below. */
1617 if ((flags & SUBSURF_IN_EDIT_MODE) && smd->mCache) {
1618 ccgSubSurf_free(static_cast<CCGSubSurf *>(smd->mCache));
1619 smd->mCache = nullptr;
1620 }
1621
1622 smd->emCache = _getSubSurf(static_cast<CCGSubSurf *>(smd->emCache),
1623 levels,
1624 3,
1625 useSimple | useAging | CCG_CALC_NORMALS);
1626
1628 static_cast<CCGSubSurf *>(smd->emCache), dm, vertCos, useSimple, useSubsurfUv);
1629 result = getCCGDerivedMesh(
1630 static_cast<CCGSubSurf *>(smd->emCache), drawInteriorEdges, useSubsurfUv, dm);
1631 }
1632 else if (flags & SUBSURF_USE_RENDER_PARAMS) {
1633 /* Do not use cache in render mode. */
1634 CCGSubSurf *ss;
1635 int levels = (scene != nullptr && !ignore_simplify) ?
1636 get_render_subsurf_level(&scene->r, smd->renderLevels, true) :
1637 smd->renderLevels;
1638
1639 if (levels == 0) {
1640 return dm;
1641 }
1642
1643 ss = _getSubSurf(nullptr, levels, 3, useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS);
1644
1645 ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv);
1646
1647 result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
1648
1649 result->freeSS = 1;
1650 }
1651 else {
1652 int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
1653 int levels = (scene != nullptr && !ignore_simplify) ?
1654 get_render_subsurf_level(&scene->r, smd->levels, false) :
1655 smd->levels;
1656 CCGSubSurf *ss;
1657
1658 /* It is quite possible there is a much better place to do this. It
1659 * depends a bit on how rigorously we expect this function to never
1660 * be called in editmode. In semi-theory we could share a single
1661 * cache, but the handles used inside and outside editmode are not
1662 * the same so we would need some way of converting them. Its probably
1663 * not worth the effort. But then why am I even writing this long
1664 * comment that no one will read? Hmmm. - zr
1665 *
1666 * Addendum: we can't really ensure that this is never called in edit
1667 * mode, so now we have a parameter to verify it. - brecht
1668 */
1669 if (!(flags & SUBSURF_IN_EDIT_MODE) && smd->emCache) {
1670 ccgSubSurf_free(static_cast<CCGSubSurf *>(smd->emCache));
1671 smd->emCache = nullptr;
1672 }
1673
1674 if (useIncremental && (flags & SUBSURF_IS_FINAL_CALC)) {
1675 smd->mCache = ss = _getSubSurf(static_cast<CCGSubSurf *>(smd->mCache),
1676 levels,
1677 3,
1678 useSimple | useAging | CCG_CALC_NORMALS);
1679
1680 ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv);
1681
1682 result = getCCGDerivedMesh(
1683 static_cast<CCGSubSurf *>(smd->mCache), drawInteriorEdges, useSubsurfUv, dm);
1684 }
1685 else {
1686 CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS;
1687 CCGSubSurf *prevSS = nullptr;
1688
1689 if ((smd->mCache) && (flags & SUBSURF_IS_FINAL_CALC)) {
1690 ccgSubSurf_free(static_cast<CCGSubSurf *>(smd->mCache));
1691 smd->mCache = nullptr;
1692 }
1693
1694 if (flags & SUBSURF_ALLOC_PAINT_MASK) {
1695 ccg_flags |= CCG_ALLOC_MASK;
1696 }
1697
1698 ss = _getSubSurf(prevSS, levels, 3, ccg_flags);
1699 ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv);
1700
1701 result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
1702
1703 if (flags & SUBSURF_IS_FINAL_CALC) {
1704 smd->mCache = ss;
1705 }
1706 else {
1707 result->freeSS = 1;
1708 }
1709
1710 if (flags & SUBSURF_ALLOC_PAINT_MASK) {
1712 }
1713 }
1714 }
1715
1716 return (DerivedMesh *)result;
1717}
1718
1719void subsurf_calculate_limit_positions(Mesh *mesh, float (*r_positions)[3])
1720{
1721 /* Finds the subsurf limit positions for the verts in a mesh
1722 * and puts them in an array of floats. Please note that the
1723 * calculated vert positions is incorrect for the verts
1724 * on the boundary of the mesh.
1725 */
1726 CCGSubSurf *ss = _getSubSurf(nullptr, 1, 3, CCG_USE_ARENA);
1727 float edge_sum[3], face_sum[3];
1728 CCGVertIterator vi;
1729 DerivedMesh *dm = CDDM_from_mesh(mesh);
1730
1731 ss_sync_from_derivedmesh(ss, dm, nullptr, 0, false);
1732
1735 {
1739 int numFaces = ccgSubSurf_getVertNumFaces(v);
1740 int i;
1741
1742 zero_v3(edge_sum);
1743 zero_v3(face_sum);
1744
1745 for (i = 0; i < N; i++) {
1748 edge_sum, edge_sum, static_cast<const float *>(ccgSubSurf_getEdgeData(ss, e, 1)));
1749 }
1750 for (i = 0; i < numFaces; i++) {
1752 add_v3_v3(face_sum, static_cast<const float *>(ccgSubSurf_getFaceCenterData(f)));
1753 }
1754
1755 /* ad-hoc correction for boundary vertices, to at least avoid them
1756 * moving completely out of place (brecht) */
1757 if (numFaces && numFaces != N) {
1758 mul_v3_fl(face_sum, float(N) / float(numFaces));
1759 }
1760
1761 const float *co = static_cast<const float *>(ccgSubSurf_getVertData(ss, v));
1762 r_positions[idx][0] = (co[0] * N * N + edge_sum[0] * 4 + face_sum[0]) / (N * (N + 5));
1763 r_positions[idx][1] = (co[1] * N * N + edge_sum[1] * 4 + face_sum[1]) / (N * (N + 5));
1764 r_positions[idx][2] = (co[2] * N * N + edge_sum[2] * 4 + face_sum[2]) / (N * (N + 5));
1765 }
1766
1767 ccgSubSurf_free(ss);
1768
1769 dm->release(dm);
1770}
void CCG_key_top_level(CCGKey *key, const CCGSubSurf *ss)
blender::float3 & CCG_elem_co(const CCGKey &, CCGElem *elem)
Definition BKE_ccg.hh:55
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer_n(const CustomData *data, eCustomDataType type, int n)
bool CustomData_free_layer_named(CustomData *data, blender::StringRef name, const int totelem)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
@ CD_SET_DEFAULT
void CustomData_interp(const CustomData *source, CustomData *dest, const int *src_indices, const float *weights, const float *sub_weights, int count, int dest_index)
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
#define ORIGINDEX_NONE
void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_n_for_write(CustomData *data, eCustomDataType type, int n, int totelem)
void * DM_get_edge_data_layer(DerivedMesh *dm, eCustomDataType type)
void DM_release(DerivedMesh *dm)
void DM_interp_vert_data(const DerivedMesh *source, DerivedMesh *dest, int *src_indices, float *weights, int count, int dest_index)
void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
void DM_copy_vert_data(const DerivedMesh *source, DerivedMesh *dest, int source_index, int dest_index, int count)
void * DM_get_vert_data_layer(DerivedMesh *dm, eCustomDataType type)
DerivedMesh * CDDM_from_mesh(Mesh *mesh)
void * DM_get_poly_data_layer(DerivedMesh *dm, eCustomDataType type)
UvVertMap * BKE_mesh_uv_vert_map_create(blender::OffsetIndices< int > faces, const bool *hide_poly, const bool *select_poly, const int *corner_verts, const float(*mloopuv)[2], unsigned int totvert, const float limit[2], bool selected, bool use_winding)
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
UvMapVert * BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v)
#define STD_UV_CONNECT_LIMIT
void multires_modifier_update_mdisps(DerivedMesh *dm, Scene *scene)
Definition multires.cc:1033
void multires_modifier_update_hidden(DerivedMesh *dm)
Definition multires.cc:1163
int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
Definition scene.cc:2700
@ MULTIRES_HIDDEN_MODIFIED
@ MULTIRES_COORDS_MODIFIED
SubsurfFlags
@ SUBSURF_FOR_EDIT_MODE
@ SUBSURF_IN_EDIT_MODE
@ SUBSURF_ALLOC_PAINT_MASK
@ SUBSURF_USE_RENDER_PARAMS
@ SUBSURF_IS_FINAL_CALC
@ SUBSURF_IGNORE_SIMPLIFY
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_INLINE
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
unsigned int uint
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
void BLI_rw_mutex_end(ThreadRWMutex *mutex)
Definition threads.cc:482
void BLI_mutex_end(ThreadMutex *mutex)
Definition threads.cc:360
#define THREAD_LOCK_READ
void BLI_mutex_init(ThreadMutex *mutex)
Definition threads.cc:340
#define THREAD_LOCK_WRITE
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
Definition threads.cc:467
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
void BLI_rw_mutex_init(ThreadRWMutex *mutex)
Definition threads.cc:462
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
Definition threads.cc:477
#define ENUM_OPERATORS(_type, _max)
#define POINTER_FROM_INT(i)
#define POINTER_AS_UINT(i)
#define POINTER_AS_INT(i)
#define POINTER_FROM_UINT(i)
void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter)
int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss)
CCGFace * ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f)
int ccgSubSurf_getNumFaces(const CCGSubSurf *ss)
void ccgVertIterator_next(CCGVertIterator *vi)
int ccgSubSurf_getVertNumFaces(CCGVert *v)
int ccgSubSurf_getNumFinalFaces(const CCGSubSurf *ss)
int ccgFaceIterator_isStopped(CCGFaceIterator *fi)
CCGSubSurf * ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator)
int ccgEdgeIterator_isStopped(CCGEdgeIterator *ei)
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_getVertData(CCGSubSurf *ss, CCGVert *v)
CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r)
int ccgSubSurf_getSubdivisionLevels(const 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)
void * ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v)
CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset)
CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r)
int ccgSubSurf_getSimpleSubdiv(const CCGSubSurf *ss)
void * ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex)
int ccgSubSurf_getGridSize(const CCGSubSurf *ss)
float ccgSubSurf_getEdgeCrease(CCGEdge *e)
CCGFace * ccgSubSurf_getVertFace(CCGVert *v, int index)
CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGEdge *e)
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)
CCGEdge * ccgSubSurf_getFaceEdge(CCGFace *f, int index)
int ccgSubSurf_getNumEdges(const CCGSubSurf *ss)
int ccgSubSurf_getNumFinalVerts(const CCGSubSurf *ss)
void * ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y)
void ccgFaceIterator_next(CCGFaceIterator *fi)
int ccgVertIterator_isStopped(CCGVertIterator *vi)
CCGEdge * ccgEdgeIterator_getCurrent(CCGEdgeIterator *ei)
CCGVert * ccgSubSurf_getFaceVert(CCGFace *f, int index)
int ccgSubSurf_getEdgeSize(const CCGSubSurf *ss)
CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels)
CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v)
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_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x)
void * CCGEdgeHDL
Definition CCGSubSurf.h:17
void * CCGVertHDL
Definition CCGSubSurf.h:16
@ eCCGError_InvalidValue
Definition CCGSubSurf.h:56
void * CCGAllocatorHDL
Definition CCGSubSurf.h:34
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT2
@ ME_SIMPLE_SUBSURF
@ eSubsurfModifierFlag_Incremental
@ eSubsurfModifierFlag_DebugIncr
@ eSubsurfModifierFlag_ControlEdges
@ SUBSURF_UV_SMOOTH_NONE
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_SIZE_OPTIMAL(size)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE void * atomic_cas_ptr(void **v, void *old, void *_new)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
virtual int getNumEdges() const
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr int64_t size() const
void reserve(const int64_t n)
Definition BLI_set.hh:614
bool add(const Key &key)
Definition BLI_set.hh:248
int64_t index_of(const Key &key) const
void reinitialize(const int64_t new_size)
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static ulong * next
#define N
static char faces[256]
const int faceMap[6][4]
Definition octree.cpp:2829
void(* free)(CCGAllocatorHDL a, void *ptr)
Definition CCGSubSurf.h:39
void(* release)(CCGAllocatorHDL a)
Definition CCGSubSurf.h:40
void *(* alloc)(CCGAllocatorHDL a, int numBytes)
Definition CCGSubSurf.h:37
void *(* realloc)(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize)
Definition CCGSubSurf.h:38
struct CCGDerivedMesh::@68 * faceMap
blender::VectorSet< blender::OrderedEdge > * ehash
MultiresModifierData * mmd
unsigned int numGrid
CCGEdge * edge
MultiresModifiedFlags modified_flags
ThreadMutex loops_cache_lock
unsigned int ** gridHidden
CCGVert * vert
struct CCGDerivedMesh::@67 * edgeMap
DerivedMesh dm
CCGFace * face
struct CCGDerivedMesh::@66 * vertMap
CCGSubSurf * ss
CCGFace ** gridFaces
CCGElem ** gridData
ThreadRWMutex origindex_cache_rwlock
struct CCGDerivedMesh::@69 multires
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
CCGDerivedMesh * ccgdm
int(* getGridSize)(DerivedMesh *dm)
void *(* getEdgeDataArray)(DerivedMesh *dm, eCustomDataType type)
int *(* getPolyArray)(DerivedMesh *dm)
int(* getNumVerts)(DerivedMesh *dm)
int *(* getCornerVertArray)(DerivedMesh *dm)
void *(* getPolyDataArray)(DerivedMesh *dm, eCustomDataType type)
int(* getNumPolys)(DerivedMesh *dm)
void(* copyVertArray)(DerivedMesh *dm, float(*r_positions)[3])
void(* copyCornerEdgeArray)(DerivedMesh *dm, int *r_corner_edges)
int(* getNumEdges)(DerivedMesh *dm)
void *(* getVertDataArray)(DerivedMesh *dm, eCustomDataType type)
void(* copyEdgeArray)(DerivedMesh *dm, blender::int2 *r_edge)
int(* getNumGrids)(DerivedMesh *dm)
float *(* getVertArray)(DerivedMesh *dm)
void(* copyPolyArray)(DerivedMesh *dm, int *r_face_offsets)
int *(* getGridOffset)(DerivedMesh *dm)
blender::int2 *(* getEdgeArray)(DerivedMesh *dm)
void(* copyCornerVertArray)(DerivedMesh *dm, int *r_corner_verts)
CCGElem **(* getGridData)(DerivedMesh *dm)
void(* release)(DerivedMesh *dm)
void(* getGridKey)(DerivedMesh *dm, CCGKey *key)
int(* getNumLoops)(DerivedMesh *dm)
FaceVertWeight * weight
float uv[4][2]
ListBase modifiers
unsigned int face_index
unsigned short loop_of_face_index
FaceVertWeightEntry * weight_table
static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize)
static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, DerivedMesh *dm, bool useSubsurfUv)
static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges)
float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE]
static CCGElem ** ccgDM_getGridData(DerivedMesh *dm)
static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, int *r_face_offsets)
static float * get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
static void ccgdm_create_grids(DerivedMesh *dm)
static void * arena_alloc(CCGAllocatorHDL a, int numBytes)
static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize)
static void free_ss_weights(WeightTable *wtable)
static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f)
static void ccgDM_copyFinalCornerVertArray(DerivedMesh *dm, int *r_corner_verts)
static int ccgDM_getNumEdges(DerivedMesh *dm)
static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v)
static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e)
static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, const float(*mloopuv)[2])
static int ccgDM_getNumVerts(DerivedMesh *dm)
static void get_face_uv_map_vert(UvVertMap *vmap, const blender::OffsetIndices< int > faces, const int *face_verts, int fi, CCGVertHDL *fverts)
static void copyFinalLoopArray_task_cb(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict)
BLI_INLINE void ccgDM_to_MVert(float mv[3], const CCGKey *key, CCGElem *elem)
void subsurf_calculate_limit_positions(Mesh *mesh, float(*r_positions)[3])
static void * ccgDM_get_edge_data_layer(DerivedMesh *dm, const eCustomDataType type)
static void ccgDM_copyFinalVertArray(DerivedMesh *dm, float(*r_positions)[3])
static int ccgDM_getNumGrids(DerivedMesh *dm)
static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, float(*vertexCos)[3], int use_flat_subdiv, bool)
static int ccgDM_getNumLoops(DerivedMesh *dm)
static void ccgDM_release(DerivedMesh *dm)
#define SUB_ELEMS_FACE
static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, float(*vertexCos)[3], int useFlatSubdiv)
static void * arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize)
static int ccgDM_getGridSize(DerivedMesh *dm)
DerivedMesh * subsurf_make_derived_from_derived(DerivedMesh *dm, SubsurfModifierData *smd, const Scene *scene, float(*vertCos)[3], SubsurfFlags flags)
static CCGSubSurf * _getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int numLayers, CCGFlags flags)
static void arena_release(CCGAllocatorHDL a)
static void * ccgDM_get_poly_data_layer(DerivedMesh *dm, const eCustomDataType type)
static int ccgDM_getNumPolys(DerivedMesh *dm)
static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
static void create_ccgdm_maps(CCGDerivedMesh *ccgdm, CCGSubSurf *ss)
static CCGDerivedMesh * getCCGDerivedMesh(CCGSubSurf *ss, int drawInteriorEdges, int useSubsurfUv, DerivedMesh *dm)
static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int layer_index)
static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, blender::int2 *edges)
static int * ccgDM_getGridOffset(DerivedMesh *dm)
CCGFlags
@ CCG_ALLOC_MASK
@ CCG_CALC_NORMALS
@ CCG_USE_ARENA
@ CCG_SIMPLE_SUBDIV
@ CCG_USE_AGING
static void ccgDM_getGridKey(DerivedMesh *dm, CCGKey *key)
static void * ccgDM_get_vert_data_layer(DerivedMesh *dm, const eCustomDataType type)
static void arena_free(CCGAllocatorHDL, void *)
BLI_INLINE void ccgDM_to_MEdge(blender::int2 *edge, const int v1, const int v2)
PointerRNA * ptr
Definition wm_files.cc:4126