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