- added DerivedMesh.drawUVEdges function & implementations
[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 <float.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_modifier_types.h"
44 #include "DNA_object_types.h"
45
46 #include "BKE_bad_level_calls.h"
47 #include "BKE_utildefines.h"
48 #include "BKE_global.h"
49 #include "BKE_mesh.h"
50 #include "BKE_subsurf.h"
51 #include "BKE_displist.h"
52 #include "BKE_DerivedMesh.h"
53
54 #include "BLI_blenlib.h"
55 #include "BLI_editVert.h"
56 #include "BLI_arithb.h"
57 #include "BLI_linklist.h"
58 #include "BLI_memarena.h"
59
60 #include "BIF_gl.h"
61
62 #include "CCGSubSurf.h"
63
64 typedef struct _VertData {
65         float co[3];
66         float no[3];
67 } VertData;
68
69 typedef struct CCGDerivedMesh CCGDerivedMesh;
70
71 static EditVert *ccgDM_getVertHandle(CCGDerivedMesh *ccgdm, CCGVert *v);
72 static EditEdge *ccgDM_getEdgeHandle(CCGDerivedMesh *ccgdm, CCGEdge *e);
73 static EditFace *ccgDM_getFaceHandle(CCGDerivedMesh *ccgdm, CCGFace *f);
74
75 ///
76
77 static void *arena_alloc(CCGAllocatorHDL a, int numBytes) {
78         return BLI_memarena_alloc(a, numBytes);
79 }
80 static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
81         void *p2 = BLI_memarena_alloc(a, newSize);
82         if (ptr) {
83                 memcpy(p2, ptr, oldSize);
84         }
85         return p2;
86 }
87 static void arena_free(CCGAllocatorHDL a, void *ptr) {
88 }
89 static void arena_release(CCGAllocatorHDL a) {
90         BLI_memarena_free(a);
91 }
92
93 static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int useEdgeCreation, int useFlatSubdiv) {
94         CCGMeshIFC ifc;
95         CCGSubSurf *ccgSS;
96
97                 /* subdivLevels==0 is not allowed */
98         subdivLevels = MAX2(subdivLevels, 1);
99
100         if (prevSS) {
101                 int oldUseAging;
102
103                 useAging = !!useAging;
104                 ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
105
106                 if (oldUseAging!=useAging) {
107                         ccgSubSurf_free(prevSS);
108                 } else {
109                         ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
110
111                         return prevSS;
112                 }
113         }
114
115         if (useAging) {
116                 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
117         } else {
118                 ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 4;
119         }
120         ifc.vertDataSize = sizeof(VertData);
121
122         if (useArena) {
123                 CCGAllocatorIFC allocatorIFC;
124                 CCGAllocatorHDL allocator = BLI_memarena_new((1<<16));
125
126                 allocatorIFC.alloc = arena_alloc;
127                 allocatorIFC.realloc = arena_realloc;
128                 allocatorIFC.free = arena_free;
129                 allocatorIFC.release = arena_release;
130
131                 ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
132         } else {
133                 ccgSS = ccgSubSurf_new(&ifc, subdivLevels, NULL, NULL);
134         }
135
136         if (useAging) {
137                 ccgSubSurf_setUseAgeCounts(ccgSS, 1, 4, 4, 4);
138         }
139         if (useEdgeCreation) {
140                 ccgSubSurf_setAllowEdgeCreation(ccgSS, 1, useFlatSubdiv?subdivLevels:0.0f);
141         }
142
143         ccgSubSurf_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(VertData, no));
144
145         return ccgSS;
146 }
147
148 static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
149         CCGVert *v0 = ccgSubSurf_getEdgeVert0(ss, e);
150         CCGVert *v1 = ccgSubSurf_getEdgeVert1(ss, e);
151         int v0idx = *((int*) ccgSubSurf_getVertUserData(ss, v0));
152         int v1idx = *((int*) ccgSubSurf_getVertUserData(ss, v1));
153         int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
154
155         if (x==0) {
156                 return v0idx;
157         } else if (x==edgeSize-1) {
158                 return v1idx;
159         } else {
160                 return edgeBase + x-1;
161         }
162 }
163 static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
164         int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
165         int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
166
167         if (x==gridSize-1 && y==gridSize-1) {
168                 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
169                 return *((int*) ccgSubSurf_getVertUserData(ss, v));
170         } else if (x==gridSize-1) {
171                 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
172                 CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
173                 int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
174                 if (v==ccgSubSurf_getEdgeVert0(ss, e)) {
175                         return edgeBase + (gridSize-1-y)-1;
176                 } else {
177                         return edgeBase + (edgeSize-2-1)-((gridSize-1-y)-1);
178                 }
179         } else if (y==gridSize-1) {
180                 CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
181                 CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
182                 int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
183                 if (v==ccgSubSurf_getEdgeVert0(ss, e)) {
184                         return edgeBase + (gridSize-1-x)-1;
185                 } else {
186                         return edgeBase + (edgeSize-2-1)-((gridSize-1-x)-1);
187                 }
188         } else if (x==0 && y==0) {
189                 return faceBase;
190         } else if (x==0) {
191                 S = (S+numVerts-1)%numVerts;
192                 return faceBase + 1 + (gridSize-2)*S + (y-1);
193         } else if (y==0) {
194                 return faceBase + 1 + (gridSize-2)*S + (x-1);
195         } else {
196                 return faceBase + 1 + (gridSize-2)*numVerts + S*(gridSize-2)*(gridSize-2) + (y-1)*(gridSize-2) + (x-1);
197         }
198 }
199
200 static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditmesh, MEdge *medge, TFace *tface)
201 {
202         unsigned int flags = ME_EDGEDRAW|ME_EDGERENDER|ME_EDGEMAPPED;
203         int j, N = ccgSubSurf_getEdgeNumFaces(ss, e);
204
205         if (!N) flags |= ME_LOOSEEDGE;
206
207         if (ssFromEditmesh) {
208                 EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(ss, e);
209
210                 if (eed->seam) {
211                         flags |= ME_SEAM;
212                 }
213         } else {
214                 int edgeIdx = (int) ccgSubSurf_getEdgeEdgeHandle(ss, e);
215
216                         /* Edges created by lib have handle of -1 */
217                 if (edgeIdx!=-1 && medge) {
218                         MEdge *origMed = &medge[edgeIdx];
219
220                         flags |= (origMed->flag&ME_SEAM);
221                 }
222
223                 if (tface) {
224                         for (j=0; j<N; j++) {
225                                 CCGFace *f = ccgSubSurf_getEdgeFace(ss, e, j);
226                                 int origIdx = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
227                                 TFace *tf = &tface[origIdx];
228
229                                 if (!(tf->flag&TF_HIDE)) flags |= ME_EDGE_TFVISIBLE;
230                                 if (tf->flag&TF_SELECT) flags |= ME_EDGE_TFSEL;
231
232                                 if (tf->flag&TF_ACTIVE) {
233                                         int fN = ccgSubSurf_getFaceNumVerts(ss, f);
234                                         int k = ccgSubSurf_getFaceEdgeIndex(ss, f, e);
235
236                                         flags |= ME_EDGE_TFACT;
237
238                                         if (k==0) {
239                                                 flags |= ME_EDGE_TFACTFIRST;
240                                         }
241                                         else if (k==fN-1) {
242                                                 flags |= ME_EDGE_TFACTLAST;
243                                         } 
244                                 }
245                         }
246                 }
247         }
248
249         return flags;
250 }
251
252 static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, int ssFromEditmesh, int drawInteriorEdges, Mesh *inMe, DispListMesh *inDLM, EditVert ***vertMap_r, EditEdge ***edgeMap_r, EditFace ***faceMap_r) {
253         DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
254         int edgeSize = ccgSubSurf_getEdgeSize(ss);
255         int gridSize = ccgSubSurf_getGridSize(ss);
256         int edgeIndexBase, edgeBase, faceBase;
257         int i, j, k, S, x, y;
258         int vertBase = 0;
259         TFace *tface = NULL;
260         MEdge *medge = NULL;
261         MFace *mface = NULL;
262         MCol *mcol = NULL;
263         CCGVertIterator *vi;
264         CCGEdgeIterator *ei;
265         CCGFaceIterator *fi;
266         EditVert **vertMap = NULL;
267         EditEdge **edgeMap = NULL;
268         EditFace **faceMap = NULL;
269
270         if (!ssFromEditmesh) {
271                 if (inDLM) {
272                         tface = inDLM->tface;
273                         medge = inDLM->medge;
274                         mface = inDLM->mface;
275                         mcol = inDLM->mcol;
276                 } else if (inMe) {
277                         tface = inMe->tface;
278                         medge = inMe->medge;
279                         mface = inMe->mface;
280                         mcol = inMe->mcol;
281                 }
282         }
283
284         dlm->totvert = ccgSubSurf_getNumFinalVerts(ss);
285         dlm->totedge = ccgSubSurf_getNumFinalEdges(ss);
286         dlm->totface = ccgSubSurf_getNumFinalFaces(ss);
287
288         if (vertMap_r) {
289                 *vertMap_r = vertMap = MEM_callocN(dlm->totvert*sizeof(*vertMap), "vmap");
290                 *edgeMap_r = edgeMap = MEM_callocN(dlm->totedge*sizeof(*edgeMap), "emap");
291                 *faceMap_r = faceMap = MEM_callocN(dlm->totface*sizeof(*faceMap), "fmap");
292         }
293
294         dlm->mvert = MEM_callocN(dlm->totvert*sizeof(*dlm->mvert), "dlm->mvert");
295         dlm->medge = MEM_callocN(dlm->totedge*sizeof(*dlm->medge), "dlm->medge");
296         dlm->mface = MEM_callocN(dlm->totface*sizeof(*dlm->mface), "dlm->mface");
297         if (!ssFromEditmesh && tface) {
298                 dlm->tface = MEM_callocN(dlm->totface*sizeof(*dlm->tface), "dlm->tface");
299                 dlm->mcol = NULL;
300         } else if (!ssFromEditmesh && mcol) {
301                 dlm->tface = NULL;
302                 dlm->mcol = MEM_mallocN(dlm->totface*4*sizeof(*dlm->mcol), "dlm->mcol");
303         } else {
304                 dlm->tface = NULL;
305                 dlm->mcol = NULL;
306         }
307
308                 // load vertices
309
310         vertBase = i = 0;
311         vi = ccgSubSurf_getVertIterator(ss);
312         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
313                 CCGVert *v = ccgVertIterator_getCurrent(vi);
314                 VecCopyf(dlm->mvert[i].co, ccgSubSurf_getVertData(ss, v));
315                 if (vertMap) {
316                         vertMap[i] = ccgDM_getVertHandle(ccgdm, v);
317                 }
318                 *((int*) ccgSubSurf_getVertUserData(ss, v)) = i++;
319         }
320         ccgVertIterator_free(vi);
321
322         edgeIndexBase = edgeBase = i;
323         ei = ccgSubSurf_getEdgeIterator(ss);
324         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
325                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
326                 int x;
327
328                 for (x=1; x<edgeSize-1; x++) {
329                         VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getEdgeData(ss, e, x));
330                 }
331
332                 *((int*) ccgSubSurf_getEdgeUserData(ss, e)) = edgeBase;
333                 edgeBase += edgeSize-2;
334         }
335         ccgEdgeIterator_free(ei);
336
337         faceBase = i;
338         fi = ccgSubSurf_getFaceIterator(ss);
339         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
340                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
341                 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
342
343                 VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getFaceCenterData(ss, f));
344                 
345                 for (S=0; S<numVerts; S++) {
346                         for (x=1; x<gridSize-1; x++) {
347                                 VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
348                         }
349                 }
350
351                 for (S=0; S<numVerts; S++) {
352                         for (y=1; y<gridSize-1; y++) {
353                                 for (x=1; x<gridSize-1; x++) {
354                                         VecCopyf(dlm->mvert[i++].co, ccgSubSurf_getFaceGridData(ss, f, S, x, y));
355                                 }
356                         }
357                 }
358
359                 *((int*) ccgSubSurf_getFaceUserData(ss, f)) = faceBase;
360                 faceBase += 1 + numVerts*((gridSize-2) + (gridSize-2)*(gridSize-2));
361         }
362         ccgFaceIterator_free(fi);
363
364                 // load edges
365
366         i=0;
367         ei = ccgSubSurf_getEdgeIterator(ss);
368         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
369                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
370                 unsigned int flags = ss_getEdgeFlags(ss, e, ssFromEditmesh, medge, tface);
371
372                 for (x=0; x<edgeSize-1; x++) {
373                         MEdge *med = &dlm->medge[i];
374                         med->v1 = getEdgeIndex(ss, e, x, edgeSize);
375                         med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
376                         med->flag = flags;
377
378                         if (edgeMap) {
379                                 edgeMap[i] = ccgDM_getEdgeHandle(ccgdm, e);
380                         }
381
382                         i++;
383                 }
384         }
385         ccgEdgeIterator_free(ei);
386
387         fi = ccgSubSurf_getFaceIterator(ss);
388         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
389                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
390                 int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
391
392                 for (k=0; k<numVerts; k++) {
393                         for (x=0; x<gridSize-1; x++) {
394                                 MEdge *med = &dlm->medge[i];
395                                 if (drawInteriorEdges) med->flag = ME_EDGEDRAW|ME_EDGERENDER;
396                                 med->v1 = getFaceIndex(ss, f, k, x, 0, edgeSize, gridSize);
397                                 med->v2 = getFaceIndex(ss, f, k, x+1, 0, edgeSize, gridSize);
398                                 i++;
399                         }
400
401                         for (x=1; x<gridSize-1; x++) {
402                                 for (y=0; y<gridSize-1; y++) {
403                                         MEdge *med;
404                                         
405                                         med = &dlm->medge[i];
406                                         if (drawInteriorEdges) med->flag = ME_EDGEDRAW|ME_EDGERENDER;
407                                         med->v1 = getFaceIndex(ss, f, k, x, y, edgeSize, gridSize);
408                                         med->v2 = getFaceIndex(ss, f, k, x, y+1, edgeSize, gridSize);
409                                         i++;
410
411                                         med = &dlm->medge[i];
412                                         if (drawInteriorEdges) med->flag = ME_EDGEDRAW|ME_EDGERENDER;
413                                         med->v1 = getFaceIndex(ss, f, k, y, x, edgeSize, gridSize);
414                                         med->v2 = getFaceIndex(ss, f, k, y+1, x, edgeSize, gridSize);
415                                         i++;
416                                 }
417                         }
418                 }
419         }
420         ccgFaceIterator_free(fi);
421
422                 // load faces
423
424         i = 0;
425         fi = ccgSubSurf_getFaceIterator(ss);
426         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
427                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
428                 int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
429                 float edge_data[4][6];
430                 float corner_data[4][6];
431                 float center_data[6] = {0};
432                 int numDataComponents = 0;
433                 TFace *origTFace = NULL;
434                 int mat_nr;
435                 int flag;
436
437                 if (!ssFromEditmesh) {
438                         int origIdx = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
439                         MFace *origMFace = &mface[origIdx];
440                         
441                         if (tface) {
442                                 origTFace = &tface[origIdx];
443
444                                 for (S=0; S<numVerts; S++) {
445                                         unsigned char *col = (unsigned char*) &origTFace->col[S];
446                                         corner_data[S][0] = col[0]/255.0f;
447                                         corner_data[S][1] = col[1]/255.0f;
448                                         corner_data[S][2] = col[2]/255.0f;
449                                         corner_data[S][3] = col[3]/255.0f;
450                                         corner_data[S][4] = origTFace->uv[S][0];
451                                         corner_data[S][5] = origTFace->uv[S][1];
452                                 }
453                                 numDataComponents = 6;
454                         } else if (mcol) {
455                                 MCol *origMCol = &mcol[origIdx*4];
456
457                                 for (S=0; S<numVerts; S++) {
458                                         unsigned char *col = (unsigned char*) &origMCol[S];
459                                         corner_data[S][0] = col[0]/255.0f;
460                                         corner_data[S][1] = col[1]/255.0f;
461                                         corner_data[S][2] = col[2]/255.0f;
462                                         corner_data[S][3] = col[3]/255.0f;
463                                 }
464                                 numDataComponents = 4;
465                         }
466
467                         for (S=0; S<numVerts; S++) {
468                                 for (k=0; k<numDataComponents; k++) {
469                                         edge_data[S][k] = (corner_data[S][k] + corner_data[(S+1)%numVerts][k])*0.5f;
470                                         center_data[k]+= corner_data[S][k];
471                                 }
472                         }
473                         for (k=0; k<numDataComponents; k++) {
474                                 center_data[k]/= numVerts;
475                         }
476
477                         mat_nr = origMFace->mat_nr;
478                         flag = origMFace->flag;
479                 } else {
480                         EditFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f);
481                         mat_nr = ef->mat_nr;
482                         flag = ef->flag;
483                 }
484
485                 for (S=0; S<numVerts; S++) {
486                         int prevS= (S-1+numVerts)%numVerts;
487
488                         for (y=0; y<gridSize-1; y++) {
489                                 for (x=0; x<gridSize-1; x++) {
490                                         MFace *mf = &dlm->mface[i];
491                                         mf->v1 = getFaceIndex(ss, f, S, x+0, y+1, edgeSize, gridSize);
492                                         mf->v2 = getFaceIndex(ss, f, S, x+1, y+1, edgeSize, gridSize);
493                                         mf->v3 = getFaceIndex(ss, f, S, x+1, y+0, edgeSize, gridSize);
494                                         mf->v4 = getFaceIndex(ss, f, S, x+0, y+0, edgeSize, gridSize);
495                                         mf->mat_nr = mat_nr;
496                                         mf->flag = flag;
497                                         mf->edcode = 0;
498
499                                         if (faceMap) {
500                                                 faceMap[i] = ccgDM_getFaceHandle(ccgdm, f);
501                                         }
502
503                                         if (x+1==gridSize-1)
504                                                 mf->edcode|= ME_V2V3;
505                                         if (y+1==gridSize-1)
506                                                 mf->edcode|= ME_V1V2;
507
508                                         for (j=0; j<4; j++) {
509                                                 int fx = x + (j==1||j==2);
510                                                 int fy = y + (j==0||j==1);
511                                                 float x_v = (float) fx/(gridSize-1);
512                                                 float y_v = (float) fy/(gridSize-1);
513                                                 float data[6];
514
515                                                 for (k=0; k<numDataComponents; k++) {
516                                                         data[k] = (center_data[k]*(1.0f-x_v) + edge_data[S][k]*x_v)*(1.0f-y_v) + 
517                                                                         (edge_data[prevS][k]*(1.0f-x_v) + corner_data[S][k]*x_v)*y_v;
518                                                 }
519
520                                                 if (dlm->tface) {
521                                                         TFace *tf = &dlm->tface[i];
522                                                         unsigned char col[4];
523                                                         col[0] = (int) (data[0]*255);
524                                                         col[1] = (int) (data[1]*255);
525                                                         col[2] = (int) (data[2]*255);
526                                                         col[3] = (int) (data[3]*255);
527                                                         tf->col[j] = *((unsigned int*) col);
528                                                         tf->uv[j][0] = data[4];
529                                                         tf->uv[j][1] = data[5];
530                                                 } else if (dlm->mcol) {
531                                                         unsigned char *col = (unsigned char*) &dlm->mcol[i*4+j];
532                                                         col[0] = (int) (data[0]*255);
533                                                         col[1] = (int) (data[1]*255);
534                                                         col[2] = (int) (data[2]*255);
535                                                         col[3] = (int) (data[3]*255);
536                                                 }
537                                         }
538
539                                         if (dlm->tface) {
540                                                 TFace *tf = &dlm->tface[i];
541                                                 tf->tpage = origTFace->tpage;
542                                                 tf->flag = origTFace->flag;
543                                                 tf->transp = origTFace->transp;
544                                                 tf->mode = origTFace->mode;
545                                                 tf->tile = origTFace->tile;
546                                         }
547
548                                         i++;
549                                 }
550                         }
551                 }
552         }
553         ccgFaceIterator_free(fi);
554
555         mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors);
556
557         return dlm;
558 }
559
560 static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float (*vertexCos)[3], int useFlatSubdiv) {
561         float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
562         CCGVertHDL fVerts[4];
563         MVert *mvert = dlm?dlm->mvert:me->mvert;
564         MEdge *medge = dlm?dlm->medge:me->medge;
565         MFace *mface = dlm?dlm->mface:me->mface;
566         int totvert = dlm?dlm->totvert:me->totvert;
567         int totedge = dlm?dlm->totedge:me->totedge;
568         int totface = dlm?dlm->totface:me->totface;
569         int i;
570
571         ccgSubSurf_initFullSync(ss);
572
573         if (vertexCos) {
574                 for (i=0; i<totvert; i++) {
575                         ccgSubSurf_syncVert(ss, (CCGVertHDL) i, vertexCos[i]);
576                 }
577         } else {
578                 for (i=0; i<totvert; i++) {
579                         ccgSubSurf_syncVert(ss, (CCGVertHDL) i, mvert[i].co);
580                 }
581         }
582
583         if (medge) {
584                 for (i=0; i<totedge; i++) {
585                         MEdge *med = &medge[i];
586                         float crease = useFlatSubdiv?creaseFactor:med->crease*creaseFactor/255.0f;
587
588                         ccgSubSurf_syncEdge(ss, (CCGEdgeHDL) i, (CCGVertHDL) med->v1, (CCGVertHDL) med->v2, crease);
589                 }
590         } else {
591                 for (i=0; i<totface; i++) {
592                         MFace *mf = &((MFace*) mface)[i];
593
594                         if (!mf->v3) {
595                                 ccgSubSurf_syncEdge(ss, (CCGEdgeHDL) i, (CCGVertHDL) mf->v1, (CCGVertHDL) mf->v2, useFlatSubdiv?creaseFactor:0.0f);
596                         }
597                 }
598         }
599
600         for (i=0; i<totface; i++) {
601                 MFace *mf = &((MFace*) mface)[i];
602
603                 if (mf->v3) {
604                         fVerts[0] = (CCGVertHDL) mf->v1;
605                         fVerts[1] = (CCGVertHDL) mf->v2;
606                         fVerts[2] = (CCGVertHDL) mf->v3;
607                         fVerts[3] = (CCGVertHDL) mf->v4;
608
609                         ccgSubSurf_syncFace(ss, (CCGFaceHDL) i, fVerts[3]?4:3, fVerts);
610                 }
611         }
612
613         ccgSubSurf_processSync(ss);
614 }
615
616 void ss_sync_from_editmesh(CCGSubSurf *ss, EditMesh *em, float (*vertCos)[3], int useFlatSubdiv)
617 {
618         float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
619         EditVert *ev, *fVerts[4];
620         EditEdge *ee;
621         EditFace *ef;
622
623         ccgSubSurf_initFullSync(ss);
624
625         if (vertCos) {
626                 int i=0;
627
628                 for (ev=em->verts.first; ev; ev=ev->next) {
629                         ccgSubSurf_syncVert(ss, ev, vertCos[i++]);
630                 }
631         } else {
632                 for (ev=em->verts.first; ev; ev=ev->next) {
633                         ccgSubSurf_syncVert(ss, ev, ev->co);
634                 }
635         }
636
637         for (ee=em->edges.first; ee; ee=ee->next) {
638                 ccgSubSurf_syncEdge(ss, ee, ee->v1, ee->v2, useFlatSubdiv?creaseFactor:ee->crease*creaseFactor);
639         }
640
641         for (ef=em->faces.first; ef; ef=ef->next) {
642                 fVerts[0] = ef->v1;
643                 fVerts[1] = ef->v2;
644                 fVerts[2] = ef->v3;
645                 fVerts[3] = ef->v4;
646
647                 ccgSubSurf_syncFace(ss, ef, ef->v4?4:3, (CCGVertHDL*) fVerts);
648         }
649
650         ccgSubSurf_processSync(ss);
651 }
652
653 /***/
654
655 struct CCGDerivedMesh {
656         DerivedMesh dm;
657
658         CCGSubSurf *ss;
659         int fromEditmesh, drawInteriorEdges;
660
661         Mesh *me;
662         DispListMesh *dlm;
663
664         EditVert **vertMap;
665         EditEdge **edgeMap;
666         EditFace **faceMap;
667 };
668
669 static EditVert *ccgDM_getVertHandle(CCGDerivedMesh *ccgdm, CCGVert *v) {
670         if (ccgdm->vertMap) {
671                 int index = (int) ccgSubSurf_getVertVertHandle(ccgdm->ss, v);
672
673                 return ccgdm->vertMap[index];
674         } else {
675                 return ccgSubSurf_getVertVertHandle(ccgdm->ss, v);
676         }
677 }
678 static EditEdge *ccgDM_getEdgeHandle(CCGDerivedMesh *ccgdm, CCGEdge *e) {
679         if (ccgdm->vertMap) {
680                 int index = (int) ccgSubSurf_getEdgeEdgeHandle(ccgdm->ss, e);
681
682                 return ccgdm->edgeMap[index];
683         } else {
684                 return ccgSubSurf_getEdgeEdgeHandle(ccgdm->ss, e);
685         }
686 }
687 static EditFace *ccgDM_getFaceHandle(CCGDerivedMesh *ccgdm, CCGFace *f) {
688         if (ccgdm->vertMap) {
689                 int index = (int) ccgSubSurf_getFaceFaceHandle(ccgdm->ss, f);
690
691                 return ccgdm->faceMap[index];
692         } else {
693                 return ccgSubSurf_getFaceFaceHandle(ccgdm->ss, f);
694         }
695 }
696
697 static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
698         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
699         CCGSubSurf *ss = ccgdm->ss;
700         CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
701         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
702         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
703         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
704         int gridSize = ccgSubSurf_getGridSize(ss);
705
706         if (!ccgSubSurf_getNumVerts(ss))
707                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
708
709         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
710                 CCGVert *v = ccgVertIterator_getCurrent(vi);
711                 float *co = ccgSubSurf_getVertData(ss, v);
712
713                 DO_MINMAX(co, min_r, max_r);
714         }
715
716         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
717                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
718                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
719
720                 for (i=0; i<edgeSize; i++)
721                         DO_MINMAX(edgeData[i].co, min_r, max_r);
722         }
723
724         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
725                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
726                 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
727
728                 for (S=0; S<numVerts; S++) {
729                         VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
730
731                         for (y=0; y<gridSize; y++)
732                                 for (x=0; x<gridSize; x++)
733                                         DO_MINMAX(faceGridData[y*gridSize + x].co, min_r, max_r);
734                 }
735         }
736
737         ccgFaceIterator_free(fi);
738         ccgEdgeIterator_free(ei);
739         ccgVertIterator_free(vi);
740 }
741 static int ccgDM_getNumVerts(DerivedMesh *dm) {
742         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
743
744         return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
745 }
746 static int ccgDM_getNumFaces(DerivedMesh *dm) {
747         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
748
749         return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
750 }
751 static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
752         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
753         CCGSubSurf *ss = ccgdm->ss;
754         int edgeSize = ccgSubSurf_getEdgeSize(ss);
755         int gridSize = ccgSubSurf_getGridSize(ss);
756         int i;
757         CCGVertIterator *vi;
758         CCGEdgeIterator *ei;
759         CCGFaceIterator *fi;
760
761         i = 0;
762         vi = ccgSubSurf_getVertIterator(ss);
763         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
764                 CCGVert *v = ccgVertIterator_getCurrent(vi);
765                 VecCopyf(cos[i++], ccgSubSurf_getVertData(ss, v));
766         }
767         ccgVertIterator_free(vi);
768
769         ei = ccgSubSurf_getEdgeIterator(ss);
770         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
771                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
772                 int x;
773
774                 for (x=1; x<edgeSize-1; x++)
775                         VecCopyf(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
776         }
777         ccgEdgeIterator_free(ei);
778
779         fi = ccgSubSurf_getFaceIterator(ss);
780         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
781                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
782                 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
783
784                 VecCopyf(cos[i++], ccgSubSurf_getFaceCenterData(ss, f));
785                 for (S=0; S<numVerts; S++)
786                         for (x=1; x<gridSize-1; x++)
787                                 VecCopyf(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
788                 for (S=0; S<numVerts; S++)
789                         for (y=1; y<gridSize-1; y++)
790                                 for (x=1; x<gridSize-1; x++)
791                                         VecCopyf(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
792         }
793         ccgFaceIterator_free(fi);
794 }
795 static void ccgDM_foreachMappedVertEM(DerivedMesh *dm, void (*func)(void *userData, EditVert *vert, float *co, float *no_f, short *no_s), void *userData) {
796         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
797         CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss);
798
799         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
800                 CCGVert *v = ccgVertIterator_getCurrent(vi);
801                 VertData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
802
803                 func(userData, ccgDM_getVertHandle(ccgdm, v), vd->co, vd->no, NULL);
804         }
805
806         ccgVertIterator_free(vi);
807 }
808 static void ccgDM_foreachMappedEdgeEM(DerivedMesh *dm, void (*func)(void *userData, EditEdge *eed, float *v0co, float *v1co), void *userData) {
809         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
810         CCGSubSurf *ss = ccgdm->ss;
811         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
812         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
813
814         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
815                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
816                 EditEdge *edge = ccgDM_getEdgeHandle(ccgdm, e);
817                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
818
819                 for (i=0; i<edgeSize-1; i++)
820                         func(userData, edge, edgeData[i].co, edgeData[i+1].co);
821         }
822
823         ccgEdgeIterator_free(ei);
824 }
825 static DispListMesh *ccgDM_convertToDispListMesh(DerivedMesh *dm, int allowShared) {
826         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
827
828         return ss_to_displistmesh(ccgdm->ss, ccgdm, ccgdm->fromEditmesh, ccgdm->drawInteriorEdges, ccgdm->me, ccgdm->dlm, NULL, NULL, NULL);
829 }
830 static DispListMesh *ccgDM_convertToDispListMeshMapped(DerivedMesh *dm, int allowShared, EditVert ***vertMap_r, EditEdge ***edgeMap_r, EditFace ***faceMap_r) {
831         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
832
833         return ss_to_displistmesh(ccgdm->ss, ccgdm, ccgdm->fromEditmesh, ccgdm->drawInteriorEdges, ccgdm->me, ccgdm->dlm, vertMap_r, edgeMap_r, faceMap_r);
834 }
835
836 static void ccgDM_drawVerts(DerivedMesh *dm) {
837         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
838         CCGSubSurf *ss = ccgdm->ss;
839         int edgeSize = ccgSubSurf_getEdgeSize(ss);
840         int gridSize = ccgSubSurf_getGridSize(ss);
841         CCGVertIterator *vi;
842         CCGEdgeIterator *ei;
843         CCGFaceIterator *fi;
844
845         glBegin(GL_POINTS);
846         vi = ccgSubSurf_getVertIterator(ss);
847         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
848                 CCGVert *v = ccgVertIterator_getCurrent(vi);
849                 glVertex3fv(ccgSubSurf_getVertData(ss, v));
850         }
851         ccgVertIterator_free(vi);
852
853         ei = ccgSubSurf_getEdgeIterator(ss);
854         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
855                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
856                 int x;
857
858                 for (x=1; x<edgeSize-1; x++)
859                         glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
860         }
861         ccgEdgeIterator_free(ei);
862
863         fi = ccgSubSurf_getFaceIterator(ss);
864         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
865                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
866                 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
867
868                 glVertex3fv(ccgSubSurf_getFaceCenterData(ss, f));
869                 for (S=0; S<numVerts; S++)
870                         for (x=1; x<gridSize-1; x++)
871                                 glVertex3fv(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
872                 for (S=0; S<numVerts; S++)
873                         for (y=1; y<gridSize-1; y++)
874                                 for (x=1; x<gridSize-1; x++)
875                                         glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
876         }
877         ccgFaceIterator_free(fi);
878         glEnd();
879 }
880 static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
881         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
882         CCGSubSurf *ss = ccgdm->ss;
883         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
884         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
885         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
886         int gridSize = ccgSubSurf_getGridSize(ss);
887         int useAging;
888
889         ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
890
891         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
892                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
893                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
894
895                 if (ccgdm->fromEditmesh) {
896                         EditEdge *eed = ccgDM_getEdgeHandle(ccgdm, e);
897                         if (eed && eed->h!=0)
898                                 continue;
899                 }
900                 if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(ss, e))
901                         continue;
902
903                 if (useAging && !(G.f&G_BACKBUFSEL)) {
904                         int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
905                         glColor3ub(0, ageCol>0?ageCol:0, 0);
906                 }
907
908                 glBegin(GL_LINE_STRIP);
909                 for (i=0; i<edgeSize-1; i++) {
910                         glVertex3fv(edgeData[i].co);
911                         glVertex3fv(edgeData[i+1].co);
912                 }
913                 glEnd();
914         }
915
916         if (useAging && !(G.f&G_BACKBUFSEL)) {
917                 glColor3ub(0, 0, 0);
918         }
919
920         if (ccgdm->drawInteriorEdges) {
921                 for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
922                         CCGFace *f = ccgFaceIterator_getCurrent(fi);
923                         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
924
925                         if (ccgdm->fromEditmesh) {
926                                 EditFace *efa = ccgDM_getFaceHandle(ccgdm, f);
927                                 if (efa && efa->h!=0)
928                                         continue;
929                         }
930
931                         for (S=0; S<numVerts; S++) {
932                                 VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
933
934                                 glBegin(GL_LINE_STRIP);
935                                 for (x=0; x<gridSize; x++)
936                                         glVertex3fv(faceGridData[x].co);
937                                 glEnd();
938                                 for (y=1; y<gridSize-1; y++) {
939                                         glBegin(GL_LINE_STRIP);
940                                         for (x=0; x<gridSize; x++)
941                                                 glVertex3fv(faceGridData[y*gridSize + x].co);
942                                         glEnd();
943                                 }
944                                 for (x=1; x<gridSize-1; x++) {
945                                         glBegin(GL_LINE_STRIP);
946                                         for (y=0; y<gridSize; y++)
947                                                 glVertex3fv(faceGridData[y*gridSize + x].co);
948                                         glEnd();
949                                 }
950                         }
951                 }
952         }
953
954         ccgFaceIterator_free(fi);
955         ccgEdgeIterator_free(ei);
956 }
957 static void ccgDM_drawEdgesFlag(DerivedMesh *dm, unsigned int mask, unsigned int value) {
958         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
959         CCGSubSurf *ss = ccgdm->ss;
960         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
961         int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
962         MEdge *medge = NULL;
963         TFace *tface = NULL;
964
965         if (!ccgdm->fromEditmesh) {
966                 medge = ccgdm->dlm?ccgdm->dlm->medge:ccgdm->me->medge;
967                 tface = ccgdm->dlm?ccgdm->dlm->tface:ccgdm->me->tface;
968         }
969
970         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
971                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
972                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
973                 unsigned int flags = ss_getEdgeFlags(ss, e, ccgdm->fromEditmesh, medge, tface);
974
975                 if ((flags&mask)==value) {
976                         glBegin(GL_LINE_STRIP);
977                         for (i=0; i<edgeSize-1; i++) {
978                                 glVertex3fv(edgeData[i].co);
979                                 glVertex3fv(edgeData[i+1].co);
980                         }
981                         glEnd();
982                 }
983         }
984
985         ccgEdgeIterator_free(ei);
986 }
987 static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
988         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
989         CCGSubSurf *ss = ccgdm->ss;
990         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
991         int gridSize = ccgSubSurf_getGridSize(ss);
992
993         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
994                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
995                 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
996                 unsigned char flag,mat_nr;
997
998                 if (ccgdm->fromEditmesh || ccgdm->vertMap) {
999                         EditFace *efa = ccgDM_getFaceHandle(ccgdm, f);
1000                         if (efa && efa->h!=0)
1001                                 continue;
1002
1003                         flag = efa->flag;
1004                         mat_nr = efa->mat_nr;
1005                 } else {
1006                         int index = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
1007                         MFace *mf = (ccgdm->dlm?ccgdm->dlm->mface:ccgdm->me->mface) + index;
1008                         flag = mf->flag;
1009                         mat_nr = mf->mat_nr;
1010                 }
1011
1012                 if (!setMaterial(mat_nr+1))
1013                         continue;
1014
1015                 glShadeModel((flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT);
1016                 for (S=0; S<numVerts; S++) {
1017                         VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1018
1019                         if (flag&ME_SMOOTH) {
1020                                 for (y=0; y<gridSize-1; y++) {
1021                                         glBegin(GL_QUAD_STRIP);
1022                                         for (x=0; x<gridSize; x++) {
1023                                                 VertData *a = &faceGridData[(y+0)*gridSize + x];
1024                                                 VertData *b = &faceGridData[(y+1)*gridSize + x];
1025
1026                                                 glNormal3fv(a->no);
1027                                                 glVertex3fv(a->co);
1028                                                 glNormal3fv(b->no);
1029                                                 glVertex3fv(b->co);
1030                                         }
1031                                         glEnd();
1032                                 }
1033                         } else {
1034                                 glBegin(GL_QUADS);
1035                                 for (y=0; y<gridSize-1; y++) {
1036                                         for (x=0; x<gridSize-1; x++) {
1037                                                 float *a = faceGridData[(y+0)*gridSize + x].co;
1038                                                 float *b = faceGridData[(y+0)*gridSize + x + 1].co;
1039                                                 float *c = faceGridData[(y+1)*gridSize + x + 1].co;
1040                                                 float *d = faceGridData[(y+1)*gridSize + x].co;
1041                                                 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
1042                                                 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
1043                                                 float no[3];
1044
1045                                                 no[0] = b_dY*a_cZ - b_dZ*a_cY;
1046                                                 no[1] = b_dZ*a_cX - b_dX*a_cZ;
1047                                                 no[2] = b_dX*a_cY - b_dY*a_cX;
1048                                                 glNormal3fv(no);
1049
1050                                                 glVertex3fv(d);
1051                                                 glVertex3fv(c);
1052                                                 glVertex3fv(b);
1053                                                 glVertex3fv(a);
1054                                         }
1055                                 }
1056                                 glEnd();
1057                         }
1058                 }
1059         }
1060
1061         ccgFaceIterator_free(fi);
1062 }
1063 static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
1064         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1065         CCGSubSurf *ss = ccgdm->ss;
1066         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1067         int gridSize = ccgSubSurf_getGridSize(ss);
1068         unsigned char *cp1, *cp2;
1069         int useTwoSide=1;
1070
1071         cp1= col1;
1072         if(col2) {
1073                 cp2= col2;
1074         } else {
1075                 cp2= NULL;
1076                 useTwoSide= 0;
1077         }
1078
1079         glShadeModel(GL_SMOOTH);
1080         if(col1 && col2)
1081                 glEnable(GL_CULL_FACE);
1082
1083         glBegin(GL_QUADS);
1084         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1085                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1086                 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
1087
1088                 for (S=0; S<numVerts; S++) {
1089                         VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1090                         for (y=0; y<gridSize-1; y++) {
1091                                 for (x=0; x<gridSize-1; x++) {
1092                                         float *a = faceGridData[(y+0)*gridSize + x].co;
1093                                         float *b = faceGridData[(y+0)*gridSize + x + 1].co;
1094                                         float *c = faceGridData[(y+1)*gridSize + x + 1].co;
1095                                         float *d = faceGridData[(y+1)*gridSize + x].co;
1096
1097                                         glColor3ub(cp1[3], cp1[2], cp1[1]);
1098                                         glVertex3fv(d);
1099                                         glColor3ub(cp1[7], cp1[6], cp1[5]);
1100                                         glVertex3fv(c);
1101                                         glColor3ub(cp1[11], cp1[10], cp1[9]);
1102                                         glVertex3fv(b);
1103                                         glColor3ub(cp1[15], cp1[14], cp1[13]);
1104                                         glVertex3fv(a);
1105
1106                                         if (useTwoSide) {
1107                                                 glColor3ub(cp2[15], cp2[14], cp2[13]);
1108                                                 glVertex3fv(a);
1109                                                 glColor3ub(cp2[11], cp2[10], cp2[9]);
1110                                                 glVertex3fv(b);
1111                                                 glColor3ub(cp2[7], cp2[6], cp2[5]);
1112                                                 glVertex3fv(c);
1113                                                 glColor3ub(cp2[3], cp2[2], cp2[1]);
1114                                                 glVertex3fv(d);
1115                                         }
1116
1117                                         if (cp2) cp2+=16;
1118                                         cp1+=16;
1119                                 }
1120                         }
1121                 }
1122         }
1123         glEnd();
1124
1125         ccgFaceIterator_free(fi);
1126 }
1127 static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) {
1128         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1129         CCGSubSurf *ss = ccgdm->ss;
1130         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1131         int gridSize = ccgSubSurf_getGridSize(ss);
1132         MFace *mface = ccgdm->dlm?ccgdm->dlm->mface:ccgdm->me->mface;
1133         TFace *tface = ccgdm->dlm?ccgdm->dlm->tface:ccgdm->me->tface;
1134         MCol *mcol = ccgdm->dlm?ccgdm->dlm->mcol:ccgdm->me->mcol;
1135 //      float uv[4][2];
1136 //      float col[4][3];
1137
1138         glBegin(GL_QUADS);
1139         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1140                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1141                 int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
1142                 int index = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
1143                 MFace *mf = &mface[index];
1144                 TFace *tf = tface?&tface[index]:NULL;
1145                 unsigned char *cp= NULL;
1146                 int flag = setDrawParams(tf, mf->mat_nr);
1147
1148                 if (flag==0) {
1149                         continue;
1150                 } else if (flag==1) {
1151                         if (tf) {
1152                                 cp= (unsigned char*) tf->col;
1153                         } else if (mcol) {
1154                                 cp= (unsigned char*) &mcol[index*4];
1155                         }
1156                 }
1157
1158                 for (S=0; S<numVerts; S++) {
1159                         VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1160                         for (y=0; y<gridSize-1; y++) {
1161                                 for (x=0; x<gridSize-1; x++) {
1162                                         VertData *a = &faceGridData[(y+0)*gridSize + x];
1163                                         VertData *b = &faceGridData[(y+0)*gridSize + x + 1];
1164                                         VertData *c = &faceGridData[(y+1)*gridSize + x + 1];
1165                                         VertData *d = &faceGridData[(y+1)*gridSize + x];
1166
1167                                         if (!(mf->flag&ME_SMOOTH)) {
1168                                                 float a_cX = c->co[0]-a->co[0], a_cY = c->co[1]-a->co[1], a_cZ = c->co[2]-a->co[2];
1169                                                 float b_dX = d->co[0]-b->co[0], b_dY = d->co[1]-b->co[1], b_dZ = d->co[2]-b->co[2];
1170                                                 float no[3];
1171
1172                                                 no[0] = b_dY*a_cZ - b_dZ*a_cY;
1173                                                 no[1] = b_dZ*a_cX - b_dX*a_cZ;
1174                                                 no[2] = b_dX*a_cY - b_dY*a_cX;
1175
1176                                                 glNormal3fv(no);
1177                                         }
1178
1179 //                                      if (tf) glTexCoord2fv(tf->uv[0]);
1180 //                                      if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1181 //                                      if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
1182 //                                      glVertex3fv(mvert[mf->v1].co);
1183
1184 /*
1185                                         {
1186                                                 float x_v = (float) fx/(gridSize-1);
1187                                                 float y_v = (float) fy/(gridSize-1);
1188                                                 float data[6];
1189
1190                                                 for (k=0; k<numDataComponents; k++) {
1191                                                         data[k] = (center_data[k]*(1.0f-x_v) + edge_data[S][k]*x_v)*(1.0f-y_v) + 
1192                                                                         (edge_data[prevS][k]*(1.0f-x_v) + corner_data[S][k]*x_v)*y_v;
1193                                         }
1194 */
1195
1196 //                                      if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1197                                         if (mf->flag&ME_SMOOTH) glNormal3fv(d->no);
1198                                         glVertex3fv(d->co);
1199 //                                      if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1200                                         if (mf->flag&ME_SMOOTH) glNormal3fv(c->no);
1201                                         glVertex3fv(c->co);
1202 //                                      if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1203                                         if (mf->flag&ME_SMOOTH) glNormal3fv(b->no);
1204                                         glVertex3fv(b->co);
1205 //                                      if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1206                                         if (mf->flag&ME_SMOOTH) glNormal3fv(a->no);
1207                                         glVertex3fv(a->co);
1208                                 }
1209                         }
1210                 }
1211         }
1212         glEnd();
1213
1214         ccgFaceIterator_free(fi);
1215 /*
1216         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
1217         Mesh *me = mdm->me;
1218         MVert *mvert= mdm->verts;
1219         MFace *mface= me->mface;
1220         TFace *tface = me->tface;
1221         float *nors = mdm->nors;
1222         int a;
1223
1224         for (a=0; a<me->totface; a++) {
1225                 MFace *mf= &mface[a];
1226                 if (tf) glTexCoord2fv(tf->uv[1]);
1227                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1228                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
1229                 glVertex3fv(mvert[mf->v2].co);
1230
1231                 if (tf) glTexCoord2fv(tf->uv[2]);
1232                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1233                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
1234                 glVertex3fv(mvert[mf->v3].co);
1235
1236                 if(mf->v4) {
1237                         if (tf) glTexCoord2fv(tf->uv[3]);
1238                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1239                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
1240                         glVertex3fv(mvert[mf->v4].co);
1241                 }
1242                 glEnd();
1243         }
1244 */
1245 }
1246
1247 static void ccgDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void *userData) {
1248         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1249         CCGSubSurf *ss = ccgdm->ss;
1250         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
1251         int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
1252
1253         ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
1254
1255         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1256                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1257                 EditEdge *edge = ccgDM_getEdgeHandle(ccgdm, e);
1258                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
1259
1260                 glBegin(GL_LINE_STRIP);
1261                 if (edge && (!setDrawOptions || setDrawOptions(userData, edge))) {
1262                         if (useAging && !(G.f&G_BACKBUFSEL)) {
1263                                 int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
1264                                 glColor3ub(0, ageCol>0?ageCol:0, 0);
1265                         }
1266
1267                         for (i=0; i<edgeSize-1; i++) {
1268                                 glVertex3fv(edgeData[i].co);
1269                                 glVertex3fv(edgeData[i+1].co);
1270                         }
1271                 }
1272                 glEnd();
1273         }
1274
1275         ccgEdgeIterator_free(ei);
1276 }
1277 static void ccgDM_drawMappedEdgesInterpEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void (*setDrawInterpOptions)(void *userData, EditEdge *edge, float t), void *userData) {
1278         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1279         CCGSubSurf *ss = ccgdm->ss;
1280         CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
1281         int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
1282
1283         ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
1284
1285         for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
1286                 CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
1287                 EditEdge *edge = ccgDM_getEdgeHandle(ccgdm, e);
1288                 VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
1289
1290                 glBegin(GL_LINE_STRIP);
1291                 if (edge && (!setDrawOptions || setDrawOptions(userData, edge))) {
1292                         for (i=0; i<edgeSize; i++) {
1293                                 setDrawInterpOptions(userData, edge, (float) i/(edgeSize-1));
1294
1295                                 if (useAging && !(G.f&G_BACKBUFSEL)) {
1296                                         int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
1297                                         glColor3ub(0, ageCol>0?ageCol:0, 0);
1298                                 }
1299
1300                                 glVertex3fv(edgeData[i].co);
1301                         }
1302                 }
1303                 glEnd();
1304         }
1305 }
1306 static void ccgDM_drawMappedFacesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditFace *face), void *userData) {
1307         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1308         CCGSubSurf *ss = ccgdm->ss;
1309         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1310         int gridSize = ccgSubSurf_getGridSize(ss);
1311
1312         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1313                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1314                 EditFace *efa = ccgDM_getFaceHandle(ccgdm, f);
1315                 if (efa && (!setDrawOptions || setDrawOptions(userData, efa))) {
1316                         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
1317
1318                         for (S=0; S<numVerts; S++) {
1319                                 VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
1320
1321                                 for (y=0; y<gridSize-1; y++) {
1322                                         glBegin(GL_QUAD_STRIP);
1323                                         for (x=0; x<gridSize; x++) {
1324                                                 glVertex3fv(faceGridData[(y+0)*gridSize + x].co);
1325                                                 glVertex3fv(faceGridData[(y+1)*gridSize + x].co);
1326                                         }
1327                                         glEnd();
1328                                 }
1329                         }
1330                 }
1331         }
1332
1333         ccgFaceIterator_free(fi);
1334 }
1335 static void ccgDM_foreachMappedFaceCenterEM(DerivedMesh *dm, void (*func)(void *userData, EditFace *efa, float *co, float *no), void *userData) {
1336         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1337         CCGSubSurf *ss = ccgdm->ss;
1338         CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
1339
1340         for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
1341                 CCGFace *f = ccgFaceIterator_getCurrent(fi);
1342                 EditFace *efa = ccgDM_getFaceHandle(ccgdm, f);
1343
1344                 if (efa) {
1345                                 /* Face center data normal isn't updated atm. */
1346                         VertData *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
1347
1348                         func(userData, efa, vd->co, vd->no);
1349                 }
1350         }
1351
1352         ccgFaceIterator_free(fi);
1353 }
1354
1355 static void ccgDM_release(DerivedMesh *dm) {
1356         CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
1357
1358         if (ccgdm->dlm) displistmesh_free(ccgdm->dlm);
1359         if (ccgdm->vertMap) {
1360                 MEM_freeN(ccgdm->vertMap);
1361                 MEM_freeN(ccgdm->edgeMap);
1362                 MEM_freeN(ccgdm->faceMap);
1363         }
1364
1365         MEM_freeN(ccgdm);
1366 }
1367
1368 static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int drawInteriorEdges, Mesh *me, DispListMesh *dlm, EditVert **vertMap, EditEdge **edgeMap, EditFace **faceMap) {
1369         CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
1370
1371         ccgdm->dm.getMinMax = ccgDM_getMinMax;
1372         ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
1373         ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
1374         ccgdm->dm.getVertCos = ccgdm_getVertCos;
1375         ccgdm->dm.foreachMappedVertEM = ccgDM_foreachMappedVertEM;
1376         ccgdm->dm.foreachMappedEdgeEM = ccgDM_foreachMappedEdgeEM;
1377         ccgdm->dm.foreachMappedFaceCenterEM = ccgDM_foreachMappedFaceCenterEM;
1378         ccgdm->dm.convertToDispListMesh = ccgDM_convertToDispListMesh;
1379         ccgdm->dm.convertToDispListMeshMapped = ccgDM_convertToDispListMeshMapped;
1380
1381         ccgdm->dm.drawVerts = ccgDM_drawVerts;
1382         ccgdm->dm.drawEdges = ccgDM_drawEdges;
1383         ccgdm->dm.drawEdgesFlag = ccgDM_drawEdgesFlag;
1384         ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
1385         ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
1386         ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
1387
1388         ccgdm->dm.drawMappedEdgesInterpEM = ccgDM_drawMappedEdgesInterpEM;
1389         ccgdm->dm.drawMappedEdgesEM = ccgDM_drawMappedEdgesEM;
1390         ccgdm->dm.drawMappedFacesEM = ccgDM_drawMappedFacesEM;
1391
1392         ccgdm->dm.release = ccgDM_release;
1393         
1394         ccgdm->ss = ss;
1395         ccgdm->fromEditmesh = fromEditmesh;
1396         ccgdm->drawInteriorEdges = drawInteriorEdges;
1397         ccgdm->me = me;
1398         ccgdm->dlm = dlm;
1399         ccgdm->vertMap = vertMap;
1400         ccgdm->edgeMap = edgeMap;
1401         ccgdm->faceMap = faceMap;
1402
1403         return ccgdm;
1404 }
1405
1406 /***/
1407
1408 DerivedMesh *subsurf_make_derived_from_editmesh(EditMesh *em, SubsurfModifierData *smd, float (*vertCos)[3]) {
1409         int useSimple = smd->subdivType==ME_SIMPLE_SUBSURF;
1410         int useAging = smd->flags&eSubsurfModifierFlag_DebugIncr;
1411         int drawInteriorEdges = !(smd->flags&eSubsurfModifierFlag_ControlEdges);
1412
1413         smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, 0, useSimple);
1414         ss_sync_from_editmesh(smd->emCache, em, vertCos, useSimple);
1415
1416         return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 1, drawInteriorEdges, NULL, NULL, NULL, NULL, NULL);
1417 }
1418
1419 DerivedMesh *subsurf_make_derived_from_dlm_em(DispListMesh *dlm, SubsurfModifierData *smd, float (*vertCos)[3], EditVert **vertMap, EditEdge **edgeMap, EditFace **faceMap) {
1420         int useSimple = smd->subdivType==ME_SIMPLE_SUBSURF;
1421         int useAging = smd->flags&eSubsurfModifierFlag_DebugIncr;
1422         int drawInteriorEdges = !(smd->flags&eSubsurfModifierFlag_ControlEdges);
1423                 
1424         smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, 0, useSimple);
1425
1426         ss_sync_from_mesh(smd->emCache, NULL, dlm, vertCos, useSimple);
1427
1428         return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 0, drawInteriorEdges, NULL, dlm, vertMap, edgeMap, faceMap);
1429 }
1430
1431 DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, SubsurfModifierData *smd, int useRenderParams, float (*vertCos)[3], int isFinalCalc) {
1432         int useSimple = smd->subdivType==ME_SIMPLE_SUBSURF;
1433         int drawInteriorEdges = !(smd->flags&eSubsurfModifierFlag_ControlEdges);
1434         DispListMesh *ndlm;
1435
1436                 /* Do not use cache in render mode. */
1437         if (useRenderParams) {
1438                 CCGSubSurf *ss = _getSubSurf(NULL, smd->renderLevels, 0, 1, 1, useSimple);
1439
1440                 ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
1441
1442                 ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, me, dlm, NULL, NULL, NULL);
1443                 if (dlm) displistmesh_free(dlm);
1444
1445                 ccgSubSurf_free(ss);
1446                 
1447                 return derivedmesh_from_displistmesh(ndlm, NULL, NULL, NULL, NULL);
1448         } else {
1449                 int useEdgeCreation = !(dlm?dlm->medge:me->medge);
1450                 int useIncremental = (smd->flags&eSubsurfModifierFlag_Incremental) && !useEdgeCreation;
1451                 int useAging = smd->flags&eSubsurfModifierFlag_DebugIncr;
1452                 CCGSubSurf *ss;
1453                 
1454                         /* It is quite possible there is a much better place to do this. It
1455                          * depends a bit on how rigourously we expect this function to never
1456                          * be called in editmode. In semi-theory we could share a single
1457                          * cache, but the handles used inside and outside editmode are not
1458                          * the same so we would need some way of converting them. Its probably
1459                          * not worth the effort. But then why am I even writing this long
1460                          * comment that no one will read? Hmmm. - zr
1461                          */
1462                 if (smd->emCache) {
1463                         ccgSubSurf_free(smd->emCache);
1464                         smd->emCache = NULL;
1465                 }
1466
1467                 if (useIncremental && isFinalCalc) {
1468                         smd->mCache = ss = _getSubSurf(smd->mCache, smd->levels, useAging, 0, 0, useSimple);
1469
1470                         ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
1471
1472                         return (DerivedMesh*) getCCGDerivedMesh(ss, 0, drawInteriorEdges, me, dlm, NULL, NULL, NULL);
1473                 } else {
1474                         if (smd->mCache && isFinalCalc) {
1475                                 ccgSubSurf_free(smd->mCache);
1476                                 smd->mCache = NULL;
1477                         }
1478
1479                         ss = _getSubSurf(NULL, smd->levels, 0, 1, useEdgeCreation, useSimple);
1480                         ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
1481
1482                         ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, me, dlm, NULL, NULL, NULL);
1483
1484                         if (dlm) displistmesh_free(dlm);
1485                         ccgSubSurf_free(ss);
1486
1487                         return derivedmesh_from_displistmesh(ndlm, NULL, NULL, NULL, NULL);
1488                 }
1489         }
1490 }
1491
1492 void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) 
1493 {
1494                 /* Finds the subsurf limit positions for the verts in a mesh 
1495                  * and puts them in an array of floats. Please note that the 
1496                  * calculated vert positions is incorrect for the verts 
1497                  * on the boundary of the mesh.
1498                  */
1499         CCGSubSurf *ss = _getSubSurf(NULL, 1, 0, 1, 0, 0);
1500         float edge_sum[3], face_sum[3];
1501         CCGVertIterator *vi;
1502
1503         ss_sync_from_mesh(ss, me, NULL, NULL, 0);
1504
1505         vi = ccgSubSurf_getVertIterator(ss);
1506         for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
1507                 CCGVert *v = ccgVertIterator_getCurrent(vi);
1508                 int idx = (int) ccgSubSurf_getVertVertHandle(ss, v);
1509                 int N = ccgSubSurf_getVertNumEdges(ss, v);
1510                 int numFaces = ccgSubSurf_getVertNumFaces(ss, v);
1511                 float *co;
1512                 int i;
1513                 
1514                 edge_sum[0]= edge_sum[1]= edge_sum[2]= 0.0;
1515                 face_sum[0]= face_sum[1]= face_sum[2]= 0.0;
1516
1517                 for (i=0; i<N; i++) {
1518                         CCGEdge *e = ccgSubSurf_getVertEdge(ss, v, i);
1519                         VecAddf(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss, e, 1));
1520                 }
1521                 for (i=0; i<numFaces; i++) {
1522                         CCGFace *f = ccgSubSurf_getVertFace(ss, v, i);
1523                         VecAddf(face_sum, face_sum, ccgSubSurf_getFaceCenterData(ss, f));
1524                 }
1525
1526                 co = ccgSubSurf_getVertData(ss, v);
1527                 positions_r[idx][0] = (co[0]*N*N + edge_sum[0]*4 + face_sum[0])/(N*(N+5));
1528                 positions_r[idx][1] = (co[1]*N*N + edge_sum[1]*4 + face_sum[1])/(N*(N+5));
1529                 positions_r[idx][2] = (co[2]*N*N + edge_sum[2]*4 + face_sum[2])/(N*(N+5));
1530         }
1531         ccgVertIterator_free(vi);
1532
1533         ccgSubSurf_free(ss);
1534 }
1535