4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2005 Blender Foundation.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
36 #include "MEM_guardedalloc.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_modifier_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_scene_types.h"
44 #include "BKE_cdderivedmesh.h"
45 #include "BKE_customdata.h"
46 #include "BKE_DerivedMesh.h"
47 #include "BKE_displist.h"
48 #include "BKE_utildefines.h"
49 #include "BKE_global.h"
51 #include "BKE_multires.h"
52 #include "BKE_scene.h"
53 #include "BKE_subsurf.h"
55 #include "BLI_blenlib.h"
56 #include "BLI_edgehash.h"
57 #include "BLI_editVert.h"
58 #include "BLI_linklist.h"
60 #include "BLI_memarena.h"
64 #include "BIF_glutil.h"
67 #include "GPU_extensions.h"
68 #include "GPU_material.h"
70 #include "CCGSubSurf.h"
72 static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v);
73 static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e);
74 static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);
78 static void *arena_alloc(CCGAllocatorHDL a, int numBytes) {
79 return BLI_memarena_alloc(a, numBytes);
81 static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
82 void *p2 = BLI_memarena_alloc(a, newSize);
84 memcpy(p2, ptr, oldSize);
88 static void arena_free(CCGAllocatorHDL a, void *ptr) {
90 static void arena_release(CCGAllocatorHDL a) {
94 static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int useFlatSubdiv) {
98 /* subdivLevels==0 is not allowed */
99 subdivLevels = MAX2(subdivLevels, 1);
104 useAging = !!useAging;
105 ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
107 if (oldUseAging!=useAging) {
108 ccgSubSurf_free(prevSS);
110 ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
117 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 12;
119 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
121 ifc.vertDataSize = sizeof(DMGridData);
124 CCGAllocatorIFC allocatorIFC;
125 CCGAllocatorHDL allocator = BLI_memarena_new((1<<16));
127 allocatorIFC.alloc = arena_alloc;
128 allocatorIFC.realloc = arena_realloc;
129 allocatorIFC.free = arena_free;
130 allocatorIFC.release = arena_release;
132 ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
134 ccgSS = ccgSubSurf_new(&ifc, subdivLevels, NULL, NULL);
138 ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
141 ccgSubSurf_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(DMGridData, no));
146 static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
147 CCGVert *v0 = ccgSubSurf_getEdgeVert0(e);
148 CCGVert *v1 = ccgSubSurf_getEdgeVert1(e);
149 int v0idx = *((int*) ccgSubSurf_getVertUserData(ss, v0));
150 int v1idx = *((int*) ccgSubSurf_getVertUserData(ss, v1));
151 int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
155 } else if (x==edgeSize-1) {
158 return edgeBase + x-1;
161 static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
162 int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
163 int numVerts = ccgSubSurf_getFaceNumVerts(f);
165 if (x==gridSize-1 && y==gridSize-1) {
166 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
167 return *((int*) ccgSubSurf_getVertUserData(ss, v));
168 } else if (x==gridSize-1) {
169 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
170 CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
171 int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
172 if (v==ccgSubSurf_getEdgeVert0(e)) {
173 return edgeBase + (gridSize-1-y)-1;
175 return edgeBase + (edgeSize-2-1)-((gridSize-1-y)-1);
177 } else if (y==gridSize-1) {
178 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
179 CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
180 int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
181 if (v==ccgSubSurf_getEdgeVert0(e)) {
182 return edgeBase + (gridSize-1-x)-1;
184 return edgeBase + (edgeSize-2-1)-((gridSize-1-x)-1);
186 } else if (x==0 && y==0) {
189 S = (S+numVerts-1)%numVerts;
190 return faceBase + 1 + (gridSize-2)*S + (y-1);
192 return faceBase + 1 + (gridSize-2)*S + (x-1);
194 return faceBase + 1 + (gridSize-2)*numVerts + S*(gridSize-2)*(gridSize-2) + (y-1)*(gridSize-2) + (x-1);
198 static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGVertHDL *fverts) {
199 unsigned int *fv = &mf->v1;
201 int j, nverts= mf->v4? 4: 3;
203 for (j=0; j<nverts; j++, fv++) {
204 for (nv=v=get_uv_map_vert(vmap, *fv); v; v=v->next) {
211 fverts[j]= SET_INT_IN_POINTER(nv->f*4 + nv->tfindex);
215 static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MTFace *tface) {
216 MFace *mface = dm->getFaceArray(dm);
217 MVert *mvert = dm->getVertArray(dm);
218 int totvert = dm->getNumVerts(dm);
219 int totface = dm->getNumFaces(dm);
224 CCGVertHDL fverts[4];
226 float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
228 limit[0]= limit[1]= STD_UV_CONNECT_LIMIT;
229 vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit);
233 ccgSubSurf_initFullSync(ss);
235 /* create vertices */
236 for (i=0; i<totvert; i++) {
237 if (!get_uv_map_vert(vmap, i))
240 for (v=get_uv_map_vert(vmap, i)->next; v; v=v->next)
244 seam = (v != NULL) || ((mvert+i)->flag & ME_VERT_MERGED);
246 for (v=get_uv_map_vert(vmap, i); v; v=v->next) {
249 CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex);
252 uv[0]= (tface+v->f)->uv[v->tfindex][0];
253 uv[1]= (tface+v->f)->uv[v->tfindex][1];
256 ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
262 ehash = BLI_edgehash_new();
264 for (i=0; i<totface; i++) {
265 MFace *mf = &((MFace*) mface)[i];
266 int nverts= mf->v4? 4: 3;
267 CCGFace *origf= ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i));
268 unsigned int *fv = &mf->v1;
270 get_face_uv_map_vert(vmap, mf, i, fverts);
272 for (j=0; j<nverts; j++) {
273 int v0 = GET_INT_FROM_POINTER(fverts[j]);
274 int v1 = GET_INT_FROM_POINTER(fverts[(j+1)%nverts]);
275 MVert *mv0 = mvert + *(fv+j);
276 MVert *mv1 = mvert + *(fv+((j+1)%nverts));
278 if (!BLI_edgehash_haskey(ehash, v0, v1)) {
279 CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j);
280 CCGEdgeHDL ehdl= SET_INT_IN_POINTER(i*4 + j);
283 if ((mv0->flag&mv1->flag) & ME_VERT_MERGED)
284 crease = creaseFactor;
286 crease = ccgSubSurf_getEdgeCrease(orige);
288 ccgSubSurf_syncEdge(ss, ehdl, fverts[j], fverts[(j+1)%nverts], crease, &e);
289 BLI_edgehash_insert(ehash, v0, v1, NULL);
294 BLI_edgehash_free(ehash, NULL);
297 for (i=0; i<totface; i++) {
298 MFace *mf = &((MFace*) mface)[i];
299 int nverts= mf->v4? 4: 3;
302 get_face_uv_map_vert(vmap, mf, i, fverts);
303 ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f);
306 free_uv_vert_map(vmap);
307 ccgSubSurf_processSync(ss);
312 static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
318 int index, gridSize, gridFaces, edgeSize, totface, x, y, S;
319 MTFace *dmtface = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, n);
320 MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
322 if(!dmtface || !tface)
325 /* create a CCGSubSurf from uv's */
326 uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0);
328 if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) {
329 ccgSubSurf_free(uvss);
333 /* get some info from CCGSubSurf */
334 totface = ccgSubSurf_getNumFaces(uvss);
335 edgeSize = ccgSubSurf_getEdgeSize(uvss);
336 gridSize = ccgSubSurf_getGridSize(uvss);
337 gridFaces = gridSize - 1;
339 /* make a map from original faces to CCGFaces */
340 faceMap = MEM_mallocN(totface*sizeof(*faceMap), "facemapuv");
342 fi = ccgSubSurf_getFaceIterator(uvss);
343 for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
344 CCGFace *f = ccgFaceIterator_getCurrent(fi);
345 faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(uvss, f))] = f;
347 ccgFaceIterator_free(fi);
349 /* load coordinates from uvss into tface */
352 for(index = 0; index < totface; index++) {
353 CCGFace *f = faceMap[index];
354 int numVerts = ccgSubSurf_getFaceNumVerts(f);
356 for (S=0; S<numVerts; S++) {
357 DMGridData *faceGridData= ccgSubSurf_getFaceGridDataArray(uvss, f, S);
359 for(y = 0; y < gridFaces; y++) {
360 for(x = 0; x < gridFaces; x++) {
361 float *a = faceGridData[(y + 0)*gridSize + x + 0].co;
362 float *b = faceGridData[(y + 0)*gridSize + x + 1].co;
363 float *c = faceGridData[(y + 1)*gridSize + x + 1].co;
364 float *d = faceGridData[(y + 1)*gridSize + x + 0].co;
366 tf->uv[0][0] = a[0]; tf->uv[0][1] = a[1];
367 tf->uv[1][0] = d[0]; tf->uv[1][1] = d[1];
368 tf->uv[2][0] = c[0]; tf->uv[2][1] = c[1];
369 tf->uv[3][0] = b[0]; tf->uv[3][1] = b[1];
377 ccgSubSurf_free(uvss);
382 static void calc_ss_weights(int gridFaces,
383 FaceVertWeight **qweight, FaceVertWeight **tweight)
385 FaceVertWeight *qw, *tw;
387 int numWeights = gridFaces * gridFaces;
389 *tweight = MEM_mallocN(sizeof(**tweight) * numWeights, "ssTriWeight");
390 *qweight = MEM_mallocN(sizeof(**qweight) * numWeights, "ssQuadWeight");
395 for (y = 0; y < gridFaces; y++) {
396 for (x = 0; x < gridFaces; x++) {
397 for (j = 0; j < 4; j++) {
398 int fx = x + (j == 2 || j == 3);
399 int fy = y + (j == 1 || j == 2);
400 float x_v = (float) fx / gridFaces;
401 float y_v = (float) fy / gridFaces;
402 float tx_v = (1.0f - x_v), ty_v = (1.0f - y_v);
403 float center = (1.0f / 3.0f) * tx_v * ty_v;
405 (*tw)[j][0] = center + 0.5f * tx_v * y_v;
406 (*tw)[j][2] = center + 0.5f * x_v * ty_v;
407 (*tw)[j][1] = 1.0f - (*tw)[j][0] - (*tw)[j][2];
413 (*qw)[j][3] = tx_v * ty_v;
414 (*qw)[j][0] = (*qw)[j][3] + tx_v * y_v;
415 (*qw)[j][2] = (*qw)[j][3] + x_v * ty_v;
416 (*qw)[j][1] = 1.0f - (*qw)[j][0] - (*qw)[j][2] - (*qw)[j][3];
425 static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
426 float (*vertexCos)[3], int useFlatSubdiv)
428 float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
429 CCGVertHDL fVerts[4];
430 int totvert = dm->getNumVerts(dm);
431 int totedge = dm->getNumEdges(dm);
432 int totface = dm->getNumFaces(dm);
435 MVert *mvert = dm->getVertArray(dm);
436 MEdge *medge = dm->getEdgeArray(dm);
437 MFace *mface = dm->getFaceArray(dm);
442 ccgSubSurf_initFullSync(ss);
445 index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
446 for(i = 0; i < totvert; i++, mv++) {
450 ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), vertexCos[i], 0, &v);
452 ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), mv->co, 0, &v);
455 ((int*)ccgSubSurf_getVertUserData(ss, v))[1] = (index)? *index++: i;
459 index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX);
460 for(i = 0; i < totedge; i++, me++) {
464 crease = useFlatSubdiv ? creaseFactor :
465 me->crease * creaseFactor / 255.0f;
467 ccgSubSurf_syncEdge(ss, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(me->v1),
468 SET_INT_IN_POINTER(me->v2), crease, &e);
470 ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index)? *index++: i;
474 index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX);
475 for (i = 0; i < totface; i++, mf++) {
478 fVerts[0] = SET_INT_IN_POINTER(mf->v1);
479 fVerts[1] = SET_INT_IN_POINTER(mf->v2);
480 fVerts[2] = SET_INT_IN_POINTER(mf->v3);
481 fVerts[3] = SET_INT_IN_POINTER(mf->v4);
483 // this is very bad, means mesh is internally consistent.
484 // it is not really possible to continue without modifying
485 // other parts of code significantly to handle missing faces.
486 // since this really shouldn't even be possible we just bail.
487 if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3,
488 fVerts, &f) == eCCGError_InvalidValue) {
489 static int hasGivenError = 0;
492 //XXX error("Unrecoverable error in SubSurf calculation,"
493 // " mesh is inconsistent.");
501 ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i;
504 ccgSubSurf_processSync(ss);
509 static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v) {
510 return ((int*) ccgSubSurf_getVertUserData(ss, v))[1];
513 static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e) {
514 return ((int*) ccgSubSurf_getEdgeUserData(ss, e))[1];
517 static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f) {
518 return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1];
521 static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
522 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
523 CCGSubSurf *ss = ccgdm->ss;
524 CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
525 CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
526 CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
527 int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
528 int gridSize = ccgSubSurf_getGridSize(ss);
530 if (!ccgSubSurf_getNumVerts(ss))
531 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
533 for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
534 CCGVert *v = ccgVertIterator_getCurrent(vi);
535 float *co = ccgSubSurf_getVertData(ss, v);
537 DO_MINMAX(co, min_r, max_r);
540 for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
541 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
542 DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
544 for (i=0; i<edgeSize; i++)
545 DO_MINMAX(edgeData[i].co, min_r, max_r);
548 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
549 CCGFace *f = ccgFaceIterator_getCurrent(fi);
550 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
552 for (S=0; S<numVerts; S++) {
553 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
555 for (y=0; y<gridSize; y++)
556 for (x=0; x<gridSize; x++)
557 DO_MINMAX(faceGridData[y*gridSize + x].co, min_r, max_r);
561 ccgFaceIterator_free(fi);
562 ccgEdgeIterator_free(ei);
563 ccgVertIterator_free(vi);
565 static int ccgDM_getNumVerts(DerivedMesh *dm) {
566 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
568 return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
570 static int ccgDM_getNumEdges(DerivedMesh *dm) {
571 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
573 return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
575 static int ccgDM_getNumFaces(DerivedMesh *dm) {
576 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
578 return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
581 static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
583 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
584 CCGSubSurf *ss = ccgdm->ss;
587 memset(mv, 0, sizeof(*mv));
589 if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
590 /* this vert comes from face data */
591 int lastface = ccgSubSurf_getNumFaces(ss) - 1;
593 int x, y, grid, numVerts;
595 int gridSize = ccgSubSurf_getGridSize(ss);
597 int gridInternalVerts;
602 while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert)
605 f = ccgdm->faceMap[i].face;
606 numVerts = ccgSubSurf_getFaceNumVerts(f);
608 gridSideVerts = gridSize - 2;
609 gridInternalVerts = gridSideVerts * gridSideVerts;
611 gridSideEnd = 1 + numVerts * gridSideVerts;
612 gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
614 offset = vertNum - ccgdm->faceMap[i].startVert;
616 copy_v3_v3(mv->co, ccgSubSurf_getFaceCenterData(f));
617 } else if(offset < gridSideEnd) {
619 grid = offset / gridSideVerts;
620 x = offset % gridSideVerts + 1;
621 copy_v3_v3(mv->co, ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x));
622 } else if(offset < gridInternalEnd) {
623 offset -= gridSideEnd;
624 grid = offset / gridInternalVerts;
625 offset %= gridInternalVerts;
626 y = offset / gridSideVerts + 1;
627 x = offset % gridSideVerts + 1;
628 copy_v3_v3(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y));
630 } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
631 /* this vert comes from edge data */
633 int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
637 while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert)
640 e = ccgdm->edgeMap[i].edge;
642 x = vertNum - ccgdm->edgeMap[i].startVert + 1;
643 copy_v3_v3(mv->co, ccgSubSurf_getEdgeData(ss, e, x));
645 /* this vert comes from vert data */
647 i = vertNum - ccgdm->vertMap[0].startVert;
649 v = ccgdm->vertMap[i].vert;
650 copy_v3_v3(mv->co, ccgSubSurf_getVertData(ss, v));
654 static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
656 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
657 CCGSubSurf *ss = ccgdm->ss;
660 memset(med, 0, sizeof(*med));
662 if(edgeNum < ccgdm->edgeMap[0].startEdge) {
663 /* this edge comes from face data */
664 int lastface = ccgSubSurf_getNumFaces(ss) - 1;
666 int x, y, grid, numVerts;
668 int gridSize = ccgSubSurf_getGridSize(ss);
669 int edgeSize = ccgSubSurf_getEdgeSize(ss);
671 int gridInternalEdges;
674 while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge)
677 f = ccgdm->faceMap[i].face;
678 numVerts = ccgSubSurf_getFaceNumVerts(f);
680 gridSideEdges = gridSize - 1;
681 gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
683 offset = edgeNum - ccgdm->faceMap[i].startEdge;
684 grid = offset / (gridSideEdges + gridInternalEdges);
685 offset %= (gridSideEdges + gridInternalEdges);
687 if(offset < gridSideEdges) {
689 med->v1 = getFaceIndex(ss, f, grid, x, 0, edgeSize, gridSize);
690 med->v2 = getFaceIndex(ss, f, grid, x+1, 0, edgeSize, gridSize);
692 offset -= gridSideEdges;
693 x = (offset / 2) / gridSideEdges + 1;
694 y = (offset / 2) % gridSideEdges;
695 if(offset % 2 == 0) {
696 med->v1 = getFaceIndex(ss, f, grid, x, y, edgeSize, gridSize);
697 med->v2 = getFaceIndex(ss, f, grid, x, y+1, edgeSize, gridSize);
699 med->v1 = getFaceIndex(ss, f, grid, y, x, edgeSize, gridSize);
700 med->v2 = getFaceIndex(ss, f, grid, y+1, x, edgeSize, gridSize);
704 /* this vert comes from edge data */
706 int edgeSize = ccgSubSurf_getEdgeSize(ss);
709 unsigned int flags = 0;
711 i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
713 e = ccgdm->edgeMap[i].edge;
715 if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
717 x = edgeNum - ccgdm->edgeMap[i].startEdge;
719 med->v1 = getEdgeIndex(ss, e, x, edgeSize);
720 med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
722 edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL;
724 flags |= (*edgeFlag & (ME_SEAM | ME_SHARP))
725 | ME_EDGEDRAW | ME_EDGERENDER;
727 flags |= ME_EDGEDRAW | ME_EDGERENDER;
733 static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
735 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
736 CCGSubSurf *ss = ccgdm->ss;
737 int gridSize = ccgSubSurf_getGridSize(ss);
738 int edgeSize = ccgSubSurf_getEdgeSize(ss);
739 int gridSideEdges = gridSize - 1;
740 int gridFaces = gridSideEdges * gridSideEdges;
747 int lastface = ccgSubSurf_getNumFaces(ss) - 1;
748 char *faceFlags = ccgdm->faceFlags;
750 memset(mf, 0, sizeof(*mf));
753 while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace)
756 f = ccgdm->faceMap[i].face;
757 numVerts = ccgSubSurf_getFaceNumVerts(f);
759 offset = faceNum - ccgdm->faceMap[i].startFace;
760 grid = offset / gridFaces;
762 y = offset / gridSideEdges;
763 x = offset % gridSideEdges;
765 mf->v1 = getFaceIndex(ss, f, grid, x+0, y+0, edgeSize, gridSize);
766 mf->v2 = getFaceIndex(ss, f, grid, x+0, y+1, edgeSize, gridSize);
767 mf->v3 = getFaceIndex(ss, f, grid, x+1, y+1, edgeSize, gridSize);
768 mf->v4 = getFaceIndex(ss, f, grid, x+1, y+0, edgeSize, gridSize);
770 if(faceFlags) mf->flag = faceFlags[i*2];
771 else mf->flag = ME_SMOOTH;
774 static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
776 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
777 CCGSubSurf *ss = ccgdm->ss;
780 int totvert, totedge, totface;
781 int gridSize = ccgSubSurf_getGridSize(ss);
782 int edgeSize = ccgSubSurf_getEdgeSize(ss);
785 totface = ccgSubSurf_getNumFaces(ss);
786 for(index = 0; index < totface; index++) {
787 CCGFace *f = ccgdm->faceMap[index].face;
788 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
790 vd= ccgSubSurf_getFaceCenterData(f);
791 copy_v3_v3(mvert[i].co, vd->co);
792 normal_float_to_short_v3(mvert[i].no, vd->no);
795 for(S = 0; S < numVerts; S++) {
796 for(x = 1; x < gridSize - 1; x++, i++) {
797 vd= ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
798 copy_v3_v3(mvert[i].co, vd->co);
799 normal_float_to_short_v3(mvert[i].no, vd->no);
803 for(S = 0; S < numVerts; S++) {
804 for(y = 1; y < gridSize - 1; y++) {
805 for(x = 1; x < gridSize - 1; x++, i++) {
806 vd= ccgSubSurf_getFaceGridData(ss, f, S, x, y);
807 copy_v3_v3(mvert[i].co, vd->co);
808 normal_float_to_short_v3(mvert[i].no, vd->no);
814 totedge = ccgSubSurf_getNumEdges(ss);
815 for(index = 0; index < totedge; index++) {
816 CCGEdge *e = ccgdm->edgeMap[index].edge;
819 for(x = 1; x < edgeSize - 1; x++, i++) {
820 vd= ccgSubSurf_getEdgeData(ss, e, x);
821 copy_v3_v3(mvert[i].co, vd->co);
822 /* TODO CCGSubsurf does not set these */
823 normal_float_to_short_v3(mvert[i].no, vd->no);
827 totvert = ccgSubSurf_getNumVerts(ss);
828 for(index = 0; index < totvert; index++) {
829 CCGVert *v = ccgdm->vertMap[index].vert;
831 vd= ccgSubSurf_getVertData(ss, v);
832 copy_v3_v3(mvert[i].co, vd->co);
833 normal_float_to_short_v3(mvert[i].no, vd->no);
838 static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
840 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
841 CCGSubSurf *ss = ccgdm->ss;
843 int totedge, totface;
844 int gridSize = ccgSubSurf_getGridSize(ss);
845 int edgeSize = ccgSubSurf_getEdgeSize(ss);
847 short *edgeFlags = ccgdm->edgeFlags;
849 totface = ccgSubSurf_getNumFaces(ss);
850 for(index = 0; index < totface; index++) {
851 CCGFace *f = ccgdm->faceMap[index].face;
852 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
854 for(S = 0; S < numVerts; S++) {
855 for(x = 0; x < gridSize - 1; x++) {
856 MEdge *med = &medge[i];
858 if(ccgdm->drawInteriorEdges)
859 med->flag = ME_EDGEDRAW | ME_EDGERENDER;
860 med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
861 med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
865 for(x = 1; x < gridSize - 1; x++) {
866 for(y = 0; y < gridSize - 1; y++) {
870 if(ccgdm->drawInteriorEdges)
871 med->flag = ME_EDGEDRAW | ME_EDGERENDER;
872 med->v1 = getFaceIndex(ss, f, S, x, y,
874 med->v2 = getFaceIndex(ss, f, S, x, y + 1,
879 if(ccgdm->drawInteriorEdges)
880 med->flag = ME_EDGEDRAW | ME_EDGERENDER;
881 med->v1 = getFaceIndex(ss, f, S, y, x,
883 med->v2 = getFaceIndex(ss, f, S, y + 1, x,
891 totedge = ccgSubSurf_getNumEdges(ss);
892 for(index = 0; index < totedge; index++) {
893 CCGEdge *e = ccgdm->edgeMap[index].edge;
894 unsigned int flags = 0;
896 int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
898 if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
902 flags |= (edgeFlags[index] & (ME_SEAM | ME_SHARP))
903 | ME_EDGEDRAW | ME_EDGERENDER;
906 flags |= ME_EDGEDRAW | ME_EDGERENDER;
909 for(x = 0; x < edgeSize - 1; x++) {
910 MEdge *med = &medge[i];
911 med->v1 = getEdgeIndex(ss, e, x, edgeSize);
912 med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
919 static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
921 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
922 CCGSubSurf *ss = ccgdm->ss;
925 int gridSize = ccgSubSurf_getGridSize(ss);
926 int edgeSize = ccgSubSurf_getEdgeSize(ss);
928 char *faceFlags = ccgdm->faceFlags;
930 totface = ccgSubSurf_getNumFaces(ss);
931 for(index = 0; index < totface; index++) {
932 CCGFace *f = ccgdm->faceMap[index].face;
933 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
935 int flag = ME_SMOOTH; /* assume face is smooth by default */
937 for(S = 0; S < numVerts; S++) {
938 for(y = 0; y < gridSize - 1; y++) {
939 for(x = 0; x < gridSize - 1; x++) {
940 MFace *mf = &mface[i];
941 mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
943 mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
945 mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
947 mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
950 if(faceFlags) mf->flag = faceFlags[index*2];
951 else mf->flag = flag;
960 static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
961 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
962 CCGSubSurf *ss = ccgdm->ss;
963 int edgeSize = ccgSubSurf_getEdgeSize(ss);
964 int gridSize = ccgSubSurf_getGridSize(ss);
972 int index, totvert, totedge, totface;
974 totvert = ccgSubSurf_getNumVerts(ss);
975 vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap");
976 vi = ccgSubSurf_getVertIterator(ss);
977 for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
978 CCGVert *v = ccgVertIterator_getCurrent(vi);
980 vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
982 ccgVertIterator_free(vi);
984 totedge = ccgSubSurf_getNumEdges(ss);
985 edgeMap2 = MEM_mallocN(totedge*sizeof(*edgeMap2), "edgemap");
986 ei = ccgSubSurf_getEdgeIterator(ss);
987 for (i=0; !ccgEdgeIterator_isStopped(ei); i++,ccgEdgeIterator_next(ei)) {
988 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
990 edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
993 totface = ccgSubSurf_getNumFaces(ss);
994 faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap");
995 fi = ccgSubSurf_getFaceIterator(ss);
996 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
997 CCGFace *f = ccgFaceIterator_getCurrent(fi);
999 faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f;
1001 ccgFaceIterator_free(fi);
1004 for (index=0; index<totface; index++) {
1005 CCGFace *f = faceMap2[index];
1006 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
1008 copy_v3_v3(cos[i++], ccgSubSurf_getFaceCenterData(f));
1010 for (S=0; S<numVerts; S++) {
1011 for (x=1; x<gridSize-1; x++) {
1012 copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
1016 for (S=0; S<numVerts; S++) {
1017 for (y=1; y<gridSize-1; y++) {
1018 for (x=1; x<gridSize-1; x++) {
1019 copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
1025 for (index=0; index<totedge; index++) {
1026 CCGEdge *e= edgeMap2[index];
1029 for (x=1; x<edgeSize-1; x++) {
1030 copy_v3_v3(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
1034 for (index=0; index<totvert; index++) {
1035 CCGVert *v = vertMap2[index];
1036 copy_v3_v3(cos[i++], ccgSubSurf_getVertData(ss, v));
1039 MEM_freeN(vertMap2);
1040 MEM_freeN(edgeMap2);
1041 MEM_freeN(faceMap2);
1043 static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
1044 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1045 CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss);
1047 for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
1048 CCGVert *v = ccgVertIterator_getCurrent(vi);
1049 DMGridData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
1050 int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
1053 func(userData, index, vd->co, vd->no, NULL);
1056 ccgVertIterator_free(vi);
1058 static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
1059 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1060 CCGSubSurf *ss = ccgdm->ss;
1061 CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
1062 int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
1064 for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1065 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1066 DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
1067 int index = ccgDM_getEdgeMapIndex(ss, e);
1070 for (i=0; i<edgeSize-1; i++)
1071 func(userData, index, edgeData[i].co, edgeData[i+1].co);
1075 ccgEdgeIterator_free(ei);
1078 static void ccgDM_drawVerts(DerivedMesh *dm) {
1079 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1080 CCGSubSurf *ss = ccgdm->ss;
1081 int edgeSize = ccgSubSurf_getEdgeSize(ss);
1082 int gridSize = ccgSubSurf_getGridSize(ss);
1083 CCGVertIterator *vi;
1084 CCGEdgeIterator *ei;
1085 CCGFaceIterator *fi;
1088 vi = ccgSubSurf_getVertIterator(ss);
1089 for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
1090 CCGVert *v = ccgVertIterator_getCurrent(vi);
1091 glVertex3fv(ccgSubSurf_getVertData(ss, v));
1093 ccgVertIterator_free(vi);
1095 ei = ccgSubSurf_getEdgeIterator(ss);
1096 for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1097 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1100 for (x=1; x<edgeSize-1; x++)
1101 glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
1103 ccgEdgeIterator_free(ei);
1105 fi = ccgSubSurf_getFaceIterator(ss);
1106 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1107 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1108 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
1110 glVertex3fv(ccgSubSurf_getFaceCenterData(f));
1111 for (S=0; S<numVerts; S++)
1112 for (x=1; x<gridSize-1; x++)
1113 glVertex3fv(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
1114 for (S=0; S<numVerts; S++)
1115 for (y=1; y<gridSize-1; y++)
1116 for (x=1; x<gridSize-1; x++)
1117 glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
1119 ccgFaceIterator_free(fi);
1122 static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
1123 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1124 CCGSubSurf *ss = ccgdm->ss;
1125 CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
1126 CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1127 int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
1128 int gridSize = ccgSubSurf_getGridSize(ss);
1131 ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
1133 for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1134 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1135 DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
1137 if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(e))
1140 if (useAging && !(G.f&G_BACKBUFSEL)) {
1141 int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
1142 glColor3ub(0, ageCol>0?ageCol:0, 0);
1145 glBegin(GL_LINE_STRIP);
1146 for (i=0; i<edgeSize-1; i++) {
1147 glVertex3fv(edgeData[i].co);
1148 glVertex3fv(edgeData[i+1].co);
1153 if (useAging && !(G.f&G_BACKBUFSEL)) {
1154 glColor3ub(0, 0, 0);
1157 if (ccgdm->drawInteriorEdges) {
1158 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1159 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1160 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
1162 for (S=0; S<numVerts; S++) {
1163 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1165 glBegin(GL_LINE_STRIP);
1166 for (x=0; x<gridSize; x++)
1167 glVertex3fv(faceGridData[x].co);
1169 for (y=1; y<gridSize-1; y++) {
1170 glBegin(GL_LINE_STRIP);
1171 for (x=0; x<gridSize; x++)
1172 glVertex3fv(faceGridData[y*gridSize + x].co);
1175 for (x=1; x<gridSize-1; x++) {
1176 glBegin(GL_LINE_STRIP);
1177 for (y=0; y<gridSize; y++)
1178 glVertex3fv(faceGridData[y*gridSize + x].co);
1185 ccgFaceIterator_free(fi);
1186 ccgEdgeIterator_free(ei);
1188 static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
1189 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1190 CCGSubSurf *ss = ccgdm->ss;
1191 CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
1192 int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
1194 for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1195 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1196 DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
1198 if (!ccgSubSurf_getEdgeNumFaces(e)) {
1199 glBegin(GL_LINE_STRIP);
1200 for (i=0; i<edgeSize-1; i++) {
1201 glVertex3fv(edgeData[i].co);
1202 glVertex3fv(edgeData[i+1].co);
1208 ccgEdgeIterator_free(ei);
1211 static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
1213 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
1214 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
1217 no[0] = b_dY*a_cZ - b_dZ*a_cY;
1218 no[1] = b_dZ*a_cX - b_dX*a_cZ;
1219 no[2] = b_dX*a_cY - b_dY*a_cX;
1221 /* don't normalize, GL_NORMALIZE is be enabled */
1225 /* Only used by non-editmesh types */
1226 static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int fast, int (*setMaterial)(int, void *attribs)) {
1227 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1228 CCGSubSurf *ss = ccgdm->ss;
1229 CCGFaceIterator *fi;
1230 int gridSize = ccgSubSurf_getGridSize(ss);
1231 char *faceFlags = ccgdm->faceFlags;
1232 int step = (fast)? gridSize-1: 1;
1234 if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
1238 BLI_pbvh_get_grid_updates(ccgdm->pbvh, (void***)&faces, &totface);
1240 ccgSubSurf_updateFromFaces(ss, 0, faces, totface);
1241 ccgSubSurf_updateNormals(ss, faces, totface);
1245 /* should be per face */
1246 if(faceFlags && faceFlags[0] & ME_SMOOTH)
1247 glShadeModel(GL_SMOOTH);
1249 BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL);
1251 glShadeModel(GL_FLAT);
1256 fi = ccgSubSurf_getFaceIterator(ss);
1257 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1258 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1259 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
1260 int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
1261 int drawSmooth, mat_nr;
1264 drawSmooth = (faceFlags[index*2] & ME_SMOOTH);
1265 mat_nr= faceFlags[index*2 + 1];
1272 if (!setMaterial(mat_nr+1, NULL))
1275 glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
1276 for (S=0; S<numVerts; S++) {
1277 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1280 for (y=0; y<gridSize-1; y+=step) {
1281 glBegin(GL_QUAD_STRIP);
1282 for (x=0; x<gridSize; x+=step) {
1283 DMGridData *a = &faceGridData[(y+0)*gridSize + x];
1284 DMGridData *b = &faceGridData[(y+step)*gridSize + x];
1295 for (y=0; y<gridSize-1; y+=step) {
1296 for (x=0; x<gridSize-1; x+=step) {
1297 float *a = faceGridData[(y+0)*gridSize + x].co;
1298 float *b = faceGridData[(y+0)*gridSize + x + step].co;
1299 float *c = faceGridData[(y+step)*gridSize + x + step].co;
1300 float *d = faceGridData[(y+step)*gridSize + x].co;
1302 ccgDM_glNormalFast(a, b, c, d);
1315 ccgFaceIterator_free(fi);
1318 /* Only used by non-editmesh types */
1319 static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
1320 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1321 CCGSubSurf *ss = ccgdm->ss;
1322 CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1323 GPUVertexAttribs gattribs;
1324 DMVertexAttribs attribs;
1325 MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
1326 int gridSize = ccgSubSurf_getGridSize(ss);
1327 int gridFaces = gridSize - 1;
1328 int edgeSize = ccgSubSurf_getEdgeSize(ss);
1329 int transp, orig_transp, new_transp;
1330 char *faceFlags = ccgdm->faceFlags;
1331 int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
1336 transp = GPU_get_material_blend_mode();
1337 orig_transp = transp;
1339 memset(&attribs, 0, sizeof(attribs));
1341 #define PASSATTRIB(dx, dy, vert) { \
1342 if(attribs.totorco) { \
1343 index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \
1344 glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
1346 for(b = 0; b < attribs.tottface; b++) { \
1347 MTFace *tf = &attribs.tface[b].array[a]; \
1348 glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
1350 for(b = 0; b < attribs.totmcol; b++) { \
1351 MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
1353 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
1354 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
1356 if(attribs.tottang) { \
1357 float *tang = attribs.tang.array[a*4 + vert]; \
1358 glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
1362 totface = ccgSubSurf_getNumFaces(ss);
1363 for(a = 0, i = 0; i < totface; i++) {
1364 CCGFace *f = ccgdm->faceMap[i].face;
1365 int S, x, y, drawSmooth;
1366 int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
1367 int origIndex = ccgDM_getFaceMapIndex(ss, f);
1369 numVerts = ccgSubSurf_getFaceNumVerts(f);
1372 drawSmooth = (faceFlags[index*2] & ME_SMOOTH);
1373 new_matnr= faceFlags[index*2 + 1] + 1;
1380 if(new_matnr != matnr) {
1381 doDraw = setMaterial(matnr = new_matnr, &gattribs);
1383 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1386 if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) {
1387 a += gridFaces*gridFaces*numVerts;
1392 new_transp = tf[i].transp;
1394 if(new_transp != transp) {
1395 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1396 GPU_set_material_blend_mode(orig_transp);
1398 GPU_set_material_blend_mode(new_transp);
1399 transp = new_transp;
1403 glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
1404 for (S=0; S<numVerts; S++) {
1405 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1406 DMGridData *vda, *vdb;
1409 for (y=0; y<gridFaces; y++) {
1410 glBegin(GL_QUAD_STRIP);
1411 for (x=0; x<gridFaces; x++) {
1412 vda = &faceGridData[(y+0)*gridSize + x];
1413 vdb = &faceGridData[(y+1)*gridSize + x];
1415 PASSATTRIB(0, 0, 0);
1416 glNormal3fv(vda->no);
1417 glVertex3fv(vda->co);
1419 PASSATTRIB(0, 1, 1);
1420 glNormal3fv(vdb->no);
1421 glVertex3fv(vdb->co);
1423 if(x != gridFaces-1)
1427 vda = &faceGridData[(y+0)*gridSize + x];
1428 vdb = &faceGridData[(y+1)*gridSize + x];
1430 PASSATTRIB(0, 0, 3);
1431 glNormal3fv(vda->no);
1432 glVertex3fv(vda->co);
1434 PASSATTRIB(0, 1, 2);
1435 glNormal3fv(vdb->no);
1436 glVertex3fv(vdb->co);
1444 for (y=0; y<gridFaces; y++) {
1445 for (x=0; x<gridFaces; x++) {
1446 float *aco = faceGridData[(y+0)*gridSize + x].co;
1447 float *bco = faceGridData[(y+0)*gridSize + x + 1].co;
1448 float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
1449 float *dco = faceGridData[(y+1)*gridSize + x].co;
1451 ccgDM_glNormalFast(aco, bco, cco, dco);
1453 PASSATTRIB(0, 1, 1);
1455 PASSATTRIB(1, 1, 2);
1457 PASSATTRIB(1, 0, 3);
1459 PASSATTRIB(0, 0, 0);
1472 ccgFaceIterator_free(fi);
1475 static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
1476 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1479 static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
1480 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1481 CCGSubSurf *ss = ccgdm->ss;
1482 CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1483 int gridSize = ccgSubSurf_getGridSize(ss);
1484 unsigned char *cp1, *cp2;
1495 glShadeModel(GL_SMOOTH);
1497 glEnable(GL_CULL_FACE);
1500 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1501 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1502 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
1504 for (S=0; S<numVerts; S++) {
1505 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1506 for (y=0; y<gridSize-1; y++) {
1507 for (x=0; x<gridSize-1; x++) {
1508 float *a = faceGridData[(y+0)*gridSize + x].co;
1509 float *b = faceGridData[(y+0)*gridSize + x + 1].co;
1510 float *c = faceGridData[(y+1)*gridSize + x + 1].co;
1511 float *d = faceGridData[(y+1)*gridSize + x].co;
1513 glColor3ub(cp1[3], cp1[2], cp1[1]);
1515 glColor3ub(cp1[7], cp1[6], cp1[5]);
1517 glColor3ub(cp1[11], cp1[10], cp1[9]);
1519 glColor3ub(cp1[15], cp1[14], cp1[13]);
1523 glColor3ub(cp2[15], cp2[14], cp2[13]);
1525 glColor3ub(cp2[11], cp2[10], cp2[9]);
1527 glColor3ub(cp2[7], cp2[6], cp2[5]);
1529 glColor3ub(cp2[3], cp2[2], cp2[1]);
1541 ccgFaceIterator_free(fi);
1544 static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
1545 int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
1546 int (*drawParamsMapped)(void *userData, int index),
1549 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1550 CCGSubSurf *ss = ccgdm->ss;
1551 MCol *mcol = DM_get_face_data_layer(dm, CD_MCOL);
1552 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
1553 char *faceFlags = ccgdm->faceFlags;
1554 int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss);
1555 int gridFaces = gridSize - 1;
1557 totface = ccgSubSurf_getNumFaces(ss);
1558 for(i = 0; i < totface; i++) {
1559 CCGFace *f = ccgdm->faceMap[i].face;
1560 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
1561 int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
1562 int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
1563 unsigned char *cp= NULL;
1567 drawSmooth = (faceFlags[origIndex*2] & ME_SMOOTH);
1568 mat_nr= faceFlags[origIndex*2 + 1];
1576 flag = drawParams(tf, mcol, mat_nr);
1578 flag= (drawParamsMapped)? drawParamsMapped(userData, index): 1;
1580 if (flag == 0) { /* flag 0 == the face is hidden or invisible */
1581 if(tf) tf += gridFaces*gridFaces*numVerts;
1582 if(mcol) mcol += gridFaces*gridFaces*numVerts*4;
1586 /* flag 1 == use vertex colors */
1588 if(flag==1) cp= (unsigned char*)mcol;
1589 mcol += gridFaces*gridFaces*numVerts*4;
1592 for (S=0; S<numVerts; S++) {
1593 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1597 glShadeModel(GL_SMOOTH);
1598 for (y=0; y<gridFaces; y++) {
1599 glBegin(GL_QUAD_STRIP);
1600 for (x=0; x<gridFaces; x++) {
1601 a = &faceGridData[(y+0)*gridSize + x];
1602 b = &faceGridData[(y+1)*gridSize + x];
1604 if(tf) glTexCoord2fv(tf->uv[0]);
1605 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
1609 if(tf) glTexCoord2fv(tf->uv[1]);
1610 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
1614 if(x != gridFaces-1) {
1620 a = &faceGridData[(y+0)*gridSize + x];
1621 b = &faceGridData[(y+1)*gridSize + x];
1623 if(tf) glTexCoord2fv(tf->uv[3]);
1624 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
1628 if(tf) glTexCoord2fv(tf->uv[2]);
1629 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
1639 glShadeModel(GL_FLAT);
1641 for (y=0; y<gridFaces; y++) {
1642 for (x=0; x<gridFaces; x++) {
1643 float *a_co = faceGridData[(y+0)*gridSize + x].co;
1644 float *b_co = faceGridData[(y+0)*gridSize + x + 1].co;
1645 float *c_co = faceGridData[(y+1)*gridSize + x + 1].co;
1646 float *d_co = faceGridData[(y+1)*gridSize + x].co;
1648 ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
1650 if(tf) glTexCoord2fv(tf->uv[1]);
1651 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
1654 if(tf) glTexCoord2fv(tf->uv[2]);
1655 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
1658 if(tf) glTexCoord2fv(tf->uv[3]);
1659 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
1662 if(tf) glTexCoord2fv(tf->uv[0]);
1663 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
1676 static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
1678 ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
1681 static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1683 ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
1686 static void ccgDM_drawUVEdges(DerivedMesh *dm)
1689 MFace *mf = dm->getFaceArray(dm);
1690 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
1695 for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
1696 if(!(mf->flag&ME_HIDE)) {
1697 glVertex2fv(tf->uv[0]);
1698 glVertex2fv(tf->uv[1]);
1700 glVertex2fv(tf->uv[1]);
1701 glVertex2fv(tf->uv[2]);
1704 glVertex2fv(tf->uv[2]);
1705 glVertex2fv(tf->uv[0]);
1707 glVertex2fv(tf->uv[2]);
1708 glVertex2fv(tf->uv[3]);
1710 glVertex2fv(tf->uv[3]);
1711 glVertex2fv(tf->uv[0]);
1719 static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) {
1720 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1721 CCGSubSurf *ss = ccgdm->ss;
1722 CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1723 int i, gridSize = ccgSubSurf_getGridSize(ss);
1724 char *faceFlags = ccgdm->faceFlags;
1726 for (i=0; !ccgFaceIterator_isStopped(fi); i++,ccgFaceIterator_next(fi)) {
1727 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1728 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
1729 int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
1732 origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
1734 if(faceFlags) drawSmooth = (faceFlags[origIndex*2] & ME_SMOOTH);
1735 else drawSmooth = 1;
1739 draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, index, &drawSmooth);
1743 glEnable(GL_POLYGON_STIPPLE);
1744 glPolygonStipple(stipple_quarttone);
1747 for (S=0; S<numVerts; S++) {
1748 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1750 glShadeModel(GL_SMOOTH);
1751 for (y=0; y<gridSize-1; y++) {
1752 glBegin(GL_QUAD_STRIP);
1753 for (x=0; x<gridSize; x++) {
1754 DMGridData *a = &faceGridData[(y+0)*gridSize + x];
1755 DMGridData *b = &faceGridData[(y+1)*gridSize + x];
1765 glShadeModel(GL_FLAT);
1767 for (y=0; y<gridSize-1; y++) {
1768 for (x=0; x<gridSize-1; x++) {
1769 float *a = faceGridData[(y+0)*gridSize + x].co;
1770 float *b = faceGridData[(y+0)*gridSize + x + 1].co;
1771 float *c = faceGridData[(y+1)*gridSize + x + 1].co;
1772 float *d = faceGridData[(y+1)*gridSize + x].co;
1773 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
1774 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
1777 no[0] = b_dY*a_cZ - b_dZ*a_cY;
1778 no[1] = b_dZ*a_cX - b_dX*a_cZ;
1779 no[2] = b_dX*a_cY - b_dY*a_cX;
1792 glDisable(GL_POLYGON_STIPPLE);
1797 ccgFaceIterator_free(fi);
1799 static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
1800 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1801 CCGSubSurf *ss = ccgdm->ss;
1802 CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
1803 int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
1805 ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
1807 for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1808 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1809 DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
1810 int index = ccgDM_getEdgeMapIndex(ss, e);
1812 glBegin(GL_LINE_STRIP);
1813 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
1814 if (useAging && !(G.f&G_BACKBUFSEL)) {
1815 int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
1816 glColor3ub(0, ageCol>0?ageCol:0, 0);
1819 for (i=0; i<edgeSize-1; i++) {
1820 glVertex3fv(edgeData[i].co);
1821 glVertex3fv(edgeData[i+1].co);
1827 ccgEdgeIterator_free(ei);
1829 static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
1830 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1831 CCGSubSurf *ss = ccgdm->ss;
1832 CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
1833 int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
1835 ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
1837 for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1838 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1839 DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
1840 int index = ccgDM_getEdgeMapIndex(ss, e);
1842 glBegin(GL_LINE_STRIP);
1843 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
1844 for (i=0; i<edgeSize; i++) {
1845 setDrawInterpOptions(userData, index, (float) i/(edgeSize-1));
1847 if (useAging && !(G.f&G_BACKBUFSEL)) {
1848 int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
1849 glColor3ub(0, ageCol>0?ageCol:0, 0);
1852 glVertex3fv(edgeData[i].co);
1858 ccgEdgeIterator_free(ei);
1860 static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
1861 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1862 CCGSubSurf *ss = ccgdm->ss;
1863 CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1865 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1866 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1867 int index = ccgDM_getFaceMapIndex(ss, f);
1870 /* Face center data normal isn't updated atm. */
1871 DMGridData *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
1873 func(userData, index, vd->co, vd->no);
1877 ccgFaceIterator_free(fi);
1880 static void ccgDM_release(DerivedMesh *dm) {
1881 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1883 if (DM_release(dm)) {
1884 /* Before freeing, need to update the displacement map */
1885 if(ccgdm->multires.modified) {
1886 /* Check that mmd still exists */
1887 if(!ccgdm->multires.local_mmd && BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0)
1888 ccgdm->multires.mmd = NULL;
1889 if(ccgdm->multires.mmd)
1890 ccgdm->multires.update(dm);
1893 if(ccgdm->pbvh) BLI_pbvh_free(ccgdm->pbvh);
1894 if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
1895 if(ccgdm->gridData) MEM_freeN(ccgdm->gridData);
1896 if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency);
1897 if(ccgdm->freeSS) ccgSubSurf_free(ccgdm->ss);
1898 MEM_freeN(ccgdm->edgeFlags);
1899 MEM_freeN(ccgdm->faceFlags);
1900 MEM_freeN(ccgdm->vertMap);
1901 MEM_freeN(ccgdm->edgeMap);
1902 MEM_freeN(ccgdm->faceMap);
1907 static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
1909 if(type == CD_ORIGINDEX) {
1910 /* create origindex on demand to save memory */
1911 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
1912 CCGSubSurf *ss= ccgdm->ss;
1914 int a, index, totnone, totorig;
1916 DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
1917 origindex= DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1919 totorig = ccgSubSurf_getNumVerts(ss);
1920 totnone= dm->numVertData - totorig;
1922 /* original vertices are at the end */
1923 for(a=0; a<totnone; a++)
1924 origindex[a]= ORIGINDEX_NONE;
1926 for(index=0; index<totorig; index++, a++) {
1927 CCGVert *v = ccgdm->vertMap[index].vert;
1928 origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
1934 return DM_get_vert_data_layer(dm, type);
1937 static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
1939 if(type == CD_ORIGINDEX) {
1940 /* create origindex on demand to save memory */
1941 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
1942 CCGSubSurf *ss= ccgdm->ss;
1944 int a, i, index, totnone, totorig, totedge;
1945 int edgeSize= ccgSubSurf_getEdgeSize(ss);
1947 DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
1948 origindex= DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1950 totedge= ccgSubSurf_getNumEdges(ss);
1951 totorig= totedge*(edgeSize - 1);
1952 totnone= dm->numEdgeData - totorig;
1954 /* original edges are at the end */
1955 for(a=0; a<totnone; a++)
1956 origindex[a]= ORIGINDEX_NONE;
1958 for(index=0; index<totedge; index++) {
1959 CCGEdge *e= ccgdm->edgeMap[index].edge;
1960 int mapIndex= ccgDM_getEdgeMapIndex(ss, e);
1962 for(i = 0; i < edgeSize - 1; i++, a++)
1963 origindex[a]= mapIndex;
1969 return DM_get_edge_data_layer(dm, type);
1972 static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type)
1974 if(type == CD_ORIGINDEX) {
1975 /* create origindex on demand to save memory */
1976 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
1977 CCGSubSurf *ss= ccgdm->ss;
1979 int a, i, index, totface;
1980 int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
1982 DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
1983 origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX);
1985 totface= ccgSubSurf_getNumFaces(ss);
1987 for(a=0, index=0; index<totface; index++) {
1988 CCGFace *f = ccgdm->faceMap[index].face;
1989 int numVerts = ccgSubSurf_getFaceNumVerts(f);
1990 int mapIndex = ccgDM_getFaceMapIndex(ss, f);
1992 for(i=0; i<gridFaces*gridFaces*numVerts; i++, a++)
1993 origindex[a]= mapIndex;
1999 return DM_get_face_data_layer(dm, type);
2002 static int ccgDM_getNumGrids(DerivedMesh *dm)
2004 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
2005 int index, numFaces, numGrids;
2007 numFaces= ccgSubSurf_getNumFaces(ccgdm->ss);
2010 for(index=0; index<numFaces; index++) {
2011 CCGFace *f = ccgdm->faceMap[index].face;
2012 numGrids += ccgSubSurf_getFaceNumVerts(f);
2018 static int ccgDM_getGridSize(DerivedMesh *dm)
2020 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
2021 return ccgSubSurf_getGridSize(ccgdm->ss);
2024 static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
2028 int i, j= 0, numFaces, fIndex, numEdges= 0;
2030 e = ccgSubSurf_getFaceEdge(ss, f, S);
2031 numFaces = ccgSubSurf_getEdgeNumFaces(e);
2036 for(i = 0; i < numFaces; i++) {
2037 adjf = ccgSubSurf_getEdgeFace(e, i);
2040 numEdges = ccgSubSurf_getFaceNumVerts(adjf);
2041 for(j = 0; j < numEdges; j++)
2042 if(ccgSubSurf_getFaceEdge(ss, adjf, j) == e)
2050 fIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, adjf));
2052 return gridOffset[fIndex] + (j + offset)%numEdges;
2055 static void ccgdm_create_grids(DerivedMesh *dm)
2057 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
2058 CCGSubSurf *ss= ccgdm->ss;
2059 DMGridData **gridData;
2060 DMGridAdjacency *gridAdjacency, *adj;
2061 CCGFace **gridFaces;
2063 int index, numFaces, numGrids, S, gIndex, gridSize;
2068 numGrids = ccgDM_getNumGrids(dm);
2069 numFaces = ccgSubSurf_getNumFaces(ss);
2070 gridSize = ccgDM_getGridSize(dm);
2072 /* compute offset into grid array for each face */
2073 gridOffset = MEM_mallocN(sizeof(int)*numFaces, "ccgdm.gridOffset");
2075 for(gIndex = 0, index = 0; index < numFaces; index++) {
2076 CCGFace *f = ccgdm->faceMap[index].face;
2077 int numVerts = ccgSubSurf_getFaceNumVerts(f);
2079 gridOffset[index] = gIndex;
2083 /* compute grid data */
2084 gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "ccgdm.gridData");
2085 gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "ccgdm.gridAdjacency");
2086 gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "ccgdm.gridFaces");
2088 for(gIndex = 0, index = 0; index < numFaces; index++) {
2089 CCGFace *f = ccgdm->faceMap[index].face;
2090 int numVerts = ccgSubSurf_getFaceNumVerts(f);
2092 for(S = 0; S < numVerts; S++, gIndex++) {
2093 int prevS = (S - 1 + numVerts) % numVerts;
2094 int nextS = (S + 1 + numVerts) % numVerts;
2096 gridData[gIndex] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
2097 gridFaces[gIndex] = f;
2099 adj = &gridAdjacency[gIndex];
2101 adj->index[0] = gIndex - S + nextS;
2102 adj->rotation[0] = 3;
2103 adj->index[1] = ccgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
2104 adj->rotation[1] = 1;
2105 adj->index[2] = ccgdm_adjacent_grid(ss, gridOffset, f, S, 1);
2106 adj->rotation[2] = 3;
2107 adj->index[3] = gIndex - S + prevS;
2108 adj->rotation[3] = 1;
2112 ccgdm->gridData = gridData;
2113 ccgdm->gridFaces = gridFaces;
2114 ccgdm->gridAdjacency = gridAdjacency;
2115 MEM_freeN(gridOffset);
2118 static DMGridData **ccgDM_getGridData(DerivedMesh *dm)
2120 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
2122 ccgdm_create_grids(dm);
2123 return ccgdm->gridData;
2126 static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm)
2128 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
2130 ccgdm_create_grids(dm);
2131 return ccgdm->gridAdjacency;
2134 static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
2136 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
2137 int gridSize, numGrids;
2142 if(ccgdm->multires.mmd) {
2143 ccgdm_create_grids(dm);
2145 gridSize = ccgDM_getGridSize(dm);
2146 numGrids = ccgDM_getNumGrids(dm);
2148 ccgdm->pbvh = BLI_pbvh_new();
2149 BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, numGrids, gridSize,
2150 (void**)ccgdm->gridFaces);
2152 else if(ob->type == OB_MESH) {
2155 ccgdm->pbvh = BLI_pbvh_new();
2156 BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
2157 me->totface, me->totvert);
2163 static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
2164 int drawInteriorEdges,
2168 CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
2169 CCGVertIterator *vi;
2170 CCGEdgeIterator *ei;
2171 CCGFaceIterator *fi;
2172 int index, totvert, totedge, totface;
2174 int vertNum, edgeNum, faceNum;
2182 int gridInternalEdges;
2183 MEdge *medge = NULL;
2184 MFace *mface = NULL;
2185 FaceVertWeight *qweight, *tweight;
2187 DM_from_template(&ccgdm->dm, dm, ccgSubSurf_getNumFinalVerts(ss),
2188 ccgSubSurf_getNumFinalEdges(ss),
2189 ccgSubSurf_getNumFinalFaces(ss));
2191 ccgdm->dm.getMinMax = ccgDM_getMinMax;
2192 ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
2193 ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
2195 ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
2196 ccgdm->dm.getVert = ccgDM_getFinalVert;
2197 ccgdm->dm.getEdge = ccgDM_getFinalEdge;
2198 ccgdm->dm.getFace = ccgDM_getFinalFace;
2199 ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
2200 ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
2201 ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray;
2202 ccgdm->dm.getVertData = DM_get_vert_data;
2203 ccgdm->dm.getEdgeData = DM_get_edge_data;
2204 ccgdm->dm.getFaceData = DM_get_face_data;
2205 ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
2206 ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
2207 ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer;
2208 ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
2209 ccgdm->dm.getGridSize = ccgDM_getGridSize;
2210 ccgdm->dm.getGridData = ccgDM_getGridData;
2211 ccgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency;
2212 ccgdm->dm.getPBVH = ccgDM_getPBVH;
2214 ccgdm->dm.getVertCos = ccgdm_getVertCos;
2215 ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
2216 ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
2217 ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
2219 ccgdm->dm.drawVerts = ccgDM_drawVerts;
2220 ccgdm->dm.drawEdges = ccgDM_drawEdges;
2221 ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
2222 ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
2223 ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
2224 ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
2225 ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
2226 ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
2227 ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
2228 ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
2229 ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
2231 ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
2232 ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
2234 ccgdm->dm.release = ccgDM_release;
2237 ccgdm->drawInteriorEdges = drawInteriorEdges;
2238 ccgdm->useSubsurfUv = useSubsurfUv;
2240 totvert = ccgSubSurf_getNumVerts(ss);
2241 ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
2242 vi = ccgSubSurf_getVertIterator(ss);
2243 for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
2244 CCGVert *v = ccgVertIterator_getCurrent(vi);
2246 ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v;
2248 ccgVertIterator_free(vi);
2250 totedge = ccgSubSurf_getNumEdges(ss);
2251 ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
2252 ei = ccgSubSurf_getEdgeIterator(ss);
2253 for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
2254 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
2256 ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
2259 totface = ccgSubSurf_getNumFaces(ss);
2260 ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
2261 fi = ccgSubSurf_getFaceIterator(ss);
2262 for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
2263 CCGFace *f = ccgFaceIterator_getCurrent(fi);
2265 ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))].face = f;
2267 ccgFaceIterator_free(fi);
2269 edgeSize = ccgSubSurf_getEdgeSize(ss);
2270 gridSize = ccgSubSurf_getGridSize(ss);
2271 gridFaces = gridSize - 1;
2272 gridSideVerts = gridSize - 2;
2273 /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
2274 gridSideEdges = gridSize - 1;
2275 gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
2277 calc_ss_weights(gridFaces, &qweight, &tweight);
2283 /* mvert = dm->getVertArray(dm); - as yet unused */
2284 medge = dm->getEdgeArray(dm);
2285 mface = dm->getFaceArray(dm);
2287 faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(char)*2*totface, "faceFlags");
2289 for(index = 0; index < totface; ++index) {
2290 CCGFace *f = ccgdm->faceMap[index].face;
2291 int numVerts = ccgSubSurf_getFaceNumVerts(f);
2292 int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
2293 int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
2294 FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
2298 ccgdm->faceMap[index].startVert = vertNum;
2299 ccgdm->faceMap[index].startEdge = edgeNum;
2300 ccgdm->faceMap[index].startFace = faceNum;
2302 /* set the face base vert */
2303 *((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
2305 for(S = 0; S < numVerts; S++) {
2306 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
2308 vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
2311 DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
2315 for(S = 0; S < numVerts; S++) {
2316 int prevS = (S - 1 + numVerts) % numVerts;
2317 int nextS = (S + 1) % numVerts;
2318 int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
2319 for(x = 1; x < gridFaces; x++) {
2321 w[prevS] = weight[x][0][0];
2322 w[S] = weight[x][0][1];
2323 w[nextS] = weight[x][0][2];
2324 w[otherS] = weight[x][0][3];
2325 DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
2331 for(S = 0; S < numVerts; S++) {
2332 int prevS = (S - 1 + numVerts) % numVerts;
2333 int nextS = (S + 1) % numVerts;
2334 int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
2335 for(y = 1; y < gridFaces; y++) {
2336 for(x = 1; x < gridFaces; x++) {
2338 w[prevS] = weight[y * gridFaces + x][0][0];
2339 w[S] = weight[y * gridFaces + x][0][1];
2340 w[nextS] = weight[y * gridFaces + x][0][2];
2341 w[otherS] = weight[y * gridFaces + x][0][3];
2342 DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
2349 for(S = 0; S < numVerts; S++) {
2350 int prevS = (S - 1 + numVerts) % numVerts;
2351 int nextS = (S + 1) % numVerts;
2352 int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
2354 weight = (numVerts == 4) ? qweight : tweight;
2356 for(y = 0; y < gridFaces; y++) {
2357 for(x = 0; x < gridFaces; x++) {
2361 for(j = 0; j < 4; ++j) {
2362 w[j][prevS] = (*weight)[j][0];
2363 w[j][S] = (*weight)[j][1];
2364 w[j][nextS] = (*weight)[j][2];
2365 w[j][otherS] = (*weight)[j][3];
2368 DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL,
2377 faceFlags[index*2] = mface[origIndex].flag;
2378 faceFlags[index*2 + 1] = mface[origIndex].mat_nr;
2380 edgeNum += numFinalEdges;
2384 CustomData *fdata = &ccgdm->dm.faceData;
2385 CustomData *dmfdata = &dm->faceData;
2386 int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE);
2387 int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE);
2389 for (i=0; i<numlayer && i<dmnumlayer; i++)
2390 set_subsurf_uv(ss, dm, &ccgdm->dm, i);
2393 edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags");
2395 for(index = 0; index < totedge; ++index) {
2396 CCGEdge *e = ccgdm->edgeMap[index].edge;
2397 int numFinalEdges = edgeSize - 1;
2400 int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
2403 v = ccgSubSurf_getEdgeVert0(e);
2404 vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
2405 v = ccgSubSurf_getEdgeVert1(e);
2406 vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
2408 ccgdm->edgeMap[index].startVert = vertNum;
2409 ccgdm->edgeMap[index].startEdge = edgeNum;
2411 /* set the edge base vert */
2412 *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
2414 for(x = 1; x < edgeSize - 1; x++) {
2416 w[1] = (float) x / (edgeSize - 1);
2418 DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
2422 edgeFlags[index]= medge[edgeIdx].flag;
2424 edgeNum += numFinalEdges;
2427 for(index = 0; index < totvert; ++index) {
2428 CCGVert *v = ccgdm->vertMap[index].vert;
2431 vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
2433 ccgdm->vertMap[index].startVert = vertNum;
2435 /* set the vert base vert */
2436 *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
2438 DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
2451 struct DerivedMesh *subsurf_make_derived_from_derived(
2452 struct DerivedMesh *dm,
2453 struct SubsurfModifierData *smd,
2454 int useRenderParams, float (*vertCos)[3],
2455 int isFinalCalc, int editMode)
2457 int useSimple = smd->subdivType == ME_SIMPLE_SUBSURF;
2458 int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
2459 int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
2460 int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
2461 CCGDerivedMesh *result;
2464 smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0,
2466 ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
2468 result = getCCGDerivedMesh(smd->emCache,
2471 } else if(useRenderParams) {
2472 /* Do not use cache in render mode. */
2476 levels= smd->renderLevels; // XXX get_render_subsurf_level(&scene->r, smd->renderLevels);
2480 ss = _getSubSurf(NULL, levels, 0, 1, useSimple);
2482 ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
2484 result = getCCGDerivedMesh(ss,
2485 drawInteriorEdges, useSubsurfUv, dm);
2489 int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
2490 int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
2493 /* It is quite possible there is a much better place to do this. It
2494 * depends a bit on how rigourously we expect this function to never
2495 * be called in editmode. In semi-theory we could share a single
2496 * cache, but the handles used inside and outside editmode are not
2497 * the same so we would need some way of converting them. Its probably
2498 * not worth the effort. But then why am I even writing this long
2499 * comment that no one will read? Hmmm. - zr
2502 ccgSubSurf_free(smd->emCache);
2503 smd->emCache = NULL;
2506 if(useIncremental && isFinalCalc) {
2507 smd->mCache = ss = _getSubSurf(smd->mCache, smd->levels,
2508 useAging, 0, useSimple);
2510 ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
2512 result = getCCGDerivedMesh(smd->mCache,
2516 if (smd->mCache && isFinalCalc) {
2517 ccgSubSurf_free(smd->mCache);
2521 ss = _getSubSurf(NULL, smd->levels, 0, 1, useSimple);
2522 ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
2524 result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
2533 return (DerivedMesh*)result;
2536 void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
2538 /* Finds the subsurf limit positions for the verts in a mesh
2539 * and puts them in an array of floats. Please note that the
2540 * calculated vert positions is incorrect for the verts
2541 * on the boundary of the mesh.
2543 CCGSubSurf *ss = _getSubSurf(NULL, 1, 0, 1, 0);
2544 float edge_sum[3], face_sum[3];
2545 CCGVertIterator *vi;
2546 DerivedMesh *dm = CDDM_from_mesh(me, NULL);
2548 ss_sync_from_derivedmesh(ss, dm, NULL, 0);
2550 vi = ccgSubSurf_getVertIterator(ss);
2551 for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
2552 CCGVert *v = ccgVertIterator_getCurrent(vi);
2553 int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
2554 int N = ccgSubSurf_getVertNumEdges(v);
2555 int numFaces = ccgSubSurf_getVertNumFaces(v);
2559 edge_sum[0]= edge_sum[1]= edge_sum[2]= 0.0;
2560 face_sum[0]= face_sum[1]= face_sum[2]= 0.0;
2562 for (i=0; i<N; i++) {
2563 CCGEdge *e = ccgSubSurf_getVertEdge(v, i);
2564 add_v3_v3v3(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss, e, 1));
2566 for (i=0; i<numFaces; i++) {
2567 CCGFace *f = ccgSubSurf_getVertFace(v, i);
2568 add_v3_v3v3(face_sum, face_sum, ccgSubSurf_getFaceCenterData(f));
2571 /* ad-hoc correction for boundary vertices, to at least avoid them
2572 moving completely out of place (brecht) */
2573 if(numFaces && numFaces != N)
2574 mul_v3_fl(face_sum, (float)N/(float)numFaces);
2576 co = ccgSubSurf_getVertData(ss, v);
2577 positions_r[idx][0] = (co[0]*N*N + edge_sum[0]*4 + face_sum[0])/(N*(N+5));
2578 positions_r[idx][1] = (co[1]*N*N + edge_sum[1]*4 + face_sum[1])/(N*(N+5));
2579 positions_r[idx][2] = (co[2]*N*N + edge_sum[2]*4 + face_sum[2])/(N*(N+5));
2581 ccgVertIterator_free(vi);
2583 ccgSubSurf_free(ss);