merge with/from trunk at r35190
[blender.git] / source / blender / blenkernel / intern / cdderivedmesh.c
1  /*
2 * $Id$
3 *
4 * ***** BEGIN GPL 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.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2006 Blender Foundation.
21 * All rights reserved.
22 *
23 * The Original Code is: all of this file.
24 *
25 * Contributor(s): Ben Batt <benbatt@gmail.com>
26 *
27 * ***** END GPL LICENSE BLOCK *****
28 *
29 * Implementation of CDDerivedMesh.
30 *
31 * BKE_cdderivedmesh.h contains the function prototypes for this file.
32 *
33 */ 
34
35 /* TODO maybe BIF_gl.h should include string.h? */
36 #include <string.h>
37 #include "BIF_gl.h"
38
39 #include "BKE_cdderivedmesh.h"
40 #include "BKE_global.h"
41 #include "BKE_mesh.h"
42 #include "BKE_paint.h"
43 #include "BKE_utildefines.h"
44 #include "BKE_tessmesh.h"
45
46 #include "BLI_editVert.h"
47 #include "BLI_scanfill.h"
48 #include "BLI_math.h"
49 #include "BLI_blenlib.h"
50 #include "BLI_edgehash.h"
51 #include "BLI_editVert.h"
52 #include "BLI_math.h"
53 #include "BLI_pbvh.h"
54 #include "BLI_array.h"
55 #include "BLI_smallhash.h"
56 #include "BLI_utildefines.h"
57
58 #include "BKE_cdderivedmesh.h"
59 #include "BKE_global.h"
60 #include "BKE_mesh.h"
61 #include "BKE_paint.h"
62
63
64 #include "DNA_meshdata_types.h"
65 #include "DNA_object_types.h"
66 #include "DNA_curve_types.h" /* for Curve */
67
68 #include "MEM_guardedalloc.h"
69
70 #include "GPU_buffers.h"
71 #include "GPU_draw.h"
72 #include "GPU_extensions.h"
73 #include "GPU_material.h"
74
75 #include <string.h>
76 #include <limits.h>
77 #include <math.h>
78
79 typedef struct {
80         DerivedMesh dm;
81
82         /* these point to data in the DerivedMesh custom data layers,
83            they are only here for efficiency and convenience **/
84         MVert *mvert;
85         MEdge *medge;
86         MFace *mface;
87         MLoop *mloop;
88         MPoly *mpoly;
89
90         /* Cached */
91         struct PBVH *pbvh;
92         int pbvh_draw;
93
94         /* Mesh connectivity */
95         struct ListBase *fmap;
96         struct IndexNode *fmap_mem;
97 } CDDerivedMesh;
98
99 DMFaceIter *cdDM_newFaceIter(DerivedMesh *source);
100
101 /**************** DerivedMesh interface functions ****************/
102 static int cdDM_getNumVerts(DerivedMesh *dm)
103 {
104         return dm->numVertData;
105 }
106
107 static int cdDM_getNumEdges(DerivedMesh *dm)
108 {
109         return dm->numEdgeData;
110 }
111
112 static int cdDM_getNumTessFaces(DerivedMesh *dm)
113 {
114         return dm->numFaceData;
115 }
116
117 static int cdDM_getNumFaces(DerivedMesh *dm)
118 {
119         return dm->numPolyData;
120 }
121
122 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
123 {
124         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
125         *vert_r = cddm->mvert[index];
126 }
127
128 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
129 {
130         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
131         *edge_r = cddm->medge[index];
132 }
133
134 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
135 {
136         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
137         *face_r = cddm->mface[index];
138 }
139
140 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
141 {
142         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
143         memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
144 }
145
146 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
147 {
148         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
149         memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
150 }
151
152 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
153 {
154         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
155         memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
156 }
157
158 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
159 {
160         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
161         int i;
162
163         if (dm->numVertData) {
164                 for (i=0; i<dm->numVertData; i++) {
165                         DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
166                 }
167         } else {
168                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
169         }
170 }
171
172 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
173 {
174         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
175
176         VECCOPY(co_r, cddm->mvert[index].co);
177 }
178
179 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
180 {
181         MVert *mv = CDDM_get_verts(dm);
182         int i;
183
184         for(i = 0; i < dm->numVertData; i++, mv++)
185                 VECCOPY(cos_r[i], mv->co);
186 }
187
188 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
189 {
190         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
191         short *no = cddm->mvert[index].no;
192
193         no_r[0] = no[0]/32767.f;
194         no_r[1] = no[1]/32767.f;
195         no_r[2] = no[2]/32767.f;
196 }
197
198 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
199 {
200         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
201
202         if(!cddm->fmap && ob->type == OB_MESH) {
203                 Mesh *me= ob->data;
204
205                 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
206                                          me->totvert, me->totface);
207         }
208
209         return cddm->fmap;
210 }
211
212 static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
213 {
214         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
215         Mesh *me= ob->data;
216
217         if(ob->sculpt->modifiers_active) return 0;
218
219         return (cddm->mvert == me->mvert) || ob->sculpt->kb;
220 }
221
222 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
223 {
224         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
225
226         if(!ob) {
227                 cddm->pbvh= NULL;
228                 return NULL;
229         }
230
231         if(!ob->sculpt)
232                 return NULL;
233         if(ob->sculpt->pbvh) {
234                 cddm->pbvh= ob->sculpt->pbvh;
235                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
236         }
237
238         /* always build pbvh from original mesh, and only use it for drawing if
239            this derivedmesh is just original mesh. it's the multires subsurf dm
240            that this is actually for, to support a pbvh on a modified mesh */
241         if(!cddm->pbvh && ob->type == OB_MESH) {
242                 Mesh *me= ob->data;
243                 cddm->pbvh = BLI_pbvh_new();
244                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
245                 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
246                                    me->totface, me->totvert);
247
248                 if(ob->sculpt->modifiers_active) {
249                         float (*vertCos)[3];
250                         int totvert;
251
252                         totvert= dm->getNumVerts(dm);
253                         vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
254                         dm->getVertCos(dm, vertCos);
255                         BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
256                         MEM_freeN(vertCos);
257                 }
258         }
259
260         return cddm->pbvh;
261 }
262
263 /* update vertex normals so that drawing smooth faces works during sculpt
264    TODO: proper fix is to support the pbvh in all drawing modes */
265 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
266 {
267         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
268         float (*face_nors)[3];
269
270         if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
271                 return;
272
273         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
274
275         BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
276 }
277
278 static void cdDM_drawVerts(DerivedMesh *dm)
279 {
280         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
281         MVert *mv = cddm->mvert;
282         int i;
283
284         if( GPU_buffer_legacy(dm) ) {
285                 glBegin(GL_POINTS);
286                 for(i = 0; i < dm->numVertData; i++, mv++)
287                         glVertex3fv(mv->co);
288                 glEnd();
289         }
290         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
291                 GPU_vertex_setup(dm);
292                 if( !GPU_buffer_legacy(dm) ) {
293                         if(dm->drawObject->nelements)   glDrawArrays(GL_POINTS,0, dm->drawObject->nelements);
294                         else                                                    glDrawArrays(GL_POINTS,0, dm->drawObject->nlooseverts);
295                 }
296                 GPU_buffer_unbind();
297         }
298 }
299
300 static void cdDM_drawUVEdges(DerivedMesh *dm)
301 {
302         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
303         MFace *mf = cddm->mface;
304         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
305         int i;
306
307         if(mf) {
308                 if( GPU_buffer_legacy(dm) ) {
309                         glBegin(GL_LINES);
310                         for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
311                                 if(!(mf->flag&ME_HIDE)) {
312                                         glVertex2fv(tf->uv[0]);
313                                         glVertex2fv(tf->uv[1]);
314
315                                         glVertex2fv(tf->uv[1]);
316                                         glVertex2fv(tf->uv[2]);
317
318                                         if(!mf->v4) {
319                                                 glVertex2fv(tf->uv[2]);
320                                                 glVertex2fv(tf->uv[0]);
321                                         } else {
322                                                 glVertex2fv(tf->uv[2]);
323                                                 glVertex2fv(tf->uv[3]);
324
325                                                 glVertex2fv(tf->uv[3]);
326                                                 glVertex2fv(tf->uv[0]);
327                                         }
328                                 }
329                         }
330                         glEnd();
331                 }
332                 else {
333                         int prevstart = 0;
334                         int prevdraw = 1;
335                         int draw = 1;
336                         int curpos = 0;
337
338                         GPU_uvedge_setup(dm);
339                         if( !GPU_buffer_legacy(dm) ) {
340                                 for(i = 0; i < dm->numFaceData; i++, mf++) {
341                                         if(!(mf->flag&ME_HIDE)) {
342                                                 draw = 1;
343                                         } 
344                                         else {
345                                                 draw = 0;
346                                         }
347                                         if( prevdraw != draw ) {
348                                                 if( prevdraw > 0 && (curpos-prevstart) > 0) {
349                                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
350                                                 }
351                                                 prevstart = curpos;
352                                         }
353                                         if( mf->v4 ) {
354                                                 curpos += 8;
355                                         }
356                                         else {
357                                                 curpos += 6;
358                                         }
359                                         prevdraw = draw;
360                                 }
361                                 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
362                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
363                                 }
364                         }
365                         GPU_buffer_unbind();
366                 }
367         }
368 }
369
370 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges)
371 {
372         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
373         MVert *mvert = cddm->mvert;
374         MEdge *medge = cddm->medge;
375         int i;
376         
377         if( GPU_buffer_legacy(dm) ) {
378                 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
379                 glBegin(GL_LINES);
380                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
381                         if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
382                            && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
383                                 glVertex3fv(mvert[medge->v1].co);
384                                 glVertex3fv(mvert[medge->v2].co);
385                         }
386                 }
387                 glEnd();
388         }
389         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
390                 int prevstart = 0;
391                 int prevdraw = 1;
392                 int draw = 1;
393
394                 GPU_edge_setup(dm);
395                 if( !GPU_buffer_legacy(dm) ) {
396                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
397                                 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
398                                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
399                                         draw = 1;
400                                 } 
401                                 else {
402                                         draw = 0;
403                                 }
404                                 if( prevdraw != draw ) {
405                                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
406                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
407                                         }
408                                         prevstart = i;
409                                 }
410                                 prevdraw = draw;
411                         }
412                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
413                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
414                         }
415                 }
416                 GPU_buffer_unbind();
417         }
418 }
419
420 static void cdDM_drawLooseEdges(DerivedMesh *dm)
421 {
422         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
423         MVert *mvert = cddm->mvert;
424         MEdge *medge = cddm->medge;
425         int i;
426
427         if( GPU_buffer_legacy(dm) ) {
428                 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
429                 glBegin(GL_LINES);
430                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
431                         if(medge->flag&ME_LOOSEEDGE) {
432                                 glVertex3fv(mvert[medge->v1].co);
433                                 glVertex3fv(mvert[medge->v2].co);
434                         }
435                 }
436                 glEnd();
437         }
438         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
439                 int prevstart = 0;
440                 int prevdraw = 1;
441                 int draw = 1;
442
443                 GPU_edge_setup(dm);
444                 if( !GPU_buffer_legacy(dm) ) {
445                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
446                                 if(medge->flag&ME_LOOSEEDGE) {
447                                         draw = 1;
448                                 } 
449                                 else {
450                                         draw = 0;
451                                 }
452                                 if( prevdraw != draw ) {
453                                         if( prevdraw > 0 && (i-prevstart) > 0) {
454                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
455                                         }
456                                         prevstart = i;
457                                 }
458                                 prevdraw = draw;
459                         }
460                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
461                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
462                         }
463                 }
464                 GPU_buffer_unbind();
465         }
466 }
467
468 static void cdDM_drawFacesSolid(DerivedMesh *dm,
469                                 float (*partial_redraw_planes)[4],
470                                 int UNUSED(fast), int (*setMaterial)(int, void *attribs))
471 {
472         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
473         MVert *mvert = cddm->mvert;
474         MFace *mface = cddm->mface;
475         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
476         int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
477
478 #define PASSVERT(index) {                                               \
479         if(shademodel == GL_SMOOTH) {                           \
480                 short *no = mvert[index].no;                    \
481                 glNormal3sv(no);                                                \
482         }                                                                                       \
483         glVertex3fv(mvert[index].co);   \
484 }
485
486         if(cddm->pbvh && cddm->pbvh_draw) {
487                 if(dm->numFaceData) {
488                         float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
489
490                         /* should be per face */
491                         if(!setMaterial(mface->mat_nr+1, NULL))
492                                 return;
493
494                         glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
495                         BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH));
496                         glShadeModel(GL_FLAT);
497                 }
498
499                 return;
500         }
501
502         if( GPU_buffer_legacy(dm) ) {
503                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
504                 glBegin(glmode = GL_QUADS);
505                 for(a = 0; a < dm->numFaceData; a++, mface++) {
506                         int new_glmode, new_matnr, new_shademodel;
507
508                         new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
509                         new_matnr = mface->mat_nr + 1;
510                         new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
511                         
512                         if(new_glmode != glmode || new_matnr != matnr
513                            || new_shademodel != shademodel) {
514                                 glEnd();
515
516                                 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
517
518                                 glShadeModel(shademodel = new_shademodel);
519                                 glBegin(glmode = new_glmode);
520                         } 
521                         
522                         if(drawCurrentMat) {
523                                 if(shademodel == GL_FLAT) {
524                                         if (nors) {
525                                                 glNormal3fv(nors);
526                                         }
527                                         else {
528                                                 /* TODO make this better (cache facenormals as layer?) */
529                                                 float nor[3];
530                                                 if(mface->v4) {
531                                                         normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
532                                                 } else {
533                                                         normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
534                                                 }
535                                                 glNormal3fv(nor);
536                                         }
537                                 }
538
539                                 PASSVERT(mface->v1);
540                                 PASSVERT(mface->v2);
541                                 PASSVERT(mface->v3);
542                                 if(mface->v4) {
543                                         PASSVERT(mface->v4);
544                                 }
545                         }
546
547                         if(nors) nors += 3;
548                 }
549                 glEnd();
550         }
551         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
552                 GPU_vertex_setup( dm );
553                 GPU_normal_setup( dm );
554                 if( !GPU_buffer_legacy(dm) ) {
555                         glShadeModel(GL_SMOOTH);
556                         for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
557                                 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
558                                         glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
559                         }
560                 }
561                 GPU_buffer_unbind( );
562         }
563
564 #undef PASSVERT
565         glShadeModel(GL_FLAT);
566 }
567
568 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
569 {
570         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
571         int a, glmode;
572         unsigned char *cp1, *cp2;
573         MVert *mvert = cddm->mvert;
574         MFace *mface = cddm->mface;
575
576         cp1 = col1;
577         if(col2) {
578                 cp2 = col2;
579         } else {
580                 cp2 = NULL;
581                 useTwoSided = 0;
582         }
583
584         /* there's a conflict here... twosided colors versus culling...? */
585         /* defined by history, only texture faces have culling option */
586         /* we need that as mesh option builtin, next to double sided lighting */
587         if(col1 && col2)
588                 glEnable(GL_CULL_FACE);
589
590         cdDM_update_normals_from_pbvh(dm);
591
592         if( GPU_buffer_legacy(dm) ) {
593                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
594                 glShadeModel(GL_SMOOTH);
595                 glBegin(glmode = GL_QUADS);
596                 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
597                         int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
598
599                         if(new_glmode != glmode) {
600                                 glEnd();
601                                 glBegin(glmode = new_glmode);
602                         }
603                                 
604                         glColor3ub(cp1[0], cp1[1], cp1[2]);
605                         glVertex3fv(mvert[mface->v1].co);
606                         glColor3ub(cp1[4], cp1[5], cp1[6]);
607                         glVertex3fv(mvert[mface->v2].co);
608                         glColor3ub(cp1[8], cp1[9], cp1[10]);
609                         glVertex3fv(mvert[mface->v3].co);
610                         if(mface->v4) {
611                                 glColor3ub(cp1[12], cp1[13], cp1[14]);
612                                 glVertex3fv(mvert[mface->v4].co);
613                         }
614                                 
615                         if(useTwoSided) {
616                                 glColor3ub(cp2[8], cp2[9], cp2[10]);
617                                 glVertex3fv(mvert[mface->v3].co );
618                                 glColor3ub(cp2[4], cp2[5], cp2[6]);
619                                 glVertex3fv(mvert[mface->v2].co );
620                                 glColor3ub(cp2[0], cp2[1], cp2[2]);
621                                 glVertex3fv(mvert[mface->v1].co );
622                                 if(mface->v4) {
623                                         glColor3ub(cp2[12], cp2[13], cp2[14]);
624                                         glVertex3fv(mvert[mface->v4].co );
625                                 }
626                         }
627                         if(col2) cp2 += 16;
628                 }
629                 glEnd();
630         }
631         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
632                 GPU_color4_upload(dm,cp1);
633                 GPU_vertex_setup(dm);
634                 GPU_color_setup(dm);
635                 if( !GPU_buffer_legacy(dm) ) {
636                         glShadeModel(GL_SMOOTH);
637                         glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
638
639                         if( useTwoSided ) {
640                                 GPU_color4_upload(dm,cp2);
641                                 GPU_color_setup(dm);
642                                 glCullFace(GL_FRONT);
643                                 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
644                                 glCullFace(GL_BACK);
645                         }
646                 }
647                 GPU_buffer_unbind();
648         }
649
650         glShadeModel(GL_FLAT);
651         glDisable(GL_CULL_FACE);
652 }
653
654 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
655                int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
656                int (*drawParamsMapped)(void *userData, int index),
657                void *userData) 
658 {
659         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
660         MVert *mv = cddm->mvert;
661         MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
662         MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
663         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
664         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
665         int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
666         int startFace = 0, lastFlag = 0xdeadbeef;
667         MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
668         if(!mcol)
669                 mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
670
671         cdDM_update_normals_from_pbvh(dm);
672
673         if( GPU_buffer_legacy(dm) ) {
674                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
675                 for(i = 0; i < dm->numFaceData; i++, mf++) {
676                         MVert *mvert;
677                         int flag;
678                         unsigned char *cp = NULL;
679
680                         if(drawParams) {
681                                 flag = drawParams(tf? &tf[i]: NULL, mcol!=NULL, mf->mat_nr);
682                         }
683                         else {
684                                 if(index) {
685                                         orig = *index++;
686                                         if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
687                                         if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
688                                         else    { if(nors) nors += 3; continue; }
689                                 }
690                                 else
691                                         if(drawParamsMapped) flag = drawParamsMapped(userData, i);
692                                         else    { if(nors) nors += 3; continue; }
693                         }
694                         
695                         if(flag != 0) {
696                                 if (flag==1 && mcol)
697                                         cp= (unsigned char*) &mcol[i*4];
698
699                                 if(!(mf->flag&ME_SMOOTH)) {
700                                         if (nors) {
701                                                 glNormal3fv(nors);
702                                         }
703                                         else {
704                                                 float nor[3];
705                                                 if(mf->v4) {
706                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
707                                                 } else {
708                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
709                                                 }
710                                                 glNormal3fv(nor);
711                                         }
712                                 }
713
714                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
715                                 if(tf) glTexCoord2fv(tf[i].uv[0]);
716                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
717                                 mvert = &mv[mf->v1];
718                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
719                                 glVertex3fv(mvert->co);
720                                         
721                                 if(tf) glTexCoord2fv(tf[i].uv[1]);
722                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
723                                 mvert = &mv[mf->v2];
724                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
725                                 glVertex3fv(mvert->co);
726
727                                 if(tf) glTexCoord2fv(tf[i].uv[2]);
728                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
729                                 mvert = &mv[mf->v3];
730                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
731                                 glVertex3fv(mvert->co);
732
733                                 if(mf->v4) {
734                                         if(tf) glTexCoord2fv(tf[i].uv[3]);
735                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
736                                         mvert = &mv[mf->v4];
737                                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
738                                         glVertex3fv(mvert->co);
739                                 }
740                                 glEnd();
741                         }
742                         
743                         if(nors) nors += 3;
744                 }
745         } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
746                 MCol *col = realcol;
747                 if(!col)
748                         col = mcol;
749
750                 GPU_vertex_setup( dm );
751                 GPU_normal_setup( dm );
752                 GPU_uv_setup( dm );
753                 if( col != NULL ) {
754                         /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL )  {
755                                 col = 0;
756                         } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
757                                 col = 0;
758                         }
759                         
760                         if( col != 0 ) {*/
761                                 unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
762                                 for( i=0; i < dm->getNumTessFaces(dm); i++ ) {
763                                         for( j=0; j < 4; j++ ) {
764                                                 colors[i*12+j*3] = col[i*4+j].r;
765                                                 colors[i*12+j*3+1] = col[i*4+j].g;
766                                                 colors[i*12+j*3+2] = col[i*4+j].b;
767                                         }
768                                 }
769                                 GPU_color3_upload(dm,colors);
770                                 MEM_freeN(colors);
771                                 if(realcol)
772                                         dm->drawObject->colType = CD_TEXTURE_MCOL;
773                                 else if(mcol)
774                                         dm->drawObject->colType = CD_MCOL;
775                         //}
776                         GPU_color_setup( dm );
777                 }
778
779                 if( !GPU_buffer_legacy(dm) ) {
780                         glShadeModel( GL_SMOOTH );
781                         lastFlag = 0;
782                         for(i = 0; i < dm->drawObject->nelements/3; i++) {
783                                 int actualFace = dm->drawObject->faceRemap[i];
784                                 int flag = 1;
785
786                                 if(drawParams) {
787                                         flag = drawParams(tf? &tf[actualFace]: NULL, mcol!=NULL, mf[actualFace].mat_nr);
788                                 }
789                                 else {
790                                         if(index) {
791                                                 orig = index[actualFace];
792                                                 if(orig == ORIGINDEX_NONE) continue;
793                                                 if(drawParamsMapped)
794                                                         flag = drawParamsMapped(userData, orig);
795                                         }
796                                         else
797                                                 if(drawParamsMapped)
798                                                         flag = drawParamsMapped(userData, actualFace);
799                                 }
800                                 if( flag != lastFlag ) {
801                                         if( startFace < i ) {
802                                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
803                                                         if (lastFlag==1 && col)
804                                                                 GPU_color_switch(1);
805                                                         else
806                                                                 GPU_color_switch(0);
807                                                         glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
808                                                 }
809                                         }
810                                         lastFlag = flag;
811                                         startFace = i;
812                                 }
813                         }
814                         if( startFace < dm->drawObject->nelements/3 ) {
815                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
816                                         if (lastFlag==1 && col)
817                                                 GPU_color_switch(1);
818                                         else
819                                                 GPU_color_switch(0);
820                                         glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
821                                 }
822                         }
823                 }
824
825                 GPU_buffer_unbind();
826                 glShadeModel( GL_FLAT );
827         }
828 }
829
830 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
831 {
832         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
833 }
834
835 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs))
836 {
837         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
838         MVert *mv = cddm->mvert;
839         MFace *mf = cddm->mface;
840         MCol *mc;
841         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
842         int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
843
844         mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL);
845         if(!mc)
846                 mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL);
847         if(!mc)
848                 mc = DM_get_tessface_data_layer(dm, CD_MCOL);
849
850         cdDM_update_normals_from_pbvh(dm);
851
852         /* back-buffer always uses legacy since VBO's would need the
853          * color array temporarily overwritten for drawing, then reset. */
854         if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
855                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
856                 for(i = 0; i < dm->numFaceData; i++, mf++) {
857                         int drawSmooth = (mf->flag & ME_SMOOTH);
858                         int draw= 1;
859
860                         orig= (index==NULL) ? i : *index++;
861                         
862                         if(orig == ORIGINDEX_NONE)
863                                 draw= setMaterial(mf->mat_nr + 1, NULL);
864                         else if (setDrawOptions != NULL)
865                                 draw= setDrawOptions(userData, orig, &drawSmooth);
866
867                         if(draw) {
868                                 unsigned char *cp = NULL;
869
870                                 if(useColors && mc)
871                                         cp = (unsigned char *)&mc[i * 4];
872
873                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
874                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
875
876                                 if (!drawSmooth) {
877                                         if (nors) {
878                                                 glNormal3fv(nors);
879                                         }
880                                         else {
881                                                 float nor[3];
882                                                 if(mf->v4) {
883                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
884                                                 } else {
885                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
886                                                 }
887                                                 glNormal3fv(nor);
888                                         }
889
890                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
891                                         glVertex3fv(mv[mf->v1].co);
892                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
893                                         glVertex3fv(mv[mf->v2].co);
894                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
895                                         glVertex3fv(mv[mf->v3].co);
896                                         if(mf->v4) {
897                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
898                                                 glVertex3fv(mv[mf->v4].co);
899                                         }
900                                 } else {
901                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
902                                         glNormal3sv(mv[mf->v1].no);
903                                         glVertex3fv(mv[mf->v1].co);
904                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
905                                         glNormal3sv(mv[mf->v2].no);
906                                         glVertex3fv(mv[mf->v2].co);
907                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
908                                         glNormal3sv(mv[mf->v3].no);
909                                         glVertex3fv(mv[mf->v3].co);
910                                         if(mf->v4) {
911                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
912                                                 glNormal3sv(mv[mf->v4].no);
913                                                 glVertex3fv(mv[mf->v4].co);
914                                         }
915                                 }
916
917                                 glEnd();
918                         }
919                         
920                         if (nors) nors += 3;
921                 }
922         }
923         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
924                 int prevstart = 0;
925                 GPU_vertex_setup(dm);
926                 GPU_normal_setup(dm);
927                 if( useColors && mc )
928                         GPU_color_setup(dm);
929                 if( !GPU_buffer_legacy(dm) ) {
930                         int tottri = dm->drawObject->nelements/3;
931                         glShadeModel(GL_SMOOTH);
932                         
933                         if(tottri == 0) {
934                                 /* avoid buffer problems in following code */
935                         }
936                         if(setDrawOptions == NULL) {
937                                 /* just draw the entire face array */
938                                 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
939                         }
940                         else {
941                                 /* we need to check if the next material changes */
942                                 int next_actualFace= dm->drawObject->faceRemap[0];
943                                 
944                                 for( i = 0; i < tottri; i++ ) {
945                                         //int actualFace = dm->drawObject->faceRemap[i];
946                                         int actualFace = next_actualFace;
947                                         MFace *mface= mf + actualFace;
948                                         int drawSmooth= (mface->flag & ME_SMOOTH);
949                                         int draw = 1;
950
951                                         if(i != tottri-1)
952                                                 next_actualFace= dm->drawObject->faceRemap[i+1];
953
954                                         orig= (index==NULL) ? actualFace : index[actualFace];
955
956                                         if(orig == ORIGINDEX_NONE)
957                                                 draw= setMaterial(mface->mat_nr + 1, NULL);
958                                         else if (setDrawOptions != NULL)
959                                                 draw= setDrawOptions(userData, orig, &drawSmooth);
960         
961                                         /* Goal is to draw as long of a contiguous triangle
962                                            array as possible, so draw when we hit either an
963                                            invisible triangle or at the end of the array */
964                                         if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
965                                                 if(prevstart != i)
966                                                         /* Add one to the length (via `draw')
967                                                            if we're drawing at the end of the array */
968                                                         glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
969                                                 prevstart = i + 1;
970                                         }
971                                 }
972                         }
973
974                         glShadeModel(GL_FLAT);
975                 }
976                 GPU_buffer_unbind();
977         }
978 }
979
980 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
981 {
982         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
983 }
984
985 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
986 {
987         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
988         GPUVertexAttribs gattribs;
989         DMVertexAttribs attribs;
990         MVert *mvert = cddm->mvert;
991         MFace *mface = cddm->mface;
992         MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
993         float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
994         int a, b, dodraw, matnr, new_matnr;
995         int transp, new_transp, orig_transp;
996         int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
997
998         cdDM_update_normals_from_pbvh(dm);
999
1000         matnr = -1;
1001         dodraw = 0;
1002         transp = GPU_get_material_blend_mode();
1003         orig_transp = transp;
1004
1005         glShadeModel(GL_SMOOTH);
1006
1007         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1008                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1009                 memset(&attribs, 0, sizeof(attribs));
1010
1011                 glBegin(GL_QUADS);
1012
1013                 for(a = 0; a < dm->numFaceData; a++, mface++) {
1014                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1015                         new_matnr = mface->mat_nr + 1;
1016
1017                         if(new_matnr != matnr) {
1018                                 glEnd();
1019
1020                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1021                                 if(dodraw)
1022                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1023
1024                                 glBegin(GL_QUADS);
1025                         }
1026
1027                         if(!dodraw) {
1028                                 continue;
1029                         }
1030                         else if(setDrawOptions) {
1031                                 orig = (index)? index[a]: a;
1032
1033                                 if(orig == ORIGINDEX_NONE) {
1034                                         /* since the material is set by setMaterial(), faces with no
1035                                          * origin can be assumed to be generated by a modifier */ 
1036                                         
1037                                         /* continue */
1038                                 }
1039                                 else if(!setDrawOptions(userData, orig))
1040                                         continue;
1041                         }
1042
1043                         if(tf) {
1044                                 new_transp = tf[a].transp;
1045
1046                                 if(new_transp != transp) {
1047                                         glEnd();
1048
1049                                         if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1050                                                 GPU_set_material_blend_mode(orig_transp);
1051                                         else
1052                                                 GPU_set_material_blend_mode(new_transp);
1053                                         transp = new_transp;
1054
1055                                         glBegin(GL_QUADS);
1056                                 }
1057                         }
1058
1059                         if(!smoothnormal) {
1060                                 if(nors) {
1061                                         glNormal3fv(nors[a]);
1062                                 }
1063                                 else {
1064                                         /* TODO ideally a normal layer should always be available */
1065                                         float nor[3];
1066                                         if(mface->v4) {
1067                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1068                                         } else {
1069                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1070                                         }
1071                                         glNormal3fv(nor);
1072                                 }
1073                         }
1074
1075 #define PASSVERT(index, vert) {                                                                                                 \
1076                 if(attribs.totorco)                                                                                                                     \
1077                         glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
1078                 for(b = 0; b < attribs.tottface; b++) {                                                                         \
1079                         MTFace *tf = &attribs.tface[b].array[a];                                                                \
1080                         glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
1081                 }                                                                                                                                                       \
1082                 for(b = 0; b < attribs.totmcol; b++) {                                                                          \
1083                         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
1084                         GLubyte col[4];                                                                                                                 \
1085                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
1086                         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
1087                 }                                                                                                                                                       \
1088                 if(attribs.tottang) {                                                                                                           \
1089                         float *tang = attribs.tang.array[a*4 + vert];                                                   \
1090                         glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
1091                 }                                                                                                                                                       \
1092                 if(smoothnormal)                                                                                                                        \
1093                         glNormal3sv(mvert[index].no);                                                                                   \
1094                 glVertex3fv(mvert[index].co);                                                                                           \
1095         }
1096
1097                         PASSVERT(mface->v1, 0);
1098                         PASSVERT(mface->v2, 1);
1099                         PASSVERT(mface->v3, 2);
1100                         if(mface->v4)
1101                                 PASSVERT(mface->v4, 3)
1102                         else
1103                                 PASSVERT(mface->v3, 2)
1104
1105                 }
1106                 glEnd();
1107         }
1108         else {
1109                 GPUBuffer *buffer = NULL;
1110                 char *varray = NULL;
1111                 int numdata = 0, elementsize = 0, offset;
1112                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1113                 int i;
1114
1115                 MFace *mf = mface;
1116                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1117                 memset(&attribs, 0, sizeof(attribs));
1118
1119                 GPU_vertex_setup(dm);
1120                 GPU_normal_setup(dm);
1121
1122                 if( !GPU_buffer_legacy(dm) ) {
1123                         for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
1124
1125                                 a = dm->drawObject->faceRemap[i];
1126
1127                                 mface = mf + a;
1128                                 new_matnr = mface->mat_nr + 1;
1129
1130                                 if(new_matnr != matnr ) {
1131                                         numfaces = curface - start;
1132                                         if( numfaces > 0 ) {
1133
1134                                                 if( dodraw ) {
1135
1136                                                         if( numdata != 0 ) {
1137
1138                                                                 GPU_buffer_unlock(buffer);
1139
1140                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1141                                                         }
1142
1143                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1144
1145                                                         if( numdata != 0 ) {
1146
1147                                                                 GPU_buffer_free(buffer, NULL);
1148
1149                                                                 buffer = NULL;
1150                                                         }
1151
1152                                                 }
1153                                         }
1154                                         numdata = 0;
1155                                         start = curface;
1156                                         prevdraw = dodraw;
1157                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1158                                         if(dodraw) {
1159                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1160
1161                                                 if(attribs.totorco) {
1162                                                         datatypes[numdata].index = attribs.orco.glIndex;
1163                                                         datatypes[numdata].size = 3;
1164                                                         datatypes[numdata].type = GL_FLOAT;
1165                                                         numdata++;
1166                                                 }
1167                                                 for(b = 0; b < attribs.tottface; b++) {
1168                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1169                                                         datatypes[numdata].size = 2;
1170                                                         datatypes[numdata].type = GL_FLOAT;
1171                                                         numdata++;
1172                                                 }       
1173                                                 for(b = 0; b < attribs.totmcol; b++) {
1174                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1175                                                         datatypes[numdata].size = 4;
1176                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1177                                                         numdata++;
1178                                                 }       
1179                                                 if(attribs.tottang) {
1180                                                         datatypes[numdata].index = attribs.tang.glIndex;
1181                                                         datatypes[numdata].size = 4;
1182                                                         datatypes[numdata].type = GL_FLOAT;
1183                                                         numdata++;
1184                                                 }
1185                                                 if( numdata != 0 ) {
1186                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1187                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL );
1188                                                         if( buffer == NULL ) {
1189                                                                 GPU_buffer_unbind();
1190                                                                 dm->drawObject->legacy = 1;
1191                                                                 return;
1192                                                         }
1193                                                         varray = GPU_buffer_lock_stream(buffer);
1194                                                         if( varray == NULL ) {
1195                                                                 GPU_buffer_unbind();
1196                                                                 GPU_buffer_free(buffer, NULL);
1197                                                                 dm->drawObject->legacy = 1;
1198                                                                 return;
1199                                                         }
1200                                                 }
1201                                                 else {
1202                                                         /* if the buffer was set, dont use it again.
1203                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1204                                                         prevdraw= 0;
1205                                                         buffer= NULL;
1206                                                 }
1207                                         }
1208                                 }
1209                                 if(!dodraw) {
1210                                         continue;
1211                                 }
1212
1213                                 if(tf) {
1214                                         new_transp = tf[a].transp;
1215
1216                                         if(new_transp != transp) {
1217                                                 numfaces = curface - start;
1218                                                 if( numfaces > 0 ) {
1219                                                         if( dodraw ) {
1220                                                                 if( numdata != 0 ) {
1221                                                                         GPU_buffer_unlock(buffer);
1222                                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1223                                                                 }
1224                                                                 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1225                                                                 if( numdata != 0 ) {
1226                                                                         varray = GPU_buffer_lock_stream(buffer);
1227                                                                 }
1228                                                         }
1229                                                 }
1230                                                 start = curface;
1231
1232                                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1233                                                         GPU_set_material_blend_mode(orig_transp);
1234                                                 else
1235                                                         GPU_set_material_blend_mode(new_transp);
1236                                                 transp = new_transp;
1237                                         }
1238                                 }
1239                                 
1240                                 if( numdata != 0 ) {
1241                                         offset = 0;
1242                                         if(attribs.totorco) {
1243                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1244                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1245                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1246                                                 offset += sizeof(float)*3;
1247                                         }
1248                                         for(b = 0; b < attribs.tottface; b++) {
1249                                                 MTFace *tf = &attribs.tface[b].array[a];
1250                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1251                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1252
1253                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1254                                                 offset += sizeof(float)*2;
1255                                         }
1256                                         for(b = 0; b < attribs.totmcol; b++) {
1257                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1258                                                 GLubyte col[4];
1259                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1260                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1261                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1262                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1263                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1264                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1265                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1266                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1267                                                 offset += sizeof(unsigned char)*4;
1268                                         }       
1269                                         if(attribs.tottang) {
1270                                                 float *tang = attribs.tang.array[a*4 + 0];
1271                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1272                                                 tang = attribs.tang.array[a*4 + 1];
1273                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1274                                                 tang = attribs.tang.array[a*4 + 2];
1275                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1276                                                 offset += sizeof(float)*4;
1277                                         }
1278                                 }
1279                                 curface++;
1280                                 if(mface->v4) {
1281                                         if( numdata != 0 ) {
1282                                                 offset = 0;
1283                                                 if(attribs.totorco) {
1284                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1285                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1286                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1287                                                         offset += sizeof(float)*3;
1288                                                 }
1289                                                 for(b = 0; b < attribs.tottface; b++) {
1290                                                         MTFace *tf = &attribs.tface[b].array[a];
1291                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1292                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1293                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1294                                                         offset += sizeof(float)*2;
1295                                                 }
1296                                                 for(b = 0; b < attribs.totmcol; b++) {
1297                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1298                                                         GLubyte col[4];
1299                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1300                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1301                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1302                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1303                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1304                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1305                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1306                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1307                                                         offset += sizeof(unsigned char)*4;
1308                                                 }       
1309                                                 if(attribs.tottang) {
1310                                                         float *tang = attribs.tang.array[a*4 + 2];
1311                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1312                                                         tang = attribs.tang.array[a*4 + 3];
1313                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1314                                                         tang = attribs.tang.array[a*4 + 0];
1315                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1316                                                         offset += sizeof(float)*4;
1317                                                 }
1318                                         }
1319                                         curface++;
1320                                         i++;
1321                                 }
1322                         }
1323                         numfaces = curface - start;
1324                         if( numfaces > 0 ) {
1325                                 if( dodraw ) {
1326                                         if( numdata != 0 ) {
1327                                                 GPU_buffer_unlock(buffer);
1328                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1329                                         }
1330                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1331                                 }
1332                         }
1333                         GPU_buffer_unbind();
1334                 }
1335                 GPU_buffer_free( buffer, NULL );
1336         }
1337
1338         glShadeModel(GL_FLAT);
1339 }
1340
1341 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1342 {
1343         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1344 }
1345
1346 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1347 {
1348         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1349         MVert *vert = cddm->mvert;
1350         MEdge *edge = cddm->medge;
1351         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1352
1353         glBegin(GL_LINES);
1354         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1355                 if(index) {
1356                         orig = *index++;
1357                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1358                 }
1359                 else
1360                         orig = i;
1361
1362                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1363                         glVertex3fv(vert[edge->v1].co);
1364                         glVertex3fv(vert[edge->v2].co);
1365                 }
1366         }
1367         glEnd();
1368 }
1369
1370 static void cdDM_foreachMappedVert(
1371                                                    DerivedMesh *dm,
1372                                                    void (*func)(void *userData, int index, float *co,
1373                                                                                 float *no_f, short *no_s),
1374                                                    void *userData)
1375 {
1376         MVert *mv = CDDM_get_verts(dm);
1377         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1378
1379         for(i = 0; i < dm->numVertData; i++, mv++) {
1380                 if(index) {
1381                         orig = *index++;
1382                         if(orig == ORIGINDEX_NONE) continue;
1383                         func(userData, orig, mv->co, NULL, mv->no);
1384                 }
1385                 else
1386                         func(userData, i, mv->co, NULL, mv->no);
1387         }
1388 }
1389
1390 static void cdDM_foreachMappedEdge(
1391                                                    DerivedMesh *dm,
1392                                                    void (*func)(void *userData, int index,
1393                                                                                 float *v0co, float *v1co),
1394                                                    void *userData)
1395 {
1396         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1397         MVert *mv = cddm->mvert;
1398         MEdge *med = cddm->medge;
1399         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1400
1401         for(i = 0; i < dm->numEdgeData; i++, med++) {
1402                 if (index) {
1403                         orig = *index++;
1404                         if(orig == ORIGINDEX_NONE) continue;
1405                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1406                 }
1407                 else
1408                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1409         }
1410 }
1411
1412 static void cdDM_foreachMappedFaceCenter(
1413                                                    DerivedMesh *dm,
1414                                                    void (*func)(void *userData, int index,
1415                                                                                 float *cent, float *no),
1416                                                    void *userData)
1417 {
1418         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1419         MVert *mv = cddm->mvert;
1420         MPoly *mf = cddm->mpoly;
1421         MLoop *ml = cddm->mloop;
1422         int i, j, orig, *index;
1423
1424         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1425         mf = cddm->mpoly;
1426         for(i = 0; i < dm->numPolyData; i++, mf++) {
1427                 float cent[3];
1428                 float no[3];
1429
1430                 if (index) {
1431                         orig = *index++;
1432                         if(orig == ORIGINDEX_NONE) continue;
1433                 } else
1434                         orig = i;
1435                 
1436                 ml = &cddm->mloop[mf->loopstart];
1437                 cent[0] = cent[1] = cent[2] = 0.0f;
1438                 for (j=0; j<mf->totloop; j++, ml++) {
1439                         add_v3_v3v3(cent, cent, mv[ml->v].co);
1440                 }
1441                 mul_v3_fl(cent, 1.0f / (float)j);
1442
1443                 ml = &cddm->mloop[mf->loopstart];
1444                 if (j > 3) {
1445                         normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1446                                        mv[(ml+2)->v].co, mv[(ml+3)->v].co);
1447                 } else {
1448                         normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1449                                        mv[(ml+2)->v].co);
1450                 }
1451
1452                 func(userData, orig, cent, no);
1453         }
1454
1455 }
1456
1457 static void cdDM_recalcTesselation(DerivedMesh *dm)
1458 {
1459         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1460
1461         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1462                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1463                 dm->numPolyData, 1, 0);
1464         
1465         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1466 }
1467
1468 void CDDM_recalc_tesselation(DerivedMesh *dm)
1469 {
1470         cdDM_recalcTesselation(dm);
1471 }
1472
1473 /*ignores original poly origindex layer*/
1474 static void cdDM_recalcTesselation2(DerivedMesh *dm)
1475 {
1476         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1477
1478         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1479                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1480                 dm->numPolyData, 0, 0);
1481         
1482         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1483 }
1484
1485 static void cdDM_free_internal(CDDerivedMesh *cddm)
1486 {
1487         if(cddm->fmap) MEM_freeN(cddm->fmap);
1488         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1489 }
1490
1491 static void cdDM_release(DerivedMesh *dm)
1492 {
1493         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1494
1495         if (DM_release(dm)) {
1496                 cdDM_free_internal(cddm);
1497                 MEM_freeN(cddm);
1498         }
1499 }
1500
1501 int CDDM_Check(DerivedMesh *dm)
1502 {
1503         return dm && dm->getMinMax == cdDM_getMinMax;
1504 }
1505
1506 /**************** CDDM interface functions ****************/
1507 static CDDerivedMesh *cdDM_create(const char *desc)
1508 {
1509         CDDerivedMesh *cddm;
1510         DerivedMesh *dm;
1511
1512         cddm = MEM_callocN(sizeof(*cddm), desc);
1513         dm = &cddm->dm;
1514
1515         dm->getMinMax = cdDM_getMinMax;
1516
1517         dm->getNumVerts = cdDM_getNumVerts;
1518         dm->getNumEdges = cdDM_getNumEdges;
1519         dm->getNumTessFaces = cdDM_getNumTessFaces;
1520         dm->getNumFaces = cdDM_getNumFaces;
1521
1522         dm->newFaceIter = cdDM_newFaceIter;
1523
1524         dm->getVert = cdDM_getVert;
1525         dm->getEdge = cdDM_getEdge;
1526         dm->getTessFace = cdDM_getFace;
1527         dm->copyVertArray = cdDM_copyVertArray;
1528         dm->copyEdgeArray = cdDM_copyEdgeArray;
1529         dm->copyTessFaceArray = cdDM_copyFaceArray;
1530         dm->getVertData = DM_get_vert_data;
1531         dm->getEdgeData = DM_get_edge_data;
1532         dm->getTessFaceData = DM_get_face_data;
1533         dm->getVertDataArray = DM_get_vert_data_layer;
1534         dm->getEdgeDataArray = DM_get_edge_data_layer;
1535         dm->getTessFaceDataArray = DM_get_tessface_data_layer;
1536         
1537         //doesn't work yet for all cases
1538         //dm->recalcTesselation = cdDM_recalcTesselation;
1539
1540         dm->getVertCos = cdDM_getVertCos;
1541         dm->getVertCo = cdDM_getVertCo;
1542         dm->getVertNo = cdDM_getVertNo;
1543
1544         dm->getPBVH = cdDM_getPBVH;
1545         dm->getFaceMap = cdDM_getFaceMap;
1546
1547         dm->drawVerts = cdDM_drawVerts;
1548
1549         dm->drawUVEdges = cdDM_drawUVEdges;
1550         dm->drawEdges = cdDM_drawEdges;
1551         dm->drawLooseEdges = cdDM_drawLooseEdges;
1552         dm->drawMappedEdges = cdDM_drawMappedEdges;
1553
1554         dm->drawFacesSolid = cdDM_drawFacesSolid;
1555         dm->drawFacesColored = cdDM_drawFacesColored;
1556         dm->drawFacesTex = cdDM_drawFacesTex;
1557         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1558         dm->drawMappedFaces = cdDM_drawMappedFaces;
1559         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1560         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1561
1562         dm->foreachMappedVert = cdDM_foreachMappedVert;
1563         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1564         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1565
1566         dm->release = cdDM_release;
1567
1568         return cddm;
1569 }
1570
1571 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
1572 {
1573         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1574         DerivedMesh *dm = &cddm->dm;
1575
1576         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
1577
1578         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1579         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1580         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1581         CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
1582
1583         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1584         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1585         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1586         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
1587         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
1588
1589         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1590         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1591         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1592         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1593         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1594
1595         return dm;
1596 }
1597
1598 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1599 {
1600         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1601         DerivedMesh *dm = &cddm->dm;
1602         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1603         int alloctype;
1604
1605         /* this does a referenced copy, with an exception for fluidsim */
1606
1607         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
1608                     mesh->totloop, mesh->totpoly);
1609
1610         dm->deformedOnly = 1;
1611
1612         alloctype= CD_REFERENCE;
1613
1614         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1615                                          mesh->totvert);
1616         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1617                                          mesh->totedge);
1618         CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype,
1619                                          mesh->totface);
1620         CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
1621                          mesh->totloop);
1622         CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
1623                          mesh->totpoly);
1624
1625         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1626         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1627         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1628         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1629         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1630
1631         if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
1632                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
1633
1634         return dm;
1635 }
1636
1637 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1638 {
1639         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1640                                    BLI_countlist(&em->edges),
1641                                    BLI_countlist(&em->faces), 0, 0);
1642         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1643         EditVert *eve;
1644         EditEdge *eed;
1645         EditFace *efa;
1646         MVert *mvert = cddm->mvert;
1647         MEdge *medge = cddm->medge;
1648         MFace *mface = cddm->mface;
1649         int i, *index;
1650
1651         dm->deformedOnly = 1;
1652
1653         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1654                                          CD_CALLOC, dm->numVertData);
1655         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1656                                          CD_CALLOC, dm->numEdgeData); */
1657         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1658                                          CD_CALLOC, dm->numFaceData);
1659         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1660                          CD_CALLOC, dm->numFaceData);
1661
1662         /* set eve->hash to vert index */
1663         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1664                 eve->tmp.l = i;
1665
1666         /* Need to be able to mark loose edges */
1667         for(eed = em->edges.first; eed; eed = eed->next) {
1668                 eed->f2 = 0;
1669         }
1670         for(efa = em->faces.first; efa; efa = efa->next) {
1671                 efa->e1->f2 = 1;
1672                 efa->e2->f2 = 1;
1673                 efa->e3->f2 = 1;
1674                 if(efa->e4) efa->e4->f2 = 1;
1675         }
1676
1677         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1678         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1679                 i++, eve = eve->next, index++) {
1680                 MVert *mv = &mvert[i];
1681
1682                 VECCOPY(mv->co, eve->co);
1683
1684                 mv->no[0] = eve->no[0] * 32767.0;
1685                 mv->no[1] = eve->no[1] * 32767.0;
1686                 mv->no[2] = eve->no[2] * 32767.0;
1687                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1688
1689                 mv->flag = 0;
1690
1691                 *index = i;
1692
1693                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1694         }
1695
1696         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1697         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1698                 i++, eed = eed->next, index++) {
1699                 MEdge *med = &medge[i];
1700
1701                 med->v1 = eed->v1->tmp.l;
1702                 med->v2 = eed->v2->tmp.l;
1703                 med->crease = (unsigned char) (eed->crease * 255.0f);
1704                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1705                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1706                 
1707                 if(eed->seam) med->flag |= ME_SEAM;
1708                 if(eed->sharp) med->flag |= ME_SHARP;
1709                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1710
1711                 *index = i;
1712
1713                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1714         }
1715
1716         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1717         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1718                 i++, efa = efa->next, index++) {
1719                 MFace *mf = &mface[i];
1720
1721                 mf->v1 = efa->v1->tmp.l;
1722                 mf->v2 = efa->v2->tmp.l;
1723                 mf->v3 = efa->v3->tmp.l;
1724                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1725                 mf->mat_nr = efa->mat_nr;
1726                 mf->flag = efa->flag;
1727
1728                 *index = i;
1729
1730                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1731                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1732         }
1733
1734         return dm;
1735 }
1736
1737 DerivedMesh *CDDM_from_curve(Object *ob)
1738 {
1739         return CDDM_from_curve_customDB(ob, &ob->disp);
1740 }
1741
1742 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1743 {
1744         DerivedMesh *dm;
1745         CDDerivedMesh *cddm;
1746         MVert *allvert;
1747         MEdge *alledge;
1748         MFace *allface;
1749         int totvert, totedge, totface;
1750
1751         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1752                 &totedge, &allface, &totface) != 0) {
1753                 /* Error initializing mdata. This often happens when curve is empty */
1754                 return CDDM_new(0, 0, 0, 0, 0);
1755         }
1756
1757         dm = CDDM_new(totvert, totedge, totface, totface*4, totface);
1758         dm->deformedOnly = 1;
1759
1760         cddm = (CDDerivedMesh*)dm;
1761
1762         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1763         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1764         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1765
1766         MEM_freeN(allvert);
1767         MEM_freeN(alledge);
1768         MEM_freeN(allface);
1769
1770         return dm;
1771 }
1772
1773 static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
1774                                           int cdindex, BMLoop *l3[3],
1775                                           int numCol, int numTex)
1776 {
1777         BMLoop *l;
1778         BMFace *f = l3[0]->f;
1779         MTFace *texface;
1780         MTexPoly *texpoly;
1781         MCol *mcol;
1782         MLoopCol *mloopcol;
1783         MLoopUV *mloopuv;
1784         int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
1785
1786         for(i=0; i < numTex; i++){
1787                 texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
1788                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
1789                 
1790                 texface->tpage = texpoly->tpage;
1791                 texface->flag = texpoly->flag;
1792                 texface->transp = texpoly->transp;
1793                 texface->mode = texpoly->mode;
1794                 texface->tile = texpoly->tile;
1795                 texface->unwrap = texpoly->unwrap;
1796         
1797                 for (j=0; j<3; j++) {
1798                         l = l3[j];
1799                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
1800                         texface->uv[j][0] = mloopuv->uv[0];
1801                         texface->uv[j][1] = mloopuv->uv[1];
1802                 }
1803         }
1804
1805         for(i=0; i < numCol; i++){
1806                 mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
1807                 
1808                 for (j=0; j<3; j++) {
1809                         l = l3[j];
1810                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
1811                         mcol[j].r = mloopcol->r;
1812                         mcol[j].g = mloopcol->g;
1813                         mcol[j].b = mloopcol->b;
1814                         mcol[j].a = mloopcol->a;
1815                 }
1816         }
1817
1818         if (hasWCol) {
1819                 mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
1820
1821                 for (j=0; j<3; j++) {
1822                         l = l3[j];
1823                         mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
1824                         mcol[j].r = mloopcol->r;
1825                         mcol[j].g = mloopcol->g;
1826                         mcol[j].b = mloopcol->b;
1827                         mcol[j].a = mloopcol->a;
1828                 }
1829         }
1830 }
1831
1832 DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *me)
1833 {
1834         DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, 
1835                                em->tottri, em->bm->totloop, em->bm->totface);
1836         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1837         BMesh *bm = em->bm;
1838         BMIter iter, liter;
1839         BMVert *eve;
1840         BMEdge *eed;
1841         BMFace *efa;
1842         MVert *mvert = cddm->mvert;
1843         MEdge *medge = cddm->medge;
1844         MFace *mface = cddm->mface;
1845         MLoop *mloop = cddm->mloop;
1846         MPoly *mpoly = cddm->mpoly;
1847         int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
1848         int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
1849         int i, j, *index, add_orig;
1850
1851         dm->deformedOnly = 1;
1852         
1853         /*don't add origindex layer if one already exists*/
1854         add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
1855
1856         CustomData_merge(&em->bm->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1857                          CD_CALLOC, dm->numVertData);
1858         CustomData_merge(&em->bm->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1859                          CD_CALLOC, dm->numEdgeData);
1860         CustomData_merge(&em->bm->ldata, &dm->loopData, CD_MASK_DERIVEDMESH,
1861                          CD_CALLOC, dm->numLoopData);
1862         CustomData_merge(&em->bm->pdata, &dm->polyData, CD_MASK_DERIVEDMESH,
1863                          CD_CALLOC, dm->numPolyData);
1864         
1865         /*add tesselation mface layers*/
1866         CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
1867
1868         /* set vert index */
1869         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1870         for (i=0; eve; eve=BMIter_Step(&iter), i++)
1871                 BMINDEX_SET(eve, i);
1872
1873         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1874
1875         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1876         for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
1877                 MVert *mv = &mvert[i];
1878
1879                 VECCOPY(mv->co, eve->co);
1880
1881                 BMINDEX_SET(eve, i);
1882
1883                 mv->no[0] = eve->no[0] * 32767.0;
1884                 mv->no[1] = eve->no[1] * 32767.0;
1885                 mv->no[2] = eve->no[2] * 32767.0;
1886
1887                 mv->flag = BMFlags_To_MEFlags(eve);
1888
1889                 if (add_orig) *index = i;
1890
1891                 CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
1892         }
1893
1894         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1895         eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1896         for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
1897                 MEdge *med = &medge[i];
1898
1899                 BMINDEX_SET(eed, i);
1900
1901                 med->v1 = BMINDEX_GET(eed->v1);
1902                 med->v2 = BMINDEX_GET(eed->v2);
1903                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1904                 
1905                 med->flag = BMFlags_To_MEFlags(eed);
1906
1907                 CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
1908                 if (add_orig) *index = i;
1909         }
1910
1911         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1912         for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
1913                 BMINDEX_SET(efa, i);
1914         }
1915
1916         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1917         for(i = 0; i < dm->numFaceData; i++, index++) {
1918                 MFace *mf = &mface[i];
1919                 BMLoop **l = em->looptris[i];
1920                 efa = l[0]->f;
1921
1922                 mf->v1 = BMINDEX_GET(l[0]->v);
1923                 mf->v2 = BMINDEX_GET(l[1]->v);
1924                 mf->v3 = BMINDEX_GET(l[2]->v);
1925                 mf->v4 = 0;
1926                 mf->mat_nr = efa->mat_nr;
1927                 mf->flag = BMFlags_To_MEFlags(efa);
1928                 
1929                 *index = add_orig ? BMINDEX_GET(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
1930
1931                 loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
1932                 test_index_face(mf, &dm->faceData, i, 3);
1933         }
1934         
1935         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1936         j = 0;
1937         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1938         for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
1939                 BMLoop *l;
1940                 MPoly *mp = &mpoly[i];
1941
1942                 mp->totloop = efa->len;
1943                 mp->flag = BMFlags_To_MEFlags(efa);
1944                 mp->loopstart = j;
1945                 mp->mat_nr = efa->mat_nr;
1946                 
1947                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
1948                         mloop->v = BMINDEX_GET(l->v);
1949                         mloop->e = BMINDEX_GET(l->e);
1950                         CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
1951
1952                         j++;
1953                         mloop++;
1954                 }
1955
1956                 CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
1957
1958                 if (add_orig) *index = i;
1959         }
1960
1961         return dm;
1962 }
1963
1964 typedef struct CDDM_LoopIter {
1965         DMLoopIter head;
1966         CDDerivedMesh *cddm;
1967         int len, i;
1968 } CDDM_LoopIter;
1969
1970 typedef struct CDDM_FaceIter {
1971         DMFaceIter head;
1972         CDDerivedMesh *cddm;
1973         CDDM_LoopIter liter;
1974 } CDDM_FaceIter;
1975
1976 void cddm_freeiter(void *self)
1977 {
1978         MEM_freeN(self);
1979 }
1980
1981 void cddm_stepiter(void *self)
1982 {
1983         CDDM_FaceIter *iter = self;
1984         MPoly *mp;
1985         
1986         mp = iter->cddm->mpoly + iter->head.index;
1987         mp->flag = iter->head.flags;
1988         mp->mat_nr = iter->head.mat_nr;
1989
1990         iter->head.index++;
1991         if (iter->head.index >= iter->cddm->dm.numPolyData) {
1992                 iter->head.done = 1;
1993                 return;
1994         }
1995
1996         mp = iter->cddm->mpoly + iter->head.index;
1997
1998         iter->head.flags = mp->flag;
1999         iter->head.mat_nr = mp->mat_nr;
2000         iter->head.len = mp->totloop;
2001 }
2002
2003 void *cddm_faceiter_getcddata(void *self, int type, int layer)
2004 {
2005         CDDM_FaceIter *iter = self;
2006
2007         if (layer == -1) return CustomData_get(&iter->cddm->dm.polyData, 
2008                                                iter->head.index, type);
2009         else return CustomData_get_n(&iter->cddm->dm.polyData, type, 
2010                                     iter->head.index, layer);
2011 }
2012
2013 void *cddm_loopiter_getcddata(void *self, int type, int layer)
2014 {
2015         CDDM_LoopIter *iter = self;
2016
2017         if (layer == -1) return CustomData_get(&iter->cddm->dm.loopData, 
2018                                                iter->head.index, type);
2019         else return CustomData_get_n(&iter->cddm->dm.loopData, type, 
2020                                      iter->head.index, layer);
2021 }
2022
2023 void *cddm_loopiter_getvertcddata(void *self, int type, int layer)
2024 {
2025         CDDM_LoopIter *iter = self;
2026
2027         if (layer == -1) return CustomData_get(&iter->cddm->dm.vertData, 
2028                                                iter->cddm->mloop[iter->head.vindex].v,
2029                                                type);
2030         else return CustomData_get_n(&iter->cddm->dm.vertData, type, 
2031                                      iter->cddm->mloop[iter->head.vindex].v, layer);
2032 }
2033
2034 DMLoopIter *cddmiter_get_loopiter(void *self)
2035 {
2036         CDDM_FaceIter *iter = self;
2037         CDDM_LoopIter *liter = &iter->liter;
2038         MPoly *mp = iter->cddm->mpoly + iter->head.index;
2039
2040         liter->i = -1;
2041         liter->len = iter->head.len;
2042         liter->head.index = mp->loopstart-1;
2043         liter->head.done = 0;
2044
2045         liter->head.step(liter);
2046
2047         return (DMLoopIter*) liter;
2048 }
2049
2050 void cddm_loopiter_step(void *self)
2051 {
2052         CDDM_LoopIter *liter = self;
2053         MLoop *ml;
2054
2055         liter->i++;
2056         liter->head.index++;
2057
2058         if (liter->i == liter->len) {
2059                 liter->head.done = 1;
2060                 return;
2061         }
2062
2063         ml = liter->cddm->mloop + liter->head.index;
2064
2065         liter->head.eindex = ml->e;
2066         liter->head.v = liter->cddm->mvert[ml->v];
2067         liter->head.vindex = ml->v;
2068 }
2069
2070 DMFaceIter *cdDM_newFaceIter(DerivedMesh *source)
2071 {
2072         CDDerivedMesh *cddm = (CDDerivedMesh*) source;
2073         CDDM_FaceIter *iter = MEM_callocN(sizeof(CDDM_FaceIter), "DMFaceIter from cddm");
2074
2075         iter->head.free = cddm_freeiter;
2076         iter->head.step = cddm_stepiter;
2077         iter->head.getCDData = cddm_faceiter_getcddata;
2078         iter->head.getLoopsIter = cddmiter_get_loopiter;
2079
2080         iter->liter.head.step = cddm_loopiter_step;
2081         iter->liter.head.getLoopCDData = cddm_loopiter_getcddata;
2082         iter->liter.head.getVertCDData = cddm_loopiter_getvertcddata;
2083         iter->liter.cddm = cddm;
2084
2085         iter->cddm = cddm;
2086
2087         if (source->numFaceData) {
2088                 iter->head.index = -1;
2089                 iter->head.step(iter);
2090         } else {
2091                 iter->head.done = 1;
2092         }
2093
2094         return (DMFaceIter*) iter;
2095 }
2096
2097 DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
2098 {
2099         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
2100         DerivedMesh *dm = &cddm->dm;
2101         int numVerts = source->numVertData;
2102         int numEdges = source->numEdgeData;
2103         int numFaces = source->numFaceData;
2104         int numLoops = source->numLoopData;
2105         int numPolys = source->numPolyData;
2106
2107         /* ensure these are created if they are made on demand */
2108         source->getVertDataArray(source, CD_ORIGINDEX);
2109         source->getEdgeDataArray(source, CD_ORIGINDEX);
2110         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2111
2112         /* this initializes dm, and copies all non mvert/medge/mface layers */
2113         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
2114                 numLoops, numPolys);
2115         dm->deformedOnly = source->deformedOnly;
2116
2117         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
2118         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
2119         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
2120
2121         /* now add mvert/medge/mface layers */
2122         cddm->mvert = source->dupVertArray(source);
2123         cddm->medge = source->dupEdgeArray(source);
2124         cddm->mface = source->dupTessFaceArray(source);
2125
2126         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
2127         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
2128         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
2129         
2130         if (!faces_from_tessfaces)
2131                 DM_DupPolys(source, dm);
2132         else
2133                 CDDM_tessfaces_to_faces(dm);
2134
2135         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2136         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2137
2138         return dm;
2139 }
2140
2141 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
2142  * relationship betwen mesh data this needs to be set by the caller. */
2143 DerivedMesh *CDDM_from_template(DerivedMesh *source,
2144                                 int numVerts, int numEdges, int numFaces,
2145                                                                 int numLoops, int numPolys)
2146 {
2147         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
2148         DerivedMesh *dm = &cddm->dm;
2149
2150         /* ensure these are created if they are made on demand */
2151         source->getVertDataArray(source, CD_ORIGINDEX);
2152         source->getEdgeDataArray(source, CD_ORIGINDEX);
2153         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2154
2155         /* this does a copy of all non mvert/medge/mface layers */
2156         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
2157
2158         /* now add mvert/medge/mface layers */
2159         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
2160         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2161         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
2162         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
2163         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
2164
2165         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
2166                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
2167         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
2168                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2169         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
2170                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
2171
2172         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
2173         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2174         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
2175         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2176         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2177
2178         return dm;
2179 }
2180
2181 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
2182 {
2183         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2184         MVert *vert;
2185         int i;
2186
2187         /* this will just return the pointer if it wasn't a referenced layer */
2188         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2189         cddm->mvert = vert;
2190
2191         for(i = 0; i < dm->numVertData; ++i, ++vert)
2192                 VECCOPY(vert->co, vertCoords[i]);
2193 }
2194
2195 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
2196 {
2197         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2198         MVert *vert;
2199         int i;
2200
2201         /* this will just return the pointer if it wasn't a referenced layer */
2202         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2203         cddm->mvert = vert;
2204
2205         for(i = 0; i < dm->numVertData; ++i, ++vert)
2206                 VECCOPY(vert->no, vertNormals[i]);
2207 }
2208
2209 void CDDM_calc_normals(DerivedMesh *dm)
2210 {
2211         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2212         float (*temp_nors)[3];
2213         float (*face_nors)[3];
2214         float (*vert_nors)[3];
2215         int i, j, *origIndex;
2216         int numVerts = dm->numVertData;
2217         int numFaces = dm->numFaceData;
2218         MFace *mf;
2219         MPoly *mp;
2220         MVert *mv;
2221         MLoop *ml;
2222
2223         if(numVerts == 0) return;
2224
2225         if (CustomData_has_layer(&dm->faceData, CD_NORMAL))
2226                 CustomData_free_layer(&dm->faceData, CD_NORMAL, dm->numFaceData, 0);
2227
2228         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
2229                                                         "CDDM_calc_normals temp_nors");
2230
2231         /*recalc tesselation to ensure we have valid origindex values
2232           for mface->mpoly lookups.*/
2233         cdDM_recalcTesselation2(dm);
2234
2235         numFaces = dm->numFaceData;
2236
2237         /*first go through and calculate normals for all the polys*/
2238         temp_nors = MEM_callocN(sizeof(float)*3*dm->numPolyData, "temp_nors cdderivedmesh.c");
2239         vert_nors = MEM_callocN(sizeof(float)*3*dm->numVertData, "vert_nors cdderivedmesh.c");
2240         
2241         mp = cddm->mpoly;
2242         for (i=0; i<dm->numPolyData; i++, mp++) {
2243                 mesh_calc_poly_normal(mp, cddm->mloop+mp->loopstart, cddm->mvert, temp_nors[i]);
2244
2245                 ml = cddm->mloop + mp->loopstart;
2246                 for (j=0; j<mp->totloop; j++, ml++) {
2247                         VECADD(vert_nors[ml->v], vert_nors[ml->v], temp_nors[i]);
2248                 }
2249         }
2250
2251         face_nors = MEM_callocN(sizeof(float)*3*dm->numFaceData, "face_nors cdderivedmesh.c");
2252         origIndex = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
2253
2254         mf = cddm->mface;
2255         for (i=0; i<dm->numFaceData; i++, mf++, origIndex++) {
2256                 VECCOPY(face_nors[i], temp_nors[*origIndex]);
2257         }
2258
2259         mv = cddm->mvert;
2260         for (i=0; i<dm->numVertData; i++, mv++) {
2261                 float *no = vert_nors[i];
2262                 
2263                 if (normalize_v3(no) == 0.0) {
2264                         VECCOPY(no, mv->co);
2265                         if (normalize_v3(no) == 0.0) {
2266                                 no[0] = 0.0f;
2267                                 no[1] = 0.0f;
2268                                 no[2] = 1.0f;
2269                         }
2270                 }
2271
2272                 normal_float_to_short_v3(mv->no, no);
2273         }
2274
2275         MEM_freeN(temp_nors);
2276         MEM_freeN(vert_nors);
2277
2278         /*this restores original poly origindex -> tessface origindex mapping,
2279           instead of the poly index -> tessface origindex one we generated
2280           with cdDM_recalcTesselation2*/
2281         cdDM_recalcTesselation(dm);
2282         CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, 
2283                 face_nors, dm->numFaceData);
2284 }
2285
2286 #if 0
2287 /*merge verts
2288  
2289   vtargetmap is a table that maps vertices to target vertices.  a value of -1
2290   indicates a vertex is a target, and is to be kept.
2291   
2292   this is a really horribly written function.  ger. - joeedh
2293
2294  */
2295 DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap)
2296 {
2297         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2298         CDDerivedMesh *cddm2 = NULL;
2299         MVert *mv, *mvert = NULL;
2300         BLI_array_declare(mvert);
2301         MEdge *me, *medge = NULL;
2302         BLI_array_declare(medge);
2303         MPoly *mp, *mpoly = NULL;
2304         BLI_array_declare(mpoly);
2305         MLoop *ml, *mloop = NULL;
2306         BLI_array_declare(mloop);
2307         SmallHash _hash, *hash=&_hash;
2308         SmallHash _hash2, *hash2=&_hash2;
2309         int *newv = NULL, *newe = NULL, *newl = NULL;
2310         int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
2311         BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
2312         int i, j, c, totloop, totpoly;
2313         
2314         BLI_smallhash_init(hash);
2315         BLI_smallhash_init(hash2);
2316
2317 #if 0
2318         /*split off ngon faces with merges in them*/
2319         mp = cddm->mpoly;
2320         for (i=0; i<dm->numPolyData; i++, mp++) {
2321                 ml = cddm->mloop + mp->loopstart;
2322                 for (j=0; j<mp->totloop; j++, ml++) {
2323                         MLoop *ml2 = NULL;
2324                         int k, k1, a;
2325                         
2326                         if (ml->v == -1)
2327                                 continue;
2328                         
2329                         for (k1=0; k1<mp->totloop; k1++) {
2330                                 k = (j + k1) % mp->totloop;
2331                                 ml2 = cddm->mloop + mp->loopstart + k;
2332                                 
2333                                 if (ml == ml2 || ml2->v == -1)
2334                                         continue;
2335                                 
2336                                 if (vtargetmap[ml->v] == ml2->v || vtargetmap[ml2->v] == ml->v) {
2337                                         MLoop *ml3;
2338                                         MPoly *mp2;
2339                                         int s, e, l, tot;
2340                                         
2341                                         if (k < j) 
2342                                                 SWAP(int, k, j);
2343                                         
2344                                         s = j; e = k; tot = 0;
2345                                         l = BLI_array_count(mloop);
2346                                         ml3 = cddm->mloop + mp->loopstart + s;
2347                                         for (a=s; a<e; a++, ml3++) {
2348                                                 if (ml3->v == -1)
2349                                                         continue;
2350                                                 
2351                                                 BLI_smallhash_insert(hash, dm->numLoopData + BLI_array_count(mloop), SET_INT_IN_POINTER(mp->loopstart + a - s));
2352                                                 BLI_array_append(mloop, *ml3);
2353                                                 
2354                                                 ml3->v = -1;
2355                                                 ml3->e = -1;
2356                                                 tot++;
2357                                         }
2358                                         
2359                                         if (!tot)
2360                                                 continue;
2361                                         
2362                                         BLI_smallhash_insert(hash2, dm->numPolyData + BLI_array_count(mpoly), SET_INT_IN_POINTER(i));
2363         
2364                                         mp2 = BLI_array_append(mpoly, *mp);
2365                                         mp2->loopstart = l + dm->numLoopData;
2366                                         mp2->totloop = tot;
2367                                 }
2368                         }
2369                 }
2370         }
2371
2372         ml = MEM_callocN(sizeof(MLoop)*(dm->numLoopData + BLI_array_count(mloop)), "merge mloop");
2373         mp = MEM_callocN(sizeof(MPoly)*(dm->numPolyData + BLI_array_count(mloop)), "merge mpoly");
2374         
2375         memcpy(ml, cddm->mloop, sizeof(MLoop)*dm->numLoopData);
2376         memcpy(mp, cddm->mpoly, sizeof(MPoly)*dm->numPolyData);
2377         
2378         cddm->mloop = ml; cddm->mpoly = mp;
2379         
2380         memcpy(cddm->mloop+dm->numLoopData, mloop, sizeof(MLoop)*BLI_array_count(mloop));
2381         memcpy(cddm->mpoly+dm->numPolyData, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
2382         
2383         totloop = dm->numLoopData + BLI_array_count(mloop);
2384         totpoly = dm->numPolyData + BLI_array_count(mpoly);
2385         
2386         BLI_array_empty(mloop);
2387         BLI_array_empty(mpoly);
2388 #else
2389         totloop = dm->numLoopData;
2390         totpoly = dm->numPolyData;
2391 #endif
2392         
2393         newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts");
2394         newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts");
2395         newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts");
2396                 
2397         mv = cddm->mvert;
2398         c = 0;
2399         for (i=0; i<dm->numVertData; i++, mv++) {
2400                 if (vtargetmap[i] == -1) {
2401                         BLI_array_append(oldv, i);
2402                         newv[i] = c++;
2403                         BLI_array_append(mvert, *mv);
2404                 }
2405         }
2406         
2407         /*find-replace merged vertices with target vertices*/   
2408         ml = cddm->mloop;
2409         c = 0;
2410         for (i=0; i<totloop; i++, ml++) {
2411                 if (ml->v == -1)
2412                         continue;
2413                 
2414                 if (vtargetmap[ml->v] != -1) {
2415                         me = &cddm->medge[ml->e];
2416                         if (me->v1 == ml->v)
2417                                 me->v1 = vtargetmap[ml->v];
2418                         else
2419                                 me->v2 = vtargetmap[ml->v];
2420                         
2421                         ml->v = vtargetmap[ml->v];
2422                 }
2423         }
2424         
2425         /*now go through and fix edges and faces*/
2426         me = cddm->medge;
2427         c = 0;
2428         for (i=0; i<dm->numEdgeData; i++, me++) {
2429                 if (me->v1 == me->v2)
2430                         continue;
2431                 
2432                 BLI_array_append(olde, i);
2433                 newe[i] = c++;
2434                 BLI_array_append(medge, *me);
2435         }
2436         
2437         mp = cddm->mpoly;
2438         for (i=0; i<totpoly; i++, mp++) {
2439                 MPoly *mp2;
2440                 
2441                 ml = cddm->mloop + mp->loopstart;
2442                 
2443                 c = 0;
2444                 for (j=0; j<mp->totloop; j++, ml++) {
2445                         if (ml->v == -1)
2446                                 continue;
2447                         
2448                         me = cddm->medge + ml->e;
2449                         if (me->v1 != me->v2) {
2450                                 BLI_array_append(oldl, j);
2451                                 BLI_array_append(mloop, *ml);
2452                                 newl[c] = BLI_array_count(mloop)-1;
2453                                 c++;
2454                         }
2455                 }
2456                 
2457                 if (!c)
2458                         continue;
2459                 
2460                 mp2 = BLI_array_append(mpoly, *mp);
2461                 mp2->totloop = c;
2462                 mp2->loopstart = BLI_array_count(mloop) - c;
2463                 
2464                 BLI_array_append(oldp, i);
2465         }
2466         
2467         /*create new cddm*/     
2468         cddm2 = (CDDerivedMesh*) CDDM_new(BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
2469         
2470         /*copy over data.  CustomData_add_layer can do this, need to look it up.*/
2471         memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert));
2472         memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge));
2473         memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop));
2474         memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
2475         
2476         BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
2477         mvert = cddm2->mvert; medge = cddm2->medge; mloop = cddm2->mloop; mpoly = cddm2->mpoly;
2478         
2479         /*update edge indices and copy customdata*/
2480         me = cddm2->medge;
2481         for (i=0; i<cddm2->dm.numEdgeData; i++, me++) {
2482                 MEdge cpy;
2483                 
2484                 me->v1 = newv[me->v1];
2485                 me->v2 = newv[me->v2];
2486                 
2487                 cpy = *me;
2488                 CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1);
2489                 *me = cpy;
2490         }
2491         
2492         /*update loop indices and copy customdata*/
2493         ml = cddm2->mloop;
2494         for (i=0; i<cddm2->dm.numLoopData; i++, ml++) {
2495                 MLoop cpy;
2496                 
2497                 ml->e = newe[ml->e];
2498                 ml->v = newv[ml->v];
2499                         
2500                 cpy = *ml;
2501                 
2502                 if (oldl[i] >= dm->numLoopData)
2503                         oldl[i] = GET_INT_FROM_POINTER(BLI_smallhash_lookup(hash, (intptr_t)oldl[i]));
2504
2505                 CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
2506                 *ml = cpy;
2507         }
2508         
2509         /*copy vertex customdata*/      
2510         mv = cddm2->mvert;
2511         for (i=0; i<cddm2->dm.numVertData; i++, mv++) {
2512                 MVert cpy = *mv;
2513                 
2514                 CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1);
2515                 *mv = cpy;
2516         }
2517         
2518         /*copy poly customdata*/
2519         mp = cddm2->mpoly;
2520         for (i=0; i<cddm2->dm.numPolyData; i++, mp++) {
2521                 MPoly cpy = *mp;
2522                 
2523                 if (oldl[i] >= dm->numPolyData)
2524                         oldl[i] = GET_INT_FROM_POINTER(BLI_smallhash_lookup(hash, (intptr_t)oldl[i]));
2525
2526                 CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1);
2527                 *mp = cpy;
2528         }
2529         
2530         /*eek! not sure what to do with ORIGINDEX stuff here!!*/        
2531         cddm2->dm.numFaceData = mesh_recalcTesselation(&cddm2->dm.faceData, &cddm2->dm.loopData, &cddm2->dm.polyData, cddm2->mvert, 0, cddm2->dm.numLoopData, cddm2->dm.numPolyData, 1, 0);
2532         cddm2->mface = CustomData_get_layer(&cddm->dm.faceData, CD_MFACE);
2533         
2534         if (newv) 
2535                 MEM_freeN(newv); 
2536         if (newe)
2537                 MEM_freeN(newe); 
2538         if (newl)
2539                 MEM_freeN(newl);
2540         if (oldv) 
2541                 MEM_freeN(oldv); 
2542         if (olde) 
2543                 MEM_freeN(olde); 
2544         if (oldl) 
2545                 MEM_freeN(oldl); 
2546         if (oldp) 
2547                 MEM_freeN(oldp);
2548         
2549         BLI_smallhash_release(hash);
2550         BLI_smallhash_release(hash2);
2551         
2552         dm->needsFree = 1;
2553         dm->release(dm);
2554         
2555         return (DerivedMesh*)cddm2;
2556 }
2557 #endif
2558
2559 void CDDM_calc_edges(DerivedMesh *dm)
2560 {
2561         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2562         CustomData edgeData;
2563         EdgeHashIterator *ehi;
2564         MFace *mf = cddm->mface;
2565         MEdge *med;
2566         EdgeHash *eh = BLI_edgehash_new();
2567         int i, *index, numEdges, maxFaces = dm->numFaceData;
2568
2569         for (i = 0; i < maxFaces; i++, mf++) {
2570                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
2571                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
2572                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
2573                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
2574                 
2575                 if (mf->v4) {
2576                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
2577                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
2578                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
2579                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
2580                 } else {
2581                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
2582                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
2583                 }
2584         }
2585
2586         numEdges = BLI_edgehash_size(eh);
2587
2588         /* write new edges into a temporary CustomData */
2589         memset(&edgeData, 0, sizeof(edgeData));
2590         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2591         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2592
2593         ehi = BLI_edgehashIterator_new(eh);
2594         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2595         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2596         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2597                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2598                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2599
2600                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2601                 *index = ORIGINDEX_NONE;
2602         }
2603         BLI_edgehashIterator_free(ehi);
2604
2605         /* free old CustomData and assign new one */
2606         CustomData_free(&dm->edgeData, dm->numEdgeData);
2607         dm->edgeData = edgeData;
2608         dm->numEdgeData = numEdges;
2609
2610         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2611
2612         BLI_edgehash_free(eh, NULL);
2613 }
2614
2615
2616 void CDDM_calc_edges_poly(DerivedMesh *dm)
2617 {
2618         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2619         CustomData edgeData;
2620         EdgeHashIterator *ehi;
2621         MPoly *mp = cddm->mpoly;
2622         MLoop *ml;
2623         MEdge *med;
2624         EdgeHash *eh = BLI_edgehash_new();
2625         int v1, v2;
2626         int *eindex;
2627         int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
2628
2629         eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
2630
2631         med = cddm->medge;
2632         if (med) {
2633                 for (i=0; i < numEdges; i++, med++) {
2634                         BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
2635                 }
2636         }
2637
2638         for (i=0; i < maxFaces; i++, mp++) {
2639                 ml = cddm->mloop + mp->loopstart;
2640                 for (j=0; j<mp->totloop; j++, ml++) {
2641                         v1 = ml->v;
2642                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2643                         if (!BLI_edgehash_haskey(eh, v1, v2)) {
2644                                 BLI_edgehash_insert(eh, v1, v2, NULL);
2645                         }
2646                 }
2647         }
2648
2649         k = numEdges;
2650         numEdges = BLI_edgehash_size(eh);
2651
2652         /* write new edges into a temporary CustomData */
2653         memset(&edgeData, 0, sizeof(edgeData));
2654         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2655         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2656
2657         ehi = BLI_edgehashIterator_new(eh);
2658         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2659         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2660         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2661             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2662                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2663                 j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
2664
2665                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2666                 *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
2667
2668                 BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
2669         }
2670         BLI_edgehashIterator_free(ehi);
2671
2672         /* free old CustomData and assign new one */
2673         CustomData_free(&dm->edgeData, dm->numEdgeData);
2674         dm->edgeData = edgeData;
2675         dm->numEdgeData = numEdges;
2676
2677         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2678
2679         mp = cddm->mpoly;
2680         for (i=0; i < maxFaces; i++, mp++) {
2681                 ml = cddm->mloop + mp->loopstart;
2682                 for (j=0; j<mp->totloop; j++, ml++) {
2683                         v1 = ml->v;
2684                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2685                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
2686                 }
2687         }
2688
2689         BLI_edgehash_free(eh, NULL);
2690 }
2691
2692 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
2693 {
2694         if (numVerts < dm->numVertData)
2695                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
2696
2697         dm->numVertData = numVerts;
2698 }
2699
2700 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
2701 {
2702         if (numEdges < dm->numEdgeData)
2703                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
2704
2705         dm->numEdgeData = numEdges;
2706 }
2707
2708 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
2709 {
2710         if (numFaces < dm->numFaceData)
2711                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
2712
2713         dm->numFaceData = numFaces;
2714 }
2715
2716 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
2717 {
2718         return &((CDDerivedMesh*)dm)->mvert[index];
2719 }
2720
2721 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
2722 {
2723         return &((CDDerivedMesh*)dm)->medge[index];
2724 }
2725
2726 MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
2727 {
2728         return &((CDDerivedMesh*)dm)->mface[index];
2729 }
2730
2731 MVert *CDDM_get_verts(DerivedMesh *dm)
2732 {
2733         return ((CDDerivedMesh*)dm)->mvert;
2734 }
2735
2736 MEdge *CDDM_get_edges(DerivedMesh *dm)
2737 {
2738         return ((CDDerivedMesh*)dm)->medge;
2739 }
2740
2741 MFace *CDDM_get_tessfaces(DerivedMesh *dm)
2742 {
2743         return ((CDDerivedMesh*)dm)->mface;
2744 }
2745
2746 MPoly *CDDM_get_polys(DerivedMesh *dm)
2747 {
2748         return ((CDDerivedMesh*)dm)->mpoly;
2749 }
2750
2751 void CDDM_tessfaces_to_faces(DerivedMesh *dm)
2752 {
2753         /*converts mfaces to mpolys/mloops*/
2754         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2755         MFace *mf;
2756         MEdge *me;
2757         MLoop *ml;
2758         MPoly *mp;
2759         EdgeHash *eh = BLI_edgehash_new();
2760         int i, l, totloop, *index1, *index2;
2761         
2762         /*ensure we have all the edges we need*/
2763         CDDM_calc_edges(dm);
2764
2765         /*build edge hash*/
2766         me = cddm->medge;
2767         for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
2768                 BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
2769         }
2770
2771         mf = cddm->mface;
2772         totloop = 0;
2773         for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
2774                 totloop += mf->v4 ? 4 : 3;
2775         }
2776
2777         CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
2778         CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
2779         
2780         cddm->dm.numLoopData = totloop;
2781         cddm->dm.numPolyData = cddm->dm.numFaceData;
2782
2783         if (!totloop) return;
2784
2785         cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
2786         cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
2787         
2788         CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
2789         CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
2790         CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, 
2791                 CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData);
2792
2793         index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
2794         index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
2795
2796         mf = cddm->mface;
2797         mp = cddm->mpoly;
2798         ml = cddm->mloop;
2799         l = 0;
2800         for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
2801                 mp->flag = mf->flag;
2802                 mp->loopstart = l;
2803                 mp->mat_nr = mf->mat_nr;
2804                 mp->totloop = mf->v4 ? 4 : 3;
2805                 
2806                 ml->v = mf->v1;
2807                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
2808                 ml++, l++;
2809
2810                 ml->v = mf->v2;
2811                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
2812                 ml++, l++;
2813
2814                 ml->v = mf->v3;
2815                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
2816                 ml++, l++;
2817
2818                 if (mf->v4) {
2819                         ml->v = mf->v4;
2820                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
2821                         ml++, l++;
2822                 }
2823
2824         }
2825
2826         BLI_edgehash_free(eh, NULL);
2827 }
2828
2829 void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
2830 {
2831         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2832
2833         cddm->mvert = mvert;
2834 }
2835
2836 void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
2837 {
2838         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2839
2840         cddm->medge = medge;
2841 }
2842
2843 void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
2844 {
2845         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2846
2847         cddm->mface = mface;
2848 }