- convert mesh_modifier to return deformed verts instead of
[blender.git] / source / blender / blenkernel / intern / subsurf_ccg.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2005 Blender Foundation.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <math.h>
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_object_types.h"
42
43 #include "BKE_bad_level_calls.h"
44 #include "BKE_utildefines.h"
45 #include "BKE_global.h"
46 #include "BKE_mesh.h"
47 #include "BKE_subsurf.h"
48 #include "BKE_displist.h"
49 #include "BKE_DerivedMesh.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_editVert.h"
53 #include "BLI_arithb.h"
54 #include "BLI_linklist.h"
55 #include "BLI_memarena.h"
56
57 #include "BIF_gl.h"
58
59 #include "CCGSubSurf.h"
60
61 typedef struct _SubSurf {
62         CCGSubSurf *subSurf;
63
64         int useAging;
65         int controlType;
66 #define SUBSURF_CONTROLTYPE_MESH                1
67 #define SUBSURF_CONTROLTYPE_EDITMESH    2
68
69                 /* used by editmesh control type */
70         EditMesh *em;
71
72                 /* used by mesh control type */
73         Mesh *me;
74
75         Object *deformOb;
76 } SubSurf;
77
78 typedef struct _VertData {
79         float co[3];
80         float no[3];
81 } VertData;
82
83 ///
84
85 static void *arena_alloc(CCGAllocatorHDL a, int numBytes) {
86         return BLI_memarena_alloc(a, numBytes);
87 }
88 static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
89         void *p2 = BLI_memarena_alloc(a, newSize);
90         if (ptr) {
91                 memcpy(p2, ptr, oldSize);
92         }
93         return p2;
94 }
95 static void arena_free(CCGAllocatorHDL a, void *ptr) {
96 }
97 static void arena_release(CCGAllocatorHDL a) {
98         BLI_memarena_free(a);
99 }
100
101 static CCGSubSurf *_getSubSurf(SubSurf *ss, int subdivLevels, int useArena) {
102         CCGMeshIFC ifc;
103         CCGSubSurf *ccgSS;
104         CCGAllocatorIFC allocatorIFC, *allocatorIFCp;
105         CCGAllocatorHDL allocator;
106
107         if (ss->useAging) {
108                 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
109         } else {
110                 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 4;
111         }
112         ifc.vertDataSize = sizeof(VertData);
113
114         if (useArena) {
115                 allocatorIFC.alloc = arena_alloc;
116                 allocatorIFC.realloc = arena_realloc;
117                 allocatorIFC.free = arena_free;
118                 allocatorIFC.release = arena_release;
119                 allocatorIFCp = &allocatorIFC;
120                 allocator = BLI_memarena_new((1<<16));
121
122                 ccgSS = ccgSubSurf_new(&ifc, ss, subdivLevels, allocatorIFCp, allocator);
123         } else {
124                 ccgSS = ccgSubSurf_new(&ifc, ss, subdivLevels, NULL, NULL);
125         }
126
127         if (ss->useAging) {
128                 ccgSubSurf_setUseAgeCounts(ccgSS, 1, 4, 4, 4);
129         }
130
131         ccgSubSurf_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(VertData, no));
132
133         return ccgSS;
134 }
135
136 static SubSurf *subSurf_fromEditmesh(EditMesh *em, int subdivLevels, int useAging, int useArena) {
137         SubSurf *ss = MEM_mallocN(sizeof(*ss), "ss_em");
138
139         ss->useAging = useAging;
140         ss->controlType = SUBSURF_CONTROLTYPE_EDITMESH;
141         ss->subSurf = _getSubSurf(ss, subdivLevels, useArena);
142         ss->em = em;
143
144         return ss;
145 }
146
147 static SubSurf *subSurf_fromMesh(Mesh *me, int useFlatSubdiv, int subdivLevels, Object *deformOb) {
148         SubSurf *ss = MEM_mallocN(sizeof(*ss), "ss_m");
149
150         ss->controlType = SUBSURF_CONTROLTYPE_MESH;
151         ss->useAging=0;
152         ss->subSurf = _getSubSurf(ss, subdivLevels, 1);
153         ss->me = me;
154         ss->deformOb = deformOb;
155
156         ccgSubSurf_setAllowEdgeCreation(ss->subSurf, 1, useFlatSubdiv?subdivLevels:0.0f);
157
158         return ss;
159 }
160
161 static void subSurf_free(SubSurf *ss) {
162         ccgSubSurf_free(ss->subSurf);
163         MEM_freeN(ss);
164 }
165
166 static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
167         CCGVert *v0 = ccgSubSurf_getEdgeVert0(ss, e);
168         CCGVert *v1 = ccgSubSurf_getEdgeVert1(ss, e);
169         int v0idx = *((int*) ccgSubSurf_getVertUserData(ss, v0));
170         int v1idx = *((int*) ccgSubSurf_getVertUserData(ss, v1));
171         int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
172
173         if (x==0) {
174                 return v0idx;
175         } else if (x==edgeSize-1) {
176                 return v1idx;
177         } else {
178                 return edgeBase + x-1;
179         }
180 }
181 static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
182         int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
183         int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
184
185         if (x==gridSize-1 && y==gridSize-1) {
186                 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
187                 return *((int*) ccgSubSurf_getVertUserData(ss, v));
188         } else if (x==gridSize-1) {
189                 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
190                 CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
191                 int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
192                 if (v==ccgSubSurf_getEdgeVert0(ss, e)) {
193                         return edgeBase + (gridSize-1-y)-1;
194                 } else {
195                         return edgeBase + (edgeSize-2-1)-((gridSize-1-y)-1);
196                 }
197         } else if (y==gridSize-1) {
198                 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
199                 CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
200                 int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
201                 if (v==ccgSubSurf_getEdgeVert0(ss, e)) {
202                         return edgeBase + (gridSize-1-x)-1;
203                 } else {
204                         return edgeBase + (edgeSize-2-1)-((gridSize-1-x)-1);
205                 }
206         } else if (x==0 && y==0) {
207                 return faceBase;
208         } else if (x==0) {
209                 S = (S+numVerts-1)%numVerts;
210                 return faceBase + 1 + (gridSize-2)*S + (y-1);
211         } else if (y==0) {
212                 return faceBase + 1 + (gridSize-2)*S + (x-1);
213         } else {
214                 return faceBase + 1 + (gridSize-2)*numVerts + S*(gridSize-2)*(gridSize-2) + (y-1)*(gridSize-2) + (x-1);
215         }
216 }
217 static DispListMesh *subSurf_createDispListMesh(SubSurf *ssm) {
218         CCGSubSurf *ss = ssm->subSurf;
219         DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
220         int edgeSize = ccgSubSurf_getEdgeSize(ss);
221         int gridSize = ccgSubSurf_getGridSize(ss);
222         int edgeIndexBase, edgeBase, faceIndexBase, faceBase;
223         int i, j, k, S, x, y;
224         int vertBase = 0;
225         MFace *mf;
226         CCGVertIterator *vi;
227         CCGEdgeIterator *ei;
228         CCGFaceIterator *fi;
229         
230         dlm->totvert = ccgSubSurf_getNumFinalVerts(ss);
231         dlm->totedge = ccgSubSurf_getNumFinalEdges(ss);
232         dlm->totface = ccgSubSurf_getNumFinalFaces(ss);
233
234         dlm->mvert = MEM_callocN(dlm->totvert*sizeof(*dlm->mvert), "dlm->mvert");
235         dlm->medge = MEM_callocN(dlm->totedge*sizeof(*dlm->medge), "dlm->medge");
236         dlm->mface = MEM_callocN(dlm->totface*sizeof(*dlm->mface), "dlm->mface");
237         if ((ssm->controlType==SUBSURF_CONTROLTYPE_MESH) && ssm->me->tface) {
238                 dlm->tface = MEM_callocN(dlm->totface*sizeof(*dlm->tface), "dlm->tface");
239                 dlm->mcol = NULL;
240         } else if ((ssm->controlType==SUBSURF_CONTROLTYPE_MESH) && ssm->me->mcol) {
241                 dlm->tface = NULL;
242                 dlm->mcol = MEM_mallocN(dlm->totface*4*sizeof(*dlm->mcol), "dlm->mcol");
243         } else {
244                 dlm->tface = NULL;
245                 dlm->mcol = NULL;
246         }
247
248                 // load vertices
249
250         vertBase = i = 0;
251         vi = ccgSubSurf_getVertIterator(ss);
252         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
253                 CCGVert *v = ccgVertIterator_getCurrent(vi);
254                 VecCopyf(dlm->mvert[i].co, ccgSubSurf_getVertData(ss, v));
255                 *((int*) ccgSubSurf_getVertUserData(ss, v)) = i++;
256         }
257         ccgVertIterator_free(vi);
258
259         edgeIndexBase = edgeBase = i;
260         ei = ccgSubSurf_getEdgeIterator(ss);
261         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
262                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
263                 int x;
264
265                 for (x=1; x<edgeSize-1; x++) {
266                         VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getEdgeData(ss, e, x));
267                 }
268
269                 *((int*) ccgSubSurf_getEdgeUserData(ss, e)) = edgeBase;
270                 edgeBase += edgeSize-2;
271         }
272         ccgEdgeIterator_free(ei);
273
274         faceIndexBase = faceBase = i;
275         fi = ccgSubSurf_getFaceIterator(ss);
276         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
277                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
278                 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
279
280                 VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getFaceCenterData(ss, f));
281                 
282                 for (S=0; S<numVerts; S++) {
283                         for (x=1; x<gridSize-1; x++) {
284                                 VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
285                         }
286                 }
287
288                 for (S=0; S<numVerts; S++) {
289                         for (y=1; y<gridSize-1; y++) {
290                                 for (x=1; x<gridSize-1; x++) {
291                                         VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getFaceGridData(ss, f, S, x, y));
292                                 }
293                         }
294                 }
295
296                 *((int*) ccgSubSurf_getFaceUserData(ss, f)) = faceBase;
297                 faceBase += 1 + numVerts*((gridSize-2) + (gridSize-2)*(gridSize-2));
298         }
299         ccgFaceIterator_free(fi);
300
301                 // load edges
302
303         i=0;
304         ei = ccgSubSurf_getEdgeIterator(ss);
305         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
306                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
307                 for (x=0; x<edgeSize-1; x++) {
308                         MEdge *med = &dlm->medge[i];
309                         med->v1 = getEdgeIndex(ss, e, x, edgeSize);
310                         med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
311                         med->flag = ME_EDGEDRAW;
312
313                         if (ssm->controlType==SUBSURF_CONTROLTYPE_EDITMESH) {
314                                 EditEdge *ee = ccgSubSurf_getEdgeEdgeHandle(ss, e);
315
316                                 if (ee->seam) {
317                                         med->flag|= ME_SEAM;
318                                 }
319                         } else {
320                                 int edgeIdx = (int) ccgSubSurf_getEdgeEdgeHandle(ss, e);
321
322                                         /* Edges created by lib have handle of -1 */
323                                 if (edgeIdx!=-1 && ssm->me->medge) {
324                                         MEdge *origMed = &ssm->me->medge[edgeIdx];
325
326                                         med->flag|= (origMed->flag&ME_SEAM);
327                                 }
328                         }
329
330                         i++;
331                 }
332         }
333         ccgEdgeIterator_free(ei);
334
335         fi = ccgSubSurf_getFaceIterator(ss);
336         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
337                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
338                 int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
339
340                 for (k=0; k<numVerts; k++) {
341                         for (x=0; x<gridSize-1; x++) {
342                                 MEdge *med = &dlm->medge[i];
343                                 med->v1 = getFaceIndex(ss, f, k, x, 0, edgeSize, gridSize);
344                                 med->v2 = getFaceIndex(ss, f, k, x+1, 0, edgeSize, gridSize);
345                                 i++;
346                         }
347
348                         for (x=1; x<gridSize-1; x++) {
349                                 for (y=0; y<gridSize-1; y++) {
350                                         MEdge *med;
351                                         
352                                         med = &dlm->medge[i];
353                                         med->v1 = getFaceIndex(ss, f, k, x, y, edgeSize, gridSize);
354                                         med->v2 = getFaceIndex(ss, f, k, x, y+1, edgeSize, gridSize);
355                                         i++;
356
357                                         med = &dlm->medge[i];
358                                         med->v1 = getFaceIndex(ss, f, k, y, x, edgeSize, gridSize);
359                                         med->v2 = getFaceIndex(ss, f, k, y+1, x, edgeSize, gridSize);
360                                         i++;
361                                 }
362                         }
363                 }
364         }
365         ccgFaceIterator_free(fi);
366
367                 // load faces
368
369         i = 0;
370         fi = ccgSubSurf_getFaceIterator(ss);
371         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
372                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
373                 int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
374                 float edge_data[4][6];
375                 float corner_data[4][6];
376                 float center_data[6] = {0};
377                 int numDataComponents;
378                 TFace *origTFace = NULL;
379                 MCol *origMCol = NULL;
380                 int mat_nr;
381                 int flag;
382
383                 if (ssm->controlType==SUBSURF_CONTROLTYPE_MESH) {
384                         int origIdx = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
385                         MFace *origMFace = &((MFace*) ssm->me->mface)[origIdx];
386                         if (ssm->me->tface)
387                                 origTFace = &((TFace*)ssm->me->tface)[origIdx];
388                         if (ssm->me->mcol)
389                                 origMCol = &ssm->me->mcol[origIdx*4];
390                         mat_nr = origMFace->mat_nr;
391                         flag = origMFace->flag;
392                 } else {
393                         EditFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f);
394                         mat_nr = ef->mat_nr;
395                         flag = ef->flag;
396                 }
397
398                 if (origTFace) {
399                         for (S=0; S<numVerts; S++) {
400                                 unsigned char *col = (unsigned char*) &origTFace->col[S];
401                                 corner_data[S][0] = col[0]/255.0f;
402                                 corner_data[S][1] = col[1]/255.0f;
403                                 corner_data[S][2] = col[2]/255.0f;
404                                 corner_data[S][3] = col[3]/255.0f;
405                                 corner_data[S][4] = origTFace->uv[S][0];
406                                 corner_data[S][5] = origTFace->uv[S][1];
407                         }
408                         numDataComponents = 6;
409                 } else if (origMCol) {
410                         for (S=0; S<numVerts; S++) {
411                                 unsigned char *col = (unsigned char*) &origMCol[S];
412                                 corner_data[S][0] = col[0]/255.0f;
413                                 corner_data[S][1] = col[1]/255.0f;
414                                 corner_data[S][2] = col[2]/255.0f;
415                                 corner_data[S][3] = col[3]/255.0f;
416                         }
417                         numDataComponents = 4;
418                 } else {
419                         numDataComponents = 0;
420                 }
421
422                 for (S=0; S<numVerts; S++) {
423                         for (k=0; k<numDataComponents; k++) {
424                                 edge_data[S][k] = (corner_data[S][k] + corner_data[(S+1)%numVerts][k])*0.5f;
425                                 center_data[k]+= corner_data[S][k];
426                         }
427                 }
428                 for (k=0; k<numDataComponents; k++) {
429                         center_data[k]/= numVerts;
430                 }
431
432                 for (S=0; S<numVerts; S++) {
433                         int prevS= (S-1+numVerts)%numVerts;
434                         for (y=0; y<gridSize-1; y++) {
435                                 for (x=0; x<gridSize-1; x++) {
436                                         mf = &dlm->mface[i];
437                                         mf->v1 = getFaceIndex(ss, f, S, x+0, y+1, edgeSize, gridSize);
438                                         mf->v2 = getFaceIndex(ss, f, S, x+1, y+1, edgeSize, gridSize);
439                                         mf->v3 = getFaceIndex(ss, f, S, x+1, y+0, edgeSize, gridSize);
440                                         mf->v4 = getFaceIndex(ss, f, S, x+0, y+0, edgeSize, gridSize);
441                                         mf->mat_nr = mat_nr;
442                                         mf->flag = flag;
443                                         mf->edcode = 0;
444
445                                         if (x+1==gridSize-1)
446                                                 mf->edcode|= ME_V2V3;
447                                         if (y+1==gridSize-1)
448                                                 mf->edcode|= ME_V1V2;
449
450                                         for (j=0; j<4; j++) {
451                                                 int fx = x + (j==1||j==2);
452                                                 int fy = y + (j==0||j==1);
453                                                 float x_v = (float) fx/(gridSize-1);
454                                                 float y_v = (float) fy/(gridSize-1);
455                                                 float data[6];
456
457                                                 for (k=0; k<numDataComponents; k++) {
458                                                         data[k] = (center_data[k]*(1.0f-x_v) + edge_data[S][k]*x_v)*(1.0f-y_v) + 
459                                                                         (edge_data[prevS][k]*(1.0f-x_v) + corner_data[S][k]*x_v)*y_v;
460                                                 }
461
462                                                 if (dlm->tface) {
463                                                         TFace *tf = &dlm->tface[i];
464                                                         unsigned char col[4];
465                                                         col[0] = (int) (data[0]*255);
466                                                         col[1] = (int) (data[1]*255);
467                                                         col[2] = (int) (data[2]*255);
468                                                         col[3] = (int) (data[3]*255);
469                                                         tf->col[j] = *((unsigned int*) col);
470                                                         tf->uv[j][0] = data[4];
471                                                         tf->uv[j][1] = data[5];
472                                                 } else if (dlm->mcol) {
473                                                         unsigned char *col = (unsigned char*) &dlm->mcol[i*4+j];
474                                                         col[0] = (int) (data[0]*255);
475                                                         col[1] = (int) (data[1]*255);
476                                                         col[2] = (int) (data[2]*255);
477                                                         col[3] = (int) (data[3]*255);
478                                                 }
479                                         }
480                                         if (dlm->tface) {
481                                                 TFace *tf = &dlm->tface[i];
482                                                 tf->tpage = origTFace->tpage;
483                                                 tf->flag = origTFace->flag;
484                                                 tf->transp = origTFace->transp;
485                                                 tf->mode = origTFace->mode;
486                                                 tf->tile = origTFace->tile;
487                                         }
488
489                                         i++;
490                                 }
491                         }
492                 }
493         }
494         ccgFaceIterator_free(fi);
495
496         displistmesh_calc_normals(dlm);
497
498         return dlm;
499 }
500
501 static void subSurf_sync(SubSurf *ss, int useFlatSubdiv) {
502         float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss->subSurf);
503
504         ccgSubSurf_initFullSync(ss->subSurf);
505
506         if (ss->controlType==SUBSURF_CONTROLTYPE_MESH) {
507                 CCGVertHDL fVerts[4];
508                 int i;
509
510                 if (ss->deformOb && ss->deformOb->derivedDeform) {
511                         DispListMesh *dlm = ss->deformOb->derivedDeform->convertToDispListMesh(ss->deformOb->derivedDeform);
512
513                         for (i=0; i<ss->me->totvert; i++) {
514                                 ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, dlm->mvert[i].co);
515                         }
516
517                         displistmesh_free(dlm);
518                 } else {
519                         for (i=0; i<ss->me->totvert; i++) {
520                                 ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, ss->me->mvert[i].co);
521                         }
522                 }
523
524                 if (ss->me->medge) {
525                         for (i=0; i<ss->me->totedge; i++) {
526                                 MEdge *med = &ss->me->medge[i];
527                                 float crease = useFlatSubdiv?creaseFactor:med->crease*creaseFactor/255.0f;
528
529                                 ccgSubSurf_syncEdge(ss->subSurf, (CCGEdgeHDL) i, (CCGVertHDL) med->v1, (CCGVertHDL) med->v2, crease);
530                         }
531                 } else {
532                         for (i=0; i<ss->me->totface; i++) {
533                                 MFace *mf = &((MFace*) ss->me->mface)[i];
534
535                                 if (!mf->v3) {
536                                         ccgSubSurf_syncEdge(ss->subSurf, (CCGEdgeHDL) i, (CCGVertHDL) mf->v1, (CCGVertHDL) mf->v2, useFlatSubdiv?creaseFactor:0.0);
537                                 }
538                         }
539                 }
540
541                 for (i=0; i<ss->me->totface; i++) {
542                         MFace *mf = &((MFace*) ss->me->mface)[i];
543
544                         if (mf->v3) {
545                                 fVerts[0] = (CCGVertHDL) mf->v1;
546                                 fVerts[1] = (CCGVertHDL) mf->v2;
547                                 fVerts[2] = (CCGVertHDL) mf->v3;
548                                 fVerts[3] = (CCGVertHDL) mf->v4;
549
550                                 ccgSubSurf_syncFace(ss->subSurf, (CCGFaceHDL) i, fVerts[3]?4:3, fVerts);
551                         }
552                 }
553         } else {
554                 EditVert *ev, *fVerts[4];
555                 EditEdge *ee;
556                 EditFace *ef;
557
558                 for (ev=ss->em->verts.first; ev; ev=ev->next) {
559                         ccgSubSurf_syncVert(ss->subSurf, ev, ev->co);
560                 }
561
562                 for (ee=ss->em->edges.first; ee; ee=ee->next) {
563                         ccgSubSurf_syncEdge(ss->subSurf, ee, ee->v1, ee->v2, useFlatSubdiv?creaseFactor:ee->crease*creaseFactor);
564                 }
565
566                 for (ef=ss->em->faces.first; ef; ef=ef->next) {
567                         fVerts[0] = ef->v1;
568                         fVerts[1] = ef->v2;
569                         fVerts[2] = ef->v3;
570                         fVerts[3] = ef->v4;
571
572                         ccgSubSurf_syncFace(ss->subSurf, ef, ef->v4?4:3, (CCGVertHDL*) fVerts);
573                 }
574         }
575
576         ccgSubSurf_processSync(ss->subSurf);
577 }
578
579 /***/
580
581 typedef struct {
582         DerivedMesh dm;
583
584         SubSurf *ss;
585 } CCGDerivedMesh;
586
587 static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
588         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
589         CCGSubSurf *ss = ccgdm->ss->subSurf;
590         CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
591         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
592         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
593         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
594         int gridSize = ccgSubSurf_getGridSize(ss);
595
596         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
597                 CCGVert *v = ccgVertIterator_getCurrent(vi);
598                 float *co = ccgSubSurf_getVertData(ss, v);
599
600                 DO_MINMAX(co, min_r, max_r);
601         }
602
603         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
604                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
605                 EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(ss, e);
606                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
607
608                 for (i=1; i<edgeSize-1; i++)
609                         DO_MINMAX(edgeData[i].co, min_r, max_r);
610         }
611
612         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
613                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
614                 EditFace *efa = ccgSubSurf_getFaceFaceHandle(ss, f);
615                 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
616
617                 for (S=0; S<numVerts; S++) {
618                         VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
619
620                         for (x=0; x<gridSize; x++)
621                                 DO_MINMAX(faceGridData[x].co, min_r, max_r);
622                         for (y=0; y<gridSize; y++)
623                                 for (x=0; x<gridSize; x++)
624                                         DO_MINMAX(faceGridData[y*gridSize + x].co, min_r, max_r);
625                 }
626         }
627
628         ccgFaceIterator_free(fi);
629         ccgEdgeIterator_free(ei);
630         ccgVertIterator_free(vi);
631 }
632 static int ccgDM_getNumVerts(DerivedMesh *dm) {
633         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
634
635         return ccgSubSurf_getNumFinalVerts(ccgdm->ss->subSurf);
636 }
637 static int ccgDM_getNumFaces(DerivedMesh *dm) {
638         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
639
640         return ccgSubSurf_getNumFinalFaces(ccgdm->ss->subSurf);
641 }
642 static void ccgDM_getMappedVertCoEM(DerivedMesh *dm, void *vert, float co_r[3]) {
643         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
644         CCGVert *v = ccgSubSurf_getVert(ccgdm->ss->subSurf, vert);
645         float *co = ccgSubSurf_getVertData(ccgdm->ss->subSurf, v);
646
647         co_r[0] = co[0];
648         co_r[1] = co[1];
649         co_r[2] = co[2];
650 }
651 static DispListMesh *ccgDM_convertToDispListMesh(DerivedMesh *dm) {
652         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
653
654         return subSurf_createDispListMesh(ccgdm->ss);
655 }
656
657 static void ccgDM_drawVerts(DerivedMesh *dm) {
658 //      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
659 }
660 static void ccgDM_drawEdges(DerivedMesh *dm) {
661         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
662         CCGSubSurf *ss = ccgdm->ss->subSurf;
663         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
664         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
665         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
666         int gridSize = ccgSubSurf_getGridSize(ss);
667
668         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
669                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
670                 EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(ss, e);
671                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
672
673                 if (eed->h!=0)
674                         continue;
675
676                 if (ccgdm->ss->useAging && !(G.f&G_BACKBUFSEL)) {
677                         int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
678                         glColor3ub(0, ageCol>0?ageCol:0, 0);
679                 }
680
681                 glBegin(GL_LINE_STRIP);
682                 for (i=0; i<edgeSize-1; i++) {
683                         glVertex3fv(edgeData[i].co);
684                         glVertex3fv(edgeData[i+1].co);
685                 }
686                 glEnd();
687         }
688
689         if (ccgdm->ss->useAging && !(G.f&G_BACKBUFSEL)) {
690                 glColor3ub(0, 0, 0);
691         }
692
693         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
694                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
695                 EditFace *efa = ccgSubSurf_getFaceFaceHandle(ss, f);
696                 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
697
698                 if (efa->h!=0)
699                         continue;
700
701                 for (S=0; S<numVerts; S++) {
702                         VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
703
704                         glBegin(GL_LINE_STRIP);
705                         for (x=0; x<gridSize; x++)
706                                 glVertex3fv(faceGridData[x].co);
707                         glEnd();
708                         for (y=1; y<gridSize-1; y++) {
709                                 glBegin(GL_LINE_STRIP);
710                                 for (x=0; x<gridSize; x++)
711                                         glVertex3fv(faceGridData[y*gridSize + x].co);
712                                 glEnd();
713                         }
714                         for (x=1; x<gridSize-1; x++) {
715                                 glBegin(GL_LINE_STRIP);
716                                 for (y=0; y<gridSize; y++)
717                                         glVertex3fv(faceGridData[y*gridSize + x].co);
718                                 glEnd();
719                         }
720                 }
721         }
722
723         ccgFaceIterator_free(fi);
724         ccgEdgeIterator_free(ei);
725 }
726 static void ccgDM_drawMappedEdges(DerivedMesh *dm) {
727         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
728         CCGSubSurf *ss = ccgdm->ss->subSurf;
729         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
730         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
731
732         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
733                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
734                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
735
736                 glBegin(GL_LINE_STRIP);
737                 for (i=0; i<edgeSize-1; i++) {
738                         glVertex3fv(edgeData[i].co);
739                         glVertex3fv(edgeData[i+1].co);
740                 }
741                 glEnd();
742         }
743
744         ccgEdgeIterator_free(ei);
745 }
746 static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
747         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
748         CCGSubSurf *ss = ccgdm->ss->subSurf;
749         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
750         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
751
752         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
753                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
754
755                 if (!ccgSubSurf_getEdgeNumFaces(ss, e)) {
756                         VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
757
758                         glBegin(GL_LINE_STRIP);
759                         for (i=0; i<edgeSize-1; i++) {
760                                 glVertex3fv(edgeData[i].co);
761                                 glVertex3fv(edgeData[i+1].co);
762                         }
763                         glEnd();
764                 }
765         }
766
767         ccgEdgeIterator_free(ei);
768 }
769
770 static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
771         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
772         CCGSubSurf *ss = ccgdm->ss->subSurf;
773         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
774         int gridSize = ccgSubSurf_getGridSize(ss);
775
776         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
777                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
778                 EditFace *efa = ccgSubSurf_getFaceFaceHandle(ss, f);
779                 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
780                 int isSmooth = efa->flag&ME_SMOOTH;
781
782                 if (efa->h!=0)
783                         continue;
784
785                 if (!setMaterial(efa->mat_nr+1))
786                         continue;
787
788                 glShadeModel(isSmooth?GL_SMOOTH:GL_FLAT);
789                 for (S=0; S<numVerts; S++) {
790                         VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
791
792                         if (isSmooth) {
793                                 for (y=0; y<gridSize-1; y++) {
794                                         glBegin(GL_QUAD_STRIP);
795                                         for (x=0; x<gridSize; x++) {
796                                                 VertData *a = &faceGridData[(y+0)*gridSize + x];
797                                                 VertData *b = &faceGridData[(y+1)*gridSize + x];
798
799                                                 glNormal3fv(a->no);
800                                                 glVertex3fv(a->co);
801                                                 glNormal3fv(b->no);
802                                                 glVertex3fv(b->co);
803                                         }
804                                         glEnd();
805                                 }
806                         } else {
807                                 glBegin(GL_QUADS);
808                                 for (y=0; y<gridSize-1; y++) {
809                                         for (x=0; x<gridSize-1; x++) {
810                                                 float *a = faceGridData[(y+0)*gridSize + x].co;
811                                                 float *b = faceGridData[(y+0)*gridSize + x + 1].co;
812                                                 float *c = faceGridData[(y+1)*gridSize + x + 1].co;
813                                                 float *d = faceGridData[(y+1)*gridSize + x].co;
814                                                 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
815                                                 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
816                                                 float no[3];
817
818                                                 no[0] = b_dY*a_cZ - b_dZ*a_cY;
819                                                 no[1] = b_dZ*a_cX - b_dX*a_cZ;
820                                                 no[2] = b_dX*a_cY - b_dY*a_cX;
821                                                 glNormal3fv(no);
822
823                                                 glVertex3fv(d);
824                                                 glVertex3fv(c);
825                                                 glVertex3fv(b);
826                                                 glVertex3fv(a);
827                                         }
828                                 }
829                                 glEnd();
830                         }
831                 }
832         }
833
834         ccgFaceIterator_free(fi);
835 }
836 static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
837 //      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
838 }
839 static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) {
840 //      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
841 }
842
843 static void ccgDM_drawMappedVertsEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditVert *vert), void *userData) {
844         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
845         CCGSubSurf *ss = ccgdm->ss->subSurf;
846         CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
847
848         bglBegin(GL_POINTS);
849         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
850                 CCGVert *v = ccgVertIterator_getCurrent(vi);
851                 EditVert *vert = ccgSubSurf_getVertVertHandle(ss,v);
852
853                 if (!setDrawOptions || setDrawOptions(userData, vert)) {
854                         bglVertex3fv(ccgSubSurf_getVertData(ss, v));
855                 }
856         }
857         bglEnd();
858
859         ccgVertIterator_free(vi);
860 }
861 static void ccgDM_drawMappedEdgeEM(DerivedMesh *dm, void *edge) {
862         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
863         CCGSubSurf *ss = ccgdm->ss->subSurf;
864         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
865         CCGEdge *e = ccgSubSurf_getEdge(ss, edge);
866         VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
867         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
868
869         glBegin(GL_LINE_STRIP);
870         for (i=0; i<edgeSize; i++)
871                 glVertex3fv(edgeData[i].co);
872         glEnd();
873
874         ccgEdgeIterator_free(ei);
875 }
876 static void ccgDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void *userData) {
877         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
878         CCGSubSurf *ss = ccgdm->ss->subSurf;
879         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
880         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
881
882         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
883                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
884                 EditEdge *edge = ccgSubSurf_getEdgeEdgeHandle(ss, e);
885                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
886
887                 glBegin(GL_LINE_STRIP);
888                 if (!setDrawOptions || setDrawOptions(userData, edge)) {
889                         if (ccgdm->ss->useAging && !(G.f&G_BACKBUFSEL)) {
890                                 int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
891                                 glColor3ub(0, ageCol>0?ageCol:0, 0);
892                         }
893
894                         for (i=0; i<edgeSize-1; i++) {
895                                 glVertex3fv(edgeData[i].co);
896                                 glVertex3fv(edgeData[i+1].co);
897                         }
898                 }
899                 glEnd();
900         }
901
902         ccgEdgeIterator_free(ei);
903 }
904 static void ccgDM_drawMappedEdgesInterpEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void (*setDrawInterpOptions)(void *userData, EditEdge *edge, float t), void *userData) {
905         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
906         CCGSubSurf *ss = ccgdm->ss->subSurf;
907         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
908         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
909
910         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
911                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
912                 EditEdge *edge = ccgSubSurf_getEdgeEdgeHandle(ss, e);
913                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
914
915                 glBegin(GL_LINE_STRIP);
916                 if (!setDrawOptions || setDrawOptions(userData, edge)) {
917                         for (i=0; i<edgeSize; i++) {
918                                 setDrawInterpOptions(userData, edge, (float) i/(edgeSize-1));
919
920                                 if (ccgdm->ss->useAging && !(G.f&G_BACKBUFSEL)) {
921                                         int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
922                                         glColor3ub(0, ageCol>0?ageCol:0, 0);
923                                 }
924
925                                 glVertex3fv(edgeData[i].co);
926                         }
927                 }
928                 glEnd();
929         }
930 }
931 static void ccgDM_drawMappedFacesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditFace *face), void *userData) {
932         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
933         CCGSubSurf *ss = ccgdm->ss->subSurf;
934         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
935         int gridSize = ccgSubSurf_getGridSize(ss);
936
937         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
938                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
939                 EditFace *efa = ccgSubSurf_getFaceFaceHandle(ss, f);
940                 if (!setDrawOptions || setDrawOptions(userData, efa)) {
941                         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
942
943                         for (S=0; S<numVerts; S++) {
944                                 VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
945
946                                 for (y=0; y<gridSize-1; y++) {
947                                         glBegin(GL_QUAD_STRIP);
948                                         for (x=0; x<gridSize; x++) {
949                                                 glVertex3fv(faceGridData[(y+0)*gridSize + x].co);
950                                                 glVertex3fv(faceGridData[(y+1)*gridSize + x].co);
951                                         }
952                                         glEnd();
953                                 }
954                         }
955                 }
956         }
957
958         ccgFaceIterator_free(fi);
959 }
960
961 static void ccgDM_release(DerivedMesh *dm) {
962         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
963
964         subSurf_free(ccgdm->ss);
965
966         MEM_freeN(ccgdm);
967 }
968
969 static CCGDerivedMesh *getCCGDerivedMesh(SubSurf *ss) {
970         CCGDerivedMesh *ccgdm = MEM_mallocN(sizeof(*ccgdm), "ccgdm");
971
972         ccgdm->dm.getMinMax = ccgDM_getMinMax;
973         ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
974         ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
975         ccgdm->dm.getMappedVertCoEM = ccgDM_getMappedVertCoEM;
976         ccgdm->dm.convertToDispListMesh = ccgDM_convertToDispListMesh;
977
978         ccgdm->dm.drawVerts = ccgDM_drawVerts;
979         ccgdm->dm.drawEdges = ccgDM_drawEdges;
980         ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
981         ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
982         ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
983         ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
984         ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
985
986         ccgdm->dm.drawMappedVertsEM = ccgDM_drawMappedVertsEM;
987         ccgdm->dm.drawMappedEdgeEM = ccgDM_drawMappedEdgeEM;
988         ccgdm->dm.drawMappedEdgesInterpEM = ccgDM_drawMappedEdgesInterpEM;
989         ccgdm->dm.drawMappedEdgesEM = ccgDM_drawMappedEdgesEM;
990         ccgdm->dm.drawMappedFacesEM = ccgDM_drawMappedFacesEM;
991
992         ccgdm->dm.release = ccgDM_release;
993         
994         ccgdm->ss = ss;
995
996         return ccgdm;
997 }
998
999 /***/
1000
1001 DerivedMesh *subsurf_make_derived_from_editmesh(EditMesh *em, int subdivLevels, short type, DerivedMesh *oldDerived) {
1002         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) oldDerived;
1003
1004         if (!ccgdm || ccgSubSurf_getSubdivisionLevels(ccgdm->ss->subSurf)!=subdivLevels) {
1005                 if (ccgdm) {
1006                         oldDerived->release(oldDerived);
1007                 }
1008
1009                 ccgdm = getCCGDerivedMesh(subSurf_fromEditmesh(em, subdivLevels, G.rt==52, 0));
1010         }
1011
1012         subSurf_sync(ccgdm->ss, type==ME_SIMPLE_SUBSURF);
1013
1014         return (DerivedMesh*) ccgdm;
1015 }
1016
1017 DerivedMesh *subsurf_make_derived_from_mesh(Object *ob, int subdivLevels, int useDeformVerts) {
1018         Mesh *me = ob->data;
1019         int useFlatSubdiv = me->subsurftype==ME_SIMPLE_SUBSURF;
1020         SubSurf *ss = subSurf_fromMesh(me, useFlatSubdiv, subdivLevels, useDeformVerts?ob:NULL);
1021         DispListMesh *dlm;
1022
1023         subSurf_sync(ss, useFlatSubdiv);
1024
1025         dlm = subSurf_createDispListMesh(ss);
1026         
1027         subSurf_free(ss);
1028         
1029         return derivedmesh_from_displistmesh(dlm);
1030 }
1031
1032 void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) 
1033 {
1034                 /* Finds the subsurf limit positions for the verts in a mesh 
1035                  * and puts them in an array of floats. Please note that the 
1036                  * calculated vert positions is incorrect for the verts 
1037                  * on the boundary of the mesh.
1038                  */
1039         SubSurf *ss = subSurf_fromMesh(me, 0, 1, NULL);
1040         float edge_sum[3], face_sum[3];
1041         CCGVertIterator *vi;
1042
1043         subSurf_sync(ss, 0);
1044
1045         vi = ccgSubSurf_getVertIterator(ss->subSurf);
1046         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
1047                 CCGVert *v = ccgVertIterator_getCurrent(vi);
1048                 int idx = (int) ccgSubSurf_getVertVertHandle(ss->subSurf, v);
1049                 int N = ccgSubSurf_getVertNumEdges(ss->subSurf, v);
1050                 int numFaces = ccgSubSurf_getVertNumFaces(ss->subSurf, v);
1051                 float *co;
1052                 int i;
1053                 
1054                 edge_sum[0]= edge_sum[1]= edge_sum[2]= 0.0;
1055                 face_sum[0]= face_sum[1]= face_sum[2]= 0.0;
1056
1057                 for (i=0; i<N; i++) {
1058                         CCGEdge *e = ccgSubSurf_getVertEdge(ss->subSurf, v, i);
1059                         VecAddf(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss->subSurf, e, 1));
1060                 }
1061                 for (i=0; i<numFaces; i++) {
1062                         CCGFace *f = ccgSubSurf_getVertFace(ss->subSurf, v, i);
1063                         VecAddf(face_sum, face_sum, ccgSubSurf_getFaceCenterData(ss->subSurf, f));
1064                 }
1065
1066                 co = ccgSubSurf_getVertData(ss->subSurf, v);
1067                 positions_r[idx][0] = (co[0]*N*N + edge_sum[0]*4 + face_sum[0])/(N*(N+5));
1068                 positions_r[idx][1] = (co[1]*N*N + edge_sum[1]*4 + face_sum[1])/(N*(N+5));
1069                 positions_r[idx][2] = (co[2]*N*N + edge_sum[2]*4 + face_sum[2])/(N*(N+5));
1070         }
1071         ccgVertIterator_free(vi);
1072
1073         subSurf_free(ss);
1074 }
1075