svn merge -r37078:37335 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_get_tessface_data_layer(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                         } /*else {
948                                 printf("eek in cddm draw mapped faces!\n");
949                         }*/
950                         
951                         if (nors) nors += 3;
952                 }
953         }
954         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
955                 int prevstart = 0;
956                 GPU_vertex_setup(dm);
957                 GPU_normal_setup(dm);
958                 if( useColors && mc )
959                         GPU_color_setup(dm);
960                 if( !GPU_buffer_legacy(dm) ) {
961                         int tottri = dm->drawObject->nelements/3;
962                         glShadeModel(GL_SMOOTH);
963                         
964                         if(tottri == 0) {
965                                 /* avoid buffer problems in following code */
966                         }
967                         if(setDrawOptions == NULL) {
968                                 /* just draw the entire face array */
969                                 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
970                         }
971                         else {
972                                 /* we need to check if the next material changes */
973                                 int next_actualFace= dm->drawObject->faceRemap[0];
974                                 
975                                 for( i = 0; i < tottri; i++ ) {
976                                         //int actualFace = dm->drawObject->faceRemap[i];
977                                         int actualFace = next_actualFace;
978                                         MFace *mface= mf + actualFace;
979                                         int drawSmooth= (mface->flag & ME_SMOOTH);
980                                         int draw = 1;
981
982                                         if(i != tottri-1)
983                                                 next_actualFace= dm->drawObject->faceRemap[i+1];
984
985                                         orig= (index==NULL) ? actualFace : index[actualFace];
986
987                                         if(orig == ORIGINDEX_NONE)
988                                                 draw= setMaterial(mface->mat_nr + 1, NULL);
989                                         else if (setDrawOptions != NULL)
990                                                 draw= setDrawOptions(userData, orig, &drawSmooth);
991         
992                                         /* Goal is to draw as long of a contiguous triangle
993                                            array as possible, so draw when we hit either an
994                                            invisible triangle or at the end of the array */
995                                         if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
996                                                 if(prevstart != i)
997                                                         /* Add one to the length (via `draw')
998                                                            if we're drawing at the end of the array */
999                                                         glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
1000                                                 prevstart = i + 1;
1001                                         }
1002                                 }
1003                         }
1004
1005                         glShadeModel(GL_FLAT);
1006                 }
1007                 GPU_buffer_unbind();
1008         }
1009 }
1010
1011 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1012 {
1013         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
1014 }
1015
1016 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
1017 {
1018         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1019         GPUVertexAttribs gattribs;
1020         DMVertexAttribs attribs;
1021         MVert *mvert = cddm->mvert;
1022         MFace *mface = cddm->mface;
1023         MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
1024         float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
1025         int a, b, dodraw, matnr, new_matnr;
1026         int transp, new_transp, orig_transp;
1027         int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1028
1029         cdDM_update_normals_from_pbvh(dm);
1030
1031         matnr = -1;
1032         dodraw = 0;
1033         transp = GPU_get_material_blend_mode();
1034         orig_transp = transp;
1035
1036         glShadeModel(GL_SMOOTH);
1037
1038         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1039                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1040                 memset(&attribs, 0, sizeof(attribs));
1041
1042                 glBegin(GL_QUADS);
1043
1044                 for(a = 0; a < dm->numFaceData; a++, mface++) {
1045                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1046                         new_matnr = mface->mat_nr + 1;
1047
1048                         if(new_matnr != matnr) {
1049                                 glEnd();
1050
1051                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1052                                 if(dodraw)
1053                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1054
1055                                 glBegin(GL_QUADS);
1056                         }
1057
1058                         if(!dodraw) {
1059                                 continue;
1060                         }
1061                         else if(setDrawOptions) {
1062                                 orig = (index)? index[a]: a;
1063
1064                                 if(orig == ORIGINDEX_NONE) {
1065                                         /* since the material is set by setMaterial(), faces with no
1066                                          * origin can be assumed to be generated by a modifier */ 
1067                                         
1068                                         /* continue */
1069                                 }
1070                                 else if(!setDrawOptions(userData, orig))
1071                                         continue;
1072                         }
1073
1074                         if(tf) {
1075                                 new_transp = tf[a].transp;
1076
1077                                 if(new_transp != transp) {
1078                                         glEnd();
1079
1080                                         if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1081                                                 GPU_set_material_blend_mode(orig_transp);
1082                                         else
1083                                                 GPU_set_material_blend_mode(new_transp);
1084                                         transp = new_transp;
1085
1086                                         glBegin(GL_QUADS);
1087                                 }
1088                         }
1089
1090                         if(!smoothnormal) {
1091                                 if(nors) {
1092                                         glNormal3fv(nors[a]);
1093                                 }
1094                                 else {
1095                                         /* TODO ideally a normal layer should always be available */
1096                                         float nor[3];
1097                                         if(mface->v4) {
1098                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1099                                         } else {
1100                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1101                                         }
1102                                         glNormal3fv(nor);
1103                                 }
1104                         }
1105
1106 #define PASSVERT(index, vert) {                                                                                                 \
1107                 if(attribs.totorco)                                                                                                                     \
1108                         glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
1109                 for(b = 0; b < attribs.tottface; b++) {                                                                         \
1110                         MTFace *tf = &attribs.tface[b].array[a];                                                                \
1111                         glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
1112                 }                                                                                                                                                       \
1113                 for(b = 0; b < attribs.totmcol; b++) {                                                                          \
1114                         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
1115                         GLubyte col[4];                                                                                                                 \
1116                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
1117                         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
1118                 }                                                                                                                                                       \
1119                 if(attribs.tottang) {                                                                                                           \
1120                         float *tang = attribs.tang.array[a*4 + vert];                                                   \
1121                         glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
1122                 }                                                                                                                                                       \
1123                 if(smoothnormal)                                                                                                                        \
1124                         glNormal3sv(mvert[index].no);                                                                                   \
1125                 glVertex3fv(mvert[index].co);                                                                                           \
1126         }
1127
1128                         PASSVERT(mface->v1, 0);
1129                         PASSVERT(mface->v2, 1);
1130                         PASSVERT(mface->v3, 2);
1131                         if(mface->v4)
1132                                 PASSVERT(mface->v4, 3)
1133                         else
1134                                 PASSVERT(mface->v3, 2)
1135
1136                 }
1137                 glEnd();
1138         }
1139         else {
1140                 GPUBuffer *buffer = NULL;
1141                 char *varray = NULL;
1142                 int numdata = 0, elementsize = 0, offset;
1143                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1144                 int i;
1145
1146                 MFace *mf = mface;
1147                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1148                 memset(&attribs, 0, sizeof(attribs));
1149
1150                 GPU_vertex_setup(dm);
1151                 GPU_normal_setup(dm);
1152
1153                 if( !GPU_buffer_legacy(dm) ) {
1154                         for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
1155
1156                                 a = dm->drawObject->faceRemap[i];
1157
1158                                 mface = mf + a;
1159                                 new_matnr = mface->mat_nr + 1;
1160
1161                                 if(new_matnr != matnr ) {
1162                                         numfaces = curface - start;
1163                                         if( numfaces > 0 ) {
1164
1165                                                 if( dodraw ) {
1166
1167                                                         if( numdata != 0 ) {
1168
1169                                                                 GPU_buffer_unlock(buffer);
1170
1171                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1172                                                         }
1173
1174                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1175
1176                                                         if( numdata != 0 ) {
1177
1178                                                                 GPU_buffer_free(buffer, NULL);
1179
1180                                                                 buffer = NULL;
1181                                                         }
1182
1183                                                 }
1184                                         }
1185                                         numdata = 0;
1186                                         start = curface;
1187                                         prevdraw = dodraw;
1188                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1189                                         if(dodraw) {
1190                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1191
1192                                                 if(attribs.totorco) {
1193                                                         datatypes[numdata].index = attribs.orco.glIndex;
1194                                                         datatypes[numdata].size = 3;
1195                                                         datatypes[numdata].type = GL_FLOAT;
1196                                                         numdata++;
1197                                                 }
1198                                                 for(b = 0; b < attribs.tottface; b++) {
1199                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1200                                                         datatypes[numdata].size = 2;
1201                                                         datatypes[numdata].type = GL_FLOAT;
1202                                                         numdata++;
1203                                                 }       
1204                                                 for(b = 0; b < attribs.totmcol; b++) {
1205                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1206                                                         datatypes[numdata].size = 4;
1207                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1208                                                         numdata++;
1209                                                 }       
1210                                                 if(attribs.tottang) {
1211                                                         datatypes[numdata].index = attribs.tang.glIndex;
1212                                                         datatypes[numdata].size = 4;
1213                                                         datatypes[numdata].type = GL_FLOAT;
1214                                                         numdata++;
1215                                                 }
1216                                                 if( numdata != 0 ) {
1217                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1218                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL );
1219                                                         if( buffer == NULL ) {
1220                                                                 GPU_buffer_unbind();
1221                                                                 dm->drawObject->legacy = 1;
1222                                                                 return;
1223                                                         }
1224                                                         varray = GPU_buffer_lock_stream(buffer);
1225                                                         if( varray == NULL ) {
1226                                                                 GPU_buffer_unbind();
1227                                                                 GPU_buffer_free(buffer, NULL);
1228                                                                 dm->drawObject->legacy = 1;
1229                                                                 return;
1230                                                         }
1231                                                 }
1232                                                 else {
1233                                                         /* if the buffer was set, dont use it again.
1234                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1235                                                         prevdraw= 0;
1236                                                         buffer= NULL;
1237                                                 }
1238                                         }
1239                                 }
1240                                 if(!dodraw) {
1241                                         continue;
1242                                 }
1243
1244                                 if(tf) {
1245                                         new_transp = tf[a].transp;
1246
1247                                         if(new_transp != transp) {
1248                                                 numfaces = curface - start;
1249                                                 if( numfaces > 0 ) {
1250                                                         if( dodraw ) {
1251                                                                 if( numdata != 0 ) {
1252                                                                         GPU_buffer_unlock(buffer);
1253                                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1254                                                                 }
1255                                                                 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1256                                                                 if( numdata != 0 ) {
1257                                                                         varray = GPU_buffer_lock_stream(buffer);
1258                                                                 }
1259                                                         }
1260                                                 }
1261                                                 start = curface;
1262
1263                                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1264                                                         GPU_set_material_blend_mode(orig_transp);
1265                                                 else
1266                                                         GPU_set_material_blend_mode(new_transp);
1267                                                 transp = new_transp;
1268                                         }
1269                                 }
1270                                 
1271                                 if( numdata != 0 ) {
1272                                         offset = 0;
1273                                         if(attribs.totorco) {
1274                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1275                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1276                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1277                                                 offset += sizeof(float)*3;
1278                                         }
1279                                         for(b = 0; b < attribs.tottface; b++) {
1280                                                 MTFace *tf = &attribs.tface[b].array[a];
1281                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1282                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1283
1284                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1285                                                 offset += sizeof(float)*2;
1286                                         }
1287                                         for(b = 0; b < attribs.totmcol; b++) {
1288                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1289                                                 GLubyte col[4];
1290                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1291                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1292                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1293                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1294                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1295                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1296                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1297                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1298                                                 offset += sizeof(unsigned char)*4;
1299                                         }       
1300                                         if(attribs.tottang) {
1301                                                 float *tang = attribs.tang.array[a*4 + 0];
1302                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1303                                                 tang = attribs.tang.array[a*4 + 1];
1304                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1305                                                 tang = attribs.tang.array[a*4 + 2];
1306                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1307                                                 offset += sizeof(float)*4;
1308                                         }
1309                                 }
1310                                 curface++;
1311                                 if(mface->v4) {
1312                                         if( numdata != 0 ) {
1313                                                 offset = 0;
1314                                                 if(attribs.totorco) {
1315                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1316                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1317                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1318                                                         offset += sizeof(float)*3;
1319                                                 }
1320                                                 for(b = 0; b < attribs.tottface; b++) {
1321                                                         MTFace *tf = &attribs.tface[b].array[a];
1322                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1323                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1324                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1325                                                         offset += sizeof(float)*2;
1326                                                 }
1327                                                 for(b = 0; b < attribs.totmcol; b++) {
1328                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1329                                                         GLubyte col[4];
1330                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1331                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1332                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1333                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1334                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1335                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1336                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1337                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1338                                                         offset += sizeof(unsigned char)*4;
1339                                                 }       
1340                                                 if(attribs.tottang) {
1341                                                         float *tang = attribs.tang.array[a*4 + 2];
1342                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1343                                                         tang = attribs.tang.array[a*4 + 3];
1344                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1345                                                         tang = attribs.tang.array[a*4 + 0];
1346                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1347                                                         offset += sizeof(float)*4;
1348                                                 }
1349                                         }
1350                                         curface++;
1351                                         i++;
1352                                 }
1353                         }
1354                         numfaces = curface - start;
1355                         if( numfaces > 0 ) {
1356                                 if( dodraw ) {
1357                                         if( numdata != 0 ) {
1358                                                 GPU_buffer_unlock(buffer);
1359                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1360                                         }
1361                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1362                                 }
1363                         }
1364                         GPU_buffer_unbind();
1365                 }
1366                 GPU_buffer_free( buffer, NULL );
1367         }
1368
1369         glShadeModel(GL_FLAT);
1370 }
1371
1372 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1373 {
1374         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1375 }
1376
1377 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1378 {
1379         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1380         MVert *vert = cddm->mvert;
1381         MEdge *edge = cddm->medge;
1382         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1383
1384         glBegin(GL_LINES);
1385         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1386                 if(index) {
1387                         orig = *index++;
1388                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1389                 }
1390                 else
1391                         orig = i;
1392
1393                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1394                         glVertex3fv(vert[edge->v1].co);
1395                         glVertex3fv(vert[edge->v2].co);
1396                 }
1397         }
1398         glEnd();
1399 }
1400
1401 static void cdDM_foreachMappedVert(
1402                                                    DerivedMesh *dm,
1403                                                    void (*func)(void *userData, int index, float *co,
1404                                                                                 float *no_f, short *no_s),
1405                                                    void *userData)
1406 {
1407         MVert *mv = CDDM_get_verts(dm);
1408         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1409
1410         for(i = 0; i < dm->numVertData; i++, mv++) {
1411                 if(index) {
1412                         orig = *index++;
1413                         if(orig == ORIGINDEX_NONE) continue;
1414                         func(userData, orig, mv->co, NULL, mv->no);
1415                 }
1416                 else
1417                         func(userData, i, mv->co, NULL, mv->no);
1418         }
1419 }
1420
1421 static void cdDM_foreachMappedEdge(
1422                                                    DerivedMesh *dm,
1423                                                    void (*func)(void *userData, int index,
1424                                                                                 float *v0co, float *v1co),
1425                                                    void *userData)
1426 {
1427         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1428         MVert *mv = cddm->mvert;
1429         MEdge *med = cddm->medge;
1430         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1431
1432         for(i = 0; i < dm->numEdgeData; i++, med++) {
1433                 if (index) {
1434                         orig = *index++;
1435                         if(orig == ORIGINDEX_NONE) continue;
1436                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1437                 }
1438                 else
1439                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1440         }
1441 }
1442
1443 static void cdDM_foreachMappedFaceCenter(
1444                                                    DerivedMesh *dm,
1445                                                    void (*func)(void *userData, int index,
1446                                                                                 float *cent, float *no),
1447                                                    void *userData)
1448 {
1449         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1450         MVert *mv = cddm->mvert;
1451         MPoly *mf = cddm->mpoly;
1452         MLoop *ml = cddm->mloop;
1453         int i, j, orig, *index;
1454
1455         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1456         mf = cddm->mpoly;
1457         for(i = 0; i < dm->numPolyData; i++, mf++) {
1458                 float cent[3];
1459                 float no[3];
1460
1461                 if (index) {
1462                         orig = *index++;
1463                         if(orig == ORIGINDEX_NONE) continue;
1464                 } else
1465                         orig = i;
1466                 
1467                 ml = &cddm->mloop[mf->loopstart];
1468                 cent[0] = cent[1] = cent[2] = 0.0f;
1469                 for (j=0; j<mf->totloop; j++, ml++) {
1470                         add_v3_v3v3(cent, cent, mv[ml->v].co);
1471                 }
1472                 mul_v3_fl(cent, 1.0f / (float)j);
1473
1474                 ml = &cddm->mloop[mf->loopstart];
1475                 if (j > 3) {
1476                         normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1477                                        mv[(ml+2)->v].co, mv[(ml+3)->v].co);
1478                 } else {
1479                         normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1480                                        mv[(ml+2)->v].co);
1481                 }
1482
1483                 func(userData, orig, cent, no);
1484         }
1485
1486 }
1487
1488 static void cdDM_recalcTesselation(DerivedMesh *dm)
1489 {
1490         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1491
1492         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1493                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1494                 dm->numPolyData, 1, 0);
1495         
1496         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1497 }
1498
1499 /*ignores original poly origindex layer*/
1500 static void cdDM_recalcTesselation2(DerivedMesh *dm)
1501 {
1502         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1503
1504         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1505                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1506                 dm->numPolyData, 0, 0);
1507         
1508         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1509 }
1510
1511 void CDDM_recalc_tesselation(DerivedMesh *dm, int orig_use_polyorig)
1512 {
1513         if (orig_use_polyorig)
1514                 cdDM_recalcTesselation(dm);
1515         else
1516                 cdDM_recalcTesselation2(dm);
1517 }
1518
1519 static void cdDM_free_internal(CDDerivedMesh *cddm)
1520 {
1521         if(cddm->fmap) MEM_freeN(cddm->fmap);
1522         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1523 }
1524
1525 static void cdDM_release(DerivedMesh *dm)
1526 {
1527         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1528
1529         if (DM_release(dm)) {
1530                 cdDM_free_internal(cddm);
1531                 MEM_freeN(cddm);
1532         }
1533 }
1534
1535 int CDDM_Check(DerivedMesh *dm)
1536 {
1537         return dm && dm->getMinMax == cdDM_getMinMax;
1538 }
1539
1540 /**************** CDDM interface functions ****************/
1541 static CDDerivedMesh *cdDM_create(const char *desc)
1542 {
1543         CDDerivedMesh *cddm;
1544         DerivedMesh *dm;
1545
1546         cddm = MEM_callocN(sizeof(*cddm), desc);
1547         dm = &cddm->dm;
1548
1549         dm->getMinMax = cdDM_getMinMax;
1550
1551         dm->getNumVerts = cdDM_getNumVerts;
1552         dm->getNumEdges = cdDM_getNumEdges;
1553         dm->getNumTessFaces = cdDM_getNumTessFaces;
1554         dm->getNumFaces = cdDM_getNumFaces;
1555
1556         dm->newFaceIter = cdDM_newFaceIter;
1557
1558         dm->getVert = cdDM_getVert;
1559         dm->getEdge = cdDM_getEdge;
1560         dm->getTessFace = cdDM_getFace;
1561         dm->copyVertArray = cdDM_copyVertArray;
1562         dm->copyEdgeArray = cdDM_copyEdgeArray;
1563         dm->copyTessFaceArray = cdDM_copyFaceArray;
1564         dm->getVertData = DM_get_vert_data;
1565         dm->getEdgeData = DM_get_edge_data;
1566         dm->getTessFaceData = DM_get_face_data;
1567         dm->getVertDataArray = DM_get_vert_data_layer;
1568         dm->getEdgeDataArray = DM_get_edge_data_layer;
1569         dm->getTessFaceDataArray = DM_get_tessface_data_layer;
1570         
1571         //doesn't work yet for all cases
1572         //dm->recalcTesselation = cdDM_recalcTesselation;
1573
1574         dm->getVertCos = cdDM_getVertCos;
1575         dm->getVertCo = cdDM_getVertCo;
1576         dm->getVertNo = cdDM_getVertNo;
1577
1578         dm->getPBVH = cdDM_getPBVH;
1579         dm->getFaceMap = cdDM_getFaceMap;
1580
1581         dm->drawVerts = cdDM_drawVerts;
1582
1583         dm->drawUVEdges = cdDM_drawUVEdges;
1584         dm->drawEdges = cdDM_drawEdges;
1585         dm->drawLooseEdges = cdDM_drawLooseEdges;
1586         dm->drawMappedEdges = cdDM_drawMappedEdges;
1587
1588         dm->drawFacesSolid = cdDM_drawFacesSolid;
1589         dm->drawFacesColored = cdDM_drawFacesColored;
1590         dm->drawFacesTex = cdDM_drawFacesTex;
1591         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1592         dm->drawMappedFaces = cdDM_drawMappedFaces;
1593         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1594         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1595
1596         dm->foreachMappedVert = cdDM_foreachMappedVert;
1597         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1598         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1599
1600         dm->release = cdDM_release;
1601
1602         return cddm;
1603 }
1604
1605 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
1606 {
1607         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1608         DerivedMesh *dm = &cddm->dm;
1609
1610         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
1611
1612         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1613         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1614         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1615         CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
1616
1617         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1618         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1619         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1620         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
1621         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
1622
1623         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1624         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1625         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1626         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1627         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1628
1629         return dm;
1630 }
1631
1632 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1633 {
1634         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1635         DerivedMesh *dm = &cddm->dm;
1636         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1637         int alloctype;
1638
1639         /* this does a referenced copy, with an exception for fluidsim */
1640
1641         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
1642                     mesh->totloop, mesh->totpoly);
1643
1644         dm->deformedOnly = 1;
1645
1646         alloctype= CD_REFERENCE;
1647
1648         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1649                                          mesh->totvert);
1650         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1651                                          mesh->totedge);
1652         CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype,
1653                                          mesh->totface);
1654         CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
1655                          mesh->totloop);
1656         CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
1657                          mesh->totpoly);
1658
1659         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1660         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1661         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1662         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1663         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1664
1665         if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
1666                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
1667
1668         return dm;
1669 }
1670
1671 static DerivedMesh *disabled__CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1672 {
1673         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1674                                    BLI_countlist(&em->edges),
1675                                    BLI_countlist(&em->faces), 0, 0);
1676         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1677         EditVert *eve;
1678         EditEdge *eed;
1679         EditFace *efa;
1680         MVert *mvert = cddm->mvert;
1681         MEdge *medge = cddm->medge;
1682         MFace *mface = cddm->mface;
1683         int i, *index;
1684
1685         dm->deformedOnly = 1;
1686
1687         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1688                                          CD_CALLOC, dm->numVertData);
1689         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1690                                          CD_CALLOC, dm->numEdgeData); */
1691         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1692                                          CD_CALLOC, dm->numFaceData);
1693         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1694                          CD_CALLOC, dm->numFaceData);
1695
1696         /* set eve->hash to vert index */
1697         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1698                 eve->tmp.l = i;
1699
1700         /* Need to be able to mark loose edges */
1701         for(eed = em->edges.first; eed; eed = eed->next) {
1702                 eed->f2 = 0;
1703         }
1704         for(efa = em->faces.first; efa; efa = efa->next) {
1705                 efa->e1->f2 = 1;
1706                 efa->e2->f2 = 1;
1707                 efa->e3->f2 = 1;
1708                 if(efa->e4) efa->e4->f2 = 1;
1709         }
1710
1711         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1712         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1713                 i++, eve = eve->next, index++) {
1714                 MVert *mv = &mvert[i];
1715
1716                 VECCOPY(mv->co, eve->co);
1717
1718                 normal_float_to_short_v3(mv->no, eve->no);
1719                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1720
1721                 mv->flag = 0;
1722
1723                 *index = i;
1724
1725                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1726         }
1727
1728         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1729         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1730                 i++, eed = eed->next, index++) {
1731                 MEdge *med = &medge[i];
1732
1733                 med->v1 = eed->v1->tmp.l;
1734                 med->v2 = eed->v2->tmp.l;
1735                 med->crease = (unsigned char) (eed->crease * 255.0f);
1736                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1737                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1738                 
1739                 if(eed->seam) med->flag |= ME_SEAM;
1740                 if(eed->sharp) med->flag |= ME_SHARP;
1741                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1742
1743                 *index = i;
1744
1745                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1746         }
1747
1748         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1749         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1750                 i++, efa = efa->next, index++) {
1751                 MFace *mf = &mface[i];
1752
1753                 mf->v1 = efa->v1->tmp.l;
1754                 mf->v2 = efa->v2->tmp.l;
1755                 mf->v3 = efa->v3->tmp.l;
1756                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1757                 mf->mat_nr = efa->mat_nr;
1758                 mf->flag = efa->flag;
1759
1760                 *index = i;
1761
1762                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1763                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1764         }
1765
1766         return dm;
1767 }
1768
1769 DerivedMesh *CDDM_from_curve(Object *ob)
1770 {
1771         return CDDM_from_curve_customDB(ob, &ob->disp);
1772 }
1773
1774 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1775 {
1776         DerivedMesh *dm;
1777         CDDerivedMesh *cddm;
1778         MVert *allvert;
1779         MEdge *alledge;
1780         MFace *allface;
1781         MLoop *allloop;
1782         MPoly *allpoly;
1783         int totvert, totedge, totface, totloop, totpoly;
1784
1785         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1786                 &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) {
1787                 /* Error initializing mdata. This often happens when curve is empty */
1788                 return CDDM_new(0, 0, 0, 0, 0);
1789         }
1790
1791         dm = CDDM_new(totvert, totedge, totface, totloop, totpoly);
1792         dm->deformedOnly = 1;
1793
1794         cddm = (CDDerivedMesh*)dm;
1795
1796         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1797         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1798         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1799         memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop));
1800         memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly));
1801
1802         MEM_freeN(allvert);
1803         MEM_freeN(alledge);
1804         MEM_freeN(allface);
1805         MEM_freeN(allloop);
1806         MEM_freeN(allpoly);
1807
1808         return dm;
1809 }
1810
1811 static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
1812                                           int cdindex, BMLoop *l3[3],
1813                                           int numCol, int numTex)
1814 {
1815         BMLoop *l;
1816         BMFace *f = l3[0]->f;
1817         MTFace *texface;
1818         MTexPoly *texpoly;
1819         MCol *mcol;
1820         MLoopCol *mloopcol;
1821         MLoopUV *mloopuv;
1822         int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
1823
1824         for(i=0; i < numTex; i++){
1825                 texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
1826                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
1827                 
1828                 texface->tpage = texpoly->tpage;
1829                 texface->flag = texpoly->flag;
1830                 texface->transp = texpoly->transp;
1831                 texface->mode = texpoly->mode;
1832                 texface->tile = texpoly->tile;
1833                 texface->unwrap = texpoly->unwrap;
1834         
1835                 for (j=0; j<3; j++) {
1836                         l = l3[j];
1837                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
1838                         texface->uv[j][0] = mloopuv->uv[0];
1839                         texface->uv[j][1] = mloopuv->uv[1];
1840                 }
1841         }
1842
1843         for(i=0; i < numCol; i++){
1844                 mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
1845                 
1846                 for (j=0; j<3; j++) {
1847                         l = l3[j];
1848                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
1849                         mcol[j].r = mloopcol->r;
1850                         mcol[j].g = mloopcol->g;
1851                         mcol[j].b = mloopcol->b;
1852                         mcol[j].a = mloopcol->a;
1853                 }
1854         }
1855
1856         if (hasWCol) {
1857                 mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
1858
1859                 for (j=0; j<3; j++) {
1860                         l = l3[j];
1861                         mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
1862                         mcol[j].r = mloopcol->r;
1863                         mcol[j].g = mloopcol->g;
1864                         mcol[j].b = mloopcol->b;
1865                         mcol[j].a = mloopcol->a;
1866                 }
1867         }
1868 }
1869
1870 DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps)
1871 {
1872         DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, 
1873                                em->tottri, em->bm->totloop, em->bm->totface);
1874         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1875         BMesh *bm = em->bm;
1876         BMIter iter, liter;
1877         BMVert *eve;
1878         BMEdge *eed;
1879         BMFace *efa;
1880         MVert *mvert = cddm->mvert;
1881         MEdge *medge = cddm->medge;
1882         MFace *mface = cddm->mface;
1883         MLoop *mloop = cddm->mloop;
1884         MPoly *mpoly = cddm->mpoly;
1885         int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
1886         int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
1887         int i, j, *index, add_orig;
1888         int has_crease, has_edge_bweight, has_vert_bweight;
1889         int flag;
1890         
1891         has_edge_bweight = CustomData_has_layer(&em->bm->edata, CD_BWEIGHT);
1892         has_vert_bweight = CustomData_has_layer(&em->bm->vdata, CD_BWEIGHT);
1893         has_crease = CustomData_has_layer(&em->bm->edata, CD_CREASE);
1894         
1895         dm->deformedOnly = 1;
1896         
1897         /*don't add origindex layer if one already exists*/
1898         add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
1899
1900         flag = use_mdisps ? CD_MASK_DERIVEDMESH|CD_MASK_MDISPS : CD_MASK_DERIVEDMESH;
1901         
1902         /*don't process shapekeys, we only feed them through the modifier stack as needed,
1903       e.g. for applying modifiers or the like*/
1904         flag &= ~CD_SHAPEKEY;
1905         CustomData_merge(&em->bm->vdata, &dm->vertData, flag,
1906                          CD_CALLOC, dm->numVertData);
1907         CustomData_merge(&em->bm->edata, &dm->edgeData, flag,
1908                          CD_CALLOC, dm->numEdgeData);
1909         CustomData_merge(&em->bm->ldata, &dm->loopData, flag,
1910                          CD_CALLOC, dm->numLoopData);
1911         CustomData_merge(&em->bm->pdata, &dm->polyData, flag,
1912                          CD_CALLOC, dm->numPolyData);
1913         
1914         /*add tesselation mface layers*/
1915         CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
1916
1917         /* set vert index */
1918         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1919         for (i=0; eve; eve=BMIter_Step(&iter), i++)
1920                 BM_SetIndex(eve, i);
1921
1922         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1923
1924         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1925         for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
1926                 MVert *mv = &mvert[i];
1927
1928                 VECCOPY(mv->co, eve->co);
1929
1930                 BM_SetIndex(eve, i);
1931
1932                 mv->no[0] = eve->no[0] * 32767.0;
1933                 mv->no[1] = eve->no[1] * 32767.0;
1934                 mv->no[2] = eve->no[2] * 32767.0;
1935
1936                 mv->flag = BMFlags_To_MEFlags(eve);
1937
1938                 if (has_vert_bweight)
1939                         mv->bweight = (unsigned char)(BM_GetCDf(&bm->vdata, eve, CD_BWEIGHT)*255.0f);
1940
1941                 if (add_orig) *index = i;
1942
1943                 CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
1944         }
1945
1946         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1947         eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1948         for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
1949                 MEdge *med = &medge[i];
1950
1951                 BM_SetIndex(eed, i);
1952
1953                 med->v1 = BM_GetIndex(eed->v1);
1954                 med->v2 = BM_GetIndex(eed->v2);
1955                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1956
1957                 if (has_crease)
1958                         med->crease = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_CREASE)*255.0f);
1959                 if (has_edge_bweight)
1960                         med->bweight = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_BWEIGHT)*255.0f);
1961                 
1962                 med->flag = BMFlags_To_MEFlags(eed);
1963
1964                 CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
1965                 if (add_orig) *index = i;
1966         }
1967
1968         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1969         for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
1970                 BM_SetIndex(efa, i);
1971         }
1972
1973         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1974         for(i = 0; i < dm->numFaceData; i++, index++) {
1975                 MFace *mf = &mface[i];
1976                 BMLoop **l = em->looptris[i];
1977                 efa = l[0]->f;
1978
1979                 mf->v1 = BM_GetIndex(l[0]->v);
1980                 mf->v2 = BM_GetIndex(l[1]->v);
1981                 mf->v3 = BM_GetIndex(l[2]->v);
1982                 mf->v4 = 0;
1983                 mf->mat_nr = efa->mat_nr;
1984                 mf->flag = BMFlags_To_MEFlags(efa);
1985                 
1986                 *index = add_orig ? BM_GetIndex(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
1987
1988                 loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
1989                 test_index_face(mf, &dm->faceData, i, 3);
1990         }
1991         
1992         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1993         j = 0;
1994         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1995         for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
1996                 BMLoop *l;
1997                 MPoly *mp = &mpoly[i];
1998
1999                 mp->totloop = efa->len;
2000                 mp->flag = BMFlags_To_MEFlags(efa);
2001                 mp->loopstart = j;
2002                 mp->mat_nr = efa->mat_nr;
2003                 
2004                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
2005                         mloop->v = BM_GetIndex(l->v);
2006                         mloop->e = BM_GetIndex(l->e);
2007                         CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
2008
2009                         j++;
2010                         mloop++;
2011                 }
2012
2013                 CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
2014
2015                 if (add_orig) *index = i;
2016         }
2017
2018         return dm;
2019 }
2020
2021 typedef struct CDDM_LoopIter {
2022         DMLoopIter head;
2023         CDDerivedMesh *cddm;
2024         int len, i;
2025 } CDDM_LoopIter;
2026
2027 typedef struct CDDM_FaceIter {
2028         DMFaceIter head;
2029         CDDerivedMesh *cddm;
2030         CDDM_LoopIter liter;
2031 } CDDM_FaceIter;
2032
2033 static void cddm_freeiter(void *self)
2034 {
2035         MEM_freeN(self);
2036 }
2037
2038 static void cddm_stepiter(void *self)
2039 {
2040         CDDM_FaceIter *iter = self;
2041         MPoly *mp;
2042         
2043         mp = iter->cddm->mpoly + iter->head.index;
2044         mp->flag = iter->head.flags;
2045         mp->mat_nr = iter->head.mat_nr;
2046
2047         iter->head.index++;
2048         if (iter->head.index >= iter->cddm->dm.numPolyData) {
2049                 iter->head.done = 1;
2050                 return;
2051         }
2052
2053         mp = iter->cddm->mpoly + iter->head.index;
2054
2055         iter->head.flags = mp->flag;
2056         iter->head.mat_nr = mp->mat_nr;
2057         iter->head.len = mp->totloop;
2058 }
2059
2060 static void *cddm_faceiter_getcddata(void *self, int type, int layer)
2061 {
2062         CDDM_FaceIter *iter = self;
2063
2064         if (layer == -1) return CustomData_get(&iter->cddm->dm.polyData, 
2065                                                iter->head.index, type);
2066         else return CustomData_get_n(&iter->cddm->dm.polyData, type, 
2067                                     iter->head.index, layer);
2068 }
2069
2070 static void *cddm_loopiter_getcddata(void *self, int type, int layer)
2071 {
2072         CDDM_LoopIter *iter = self;
2073
2074         if (layer == -1) return CustomData_get(&iter->cddm->dm.loopData, 
2075                                                iter->head.index, type);
2076         else return CustomData_get_n(&iter->cddm->dm.loopData, type, 
2077                                      iter->head.index, layer);
2078 }
2079
2080 static void *cddm_loopiter_getvertcddata(void *self, int type, int layer)
2081 {
2082         CDDM_LoopIter *iter = self;
2083
2084         if (layer == -1) return CustomData_get(&iter->cddm->dm.vertData, 
2085                                                iter->cddm->mloop[iter->head.index].v,
2086                                                type);
2087         else return CustomData_get_n(&iter->cddm->dm.vertData, type, 
2088                                      iter->cddm->mloop[iter->head.index].v, layer);
2089 }
2090
2091 static DMLoopIter *cddmiter_get_loopiter(void *self)
2092 {
2093         CDDM_FaceIter *iter = self;
2094         CDDM_LoopIter *liter = &iter->liter;
2095         MPoly *mp = iter->cddm->mpoly + iter->head.index;
2096
2097         liter->i = -1;
2098         liter->len = iter->head.len;
2099         liter->head.index = mp->loopstart-1;
2100         liter->head.done = 0;
2101
2102         liter->head.step(liter);
2103
2104         return (DMLoopIter*) liter;
2105 }
2106
2107 static void cddm_loopiter_step(void *self)
2108 {
2109         CDDM_LoopIter *liter = self;
2110         MLoop *ml;
2111
2112         liter->i++;
2113         liter->head.index++;
2114
2115         if (liter->i == liter->len) {
2116                 liter->head.done = 1;
2117                 return;
2118         }
2119
2120         ml = liter->cddm->mloop + liter->head.index;
2121
2122         liter->head.eindex = ml->e;
2123         liter->head.v = liter->cddm->mvert[ml->v];
2124         liter->head.vindex = ml->v;
2125 }
2126
2127 DMFaceIter *cdDM_newFaceIter(DerivedMesh *source)
2128 {
2129         CDDerivedMesh *cddm = (CDDerivedMesh*) source;
2130         CDDM_FaceIter *iter = MEM_callocN(sizeof(CDDM_FaceIter), "DMFaceIter from cddm");
2131
2132         iter->head.free = cddm_freeiter;
2133         iter->head.step = cddm_stepiter;
2134         iter->head.getCDData = cddm_faceiter_getcddata;
2135         iter->head.getLoopsIter = cddmiter_get_loopiter;
2136
2137         iter->liter.head.step = cddm_loopiter_step;
2138         iter->liter.head.getLoopCDData = cddm_loopiter_getcddata;
2139         iter->liter.head.getVertCDData = cddm_loopiter_getvertcddata;
2140         iter->liter.cddm = cddm;
2141
2142         iter->cddm = cddm;
2143
2144         if (source->numFaceData) {
2145                 iter->head.index = -1;
2146                 iter->head.step(iter);
2147         } else {
2148                 iter->head.done = 1;
2149         }
2150
2151         return (DMFaceIter*) iter;
2152 }
2153
2154 DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
2155 {
2156         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
2157         DerivedMesh *dm = &cddm->dm;
2158         int numVerts = source->numVertData;
2159         int numEdges = source->numEdgeData;
2160         int numFaces = source->numFaceData;
2161         int numLoops = source->numLoopData;
2162         int numPolys = source->numPolyData;
2163
2164         /* ensure these are created if they are made on demand */
2165         source->getVertDataArray(source, CD_ORIGINDEX);
2166         source->getEdgeDataArray(source, CD_ORIGINDEX);
2167         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2168
2169         /* this initializes dm, and copies all non mvert/medge/mface layers */
2170         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
2171                 numLoops, numPolys);
2172         dm->deformedOnly = source->deformedOnly;
2173
2174         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
2175         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
2176         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
2177
2178         /* now add mvert/medge/mface layers */
2179         cddm->mvert = source->dupVertArray(source);
2180         cddm->medge = source->dupEdgeArray(source);
2181         cddm->mface = source->dupTessFaceArray(source);
2182
2183         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
2184         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
2185         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
2186         
2187         if (!faces_from_tessfaces)
2188                 DM_DupPolys(source, dm);
2189         else
2190                 CDDM_tessfaces_to_faces(dm);
2191
2192         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2193         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2194         
2195         cdDM_recalcTesselation((DerivedMesh *)cddm);
2196         
2197         return dm;
2198 }
2199
2200 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
2201  * relationship betwen mesh data this needs to be set by the caller. */
2202 DerivedMesh *CDDM_from_template(DerivedMesh *source,
2203                                 int numVerts, int numEdges, int numFaces,
2204                                                                 int numLoops, int numPolys)
2205 {
2206         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
2207         DerivedMesh *dm = &cddm->dm;
2208
2209         /* ensure these are created if they are made on demand */
2210         source->getVertDataArray(source, CD_ORIGINDEX);
2211         source->getEdgeDataArray(source, CD_ORIGINDEX);
2212         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2213
2214         /* this does a copy of all non mvert/medge/mface layers */
2215         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
2216
2217         /* now add mvert/medge/mface layers */
2218         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
2219         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2220         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
2221         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
2222         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
2223
2224         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
2225                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
2226         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
2227                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2228         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
2229                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
2230
2231         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
2232         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2233         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
2234         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2235         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2236
2237         return dm;
2238 }
2239
2240 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
2241 {
2242         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2243         MVert *vert;
2244         int i;
2245
2246         /* this will just return the pointer if it wasn't a referenced layer */
2247         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2248         cddm->mvert = vert;
2249
2250         for(i = 0; i < dm->numVertData; ++i, ++vert)
2251                 VECCOPY(vert->co, vertCoords[i]);
2252 }
2253
2254 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
2255 {
2256         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2257         MVert *vert;
2258         int i;
2259
2260         /* this will just return the pointer if it wasn't a referenced layer */
2261         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2262         cddm->mvert = vert;
2263
2264         for(i = 0; i < dm->numVertData; ++i, ++vert)
2265                 VECCOPY(vert->no, vertNormals[i]);
2266 }
2267
2268 void CDDM_calc_normals(DerivedMesh *dm)
2269 {
2270         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2271         float (*face_nors)[3] = NULL;
2272         
2273         if(dm->numVertData == 0) return;
2274
2275         /* we don't want to overwrite any referenced layers */
2276         cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2277         
2278         /*set tesselation origindex values to map to poly indices, rather then poly
2279           poly origindex values*/
2280         cdDM_recalcTesselation2(dm);
2281         
2282         face_nors = MEM_mallocN(sizeof(float)*3*dm->numFaceData, "face_nors");
2283         
2284         /* calculate face normals */
2285         mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), 
2286                                           dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numFaceData, 
2287                                           CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors);
2288         
2289         /*restore tesselation origindex indices to poly origindex indices*/
2290         cdDM_recalcTesselation(dm);
2291
2292         CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, 
2293                 face_nors, dm->numFaceData);
2294 }
2295
2296 #if 1
2297 /*merge verts
2298  
2299   vtargetmap is a table that maps vertices to target vertices.  a value of -1
2300   indicates a vertex is a target, and is to be kept.
2301   
2302   this frees dm, and returns a new one.
2303   
2304   this is a really horribly written function.  ger. - joeedh
2305
2306  */
2307 DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap)
2308 {
2309         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2310         CDDerivedMesh *cddm2 = NULL;
2311         MVert *mv, *mvert = NULL;
2312         BLI_array_declare(mvert);
2313         MEdge *me, *medge = NULL;
2314         BLI_array_declare(medge);
2315         MPoly *mp, *mpoly = NULL;
2316         BLI_array_declare(mpoly);
2317         MLoop *ml, *mloop = NULL;
2318         BLI_array_declare(mloop);
2319         EdgeHash *ehash = BLI_edgehash_new();
2320         int *newv = NULL, *newe = NULL, *newl = NULL;
2321         int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
2322         BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
2323         int i, j, c, totloop, totpoly;
2324         
2325         totloop = dm->numLoopData;
2326         totpoly = dm->numPolyData;
2327         
2328         newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts");
2329         newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts");
2330         newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts");
2331         
2332         /*fill newl with destination vertex indices*/
2333         mv = cddm->mvert;
2334         c = 0;
2335         for (i=0; i<dm->numVertData; i++, mv++) {
2336                 if (vtargetmap[i] == -1) {
2337                         BLI_array_append(oldv, i);
2338                         newv[i] = c++;
2339                         BLI_array_append(mvert, *mv);
2340                 }
2341         }
2342         
2343         /*now link target vertices to destination indices*/
2344         for (i=0; i<dm->numVertData; i++) {
2345                 if (vtargetmap[i] != -1) {
2346                         newv[i] = newv[vtargetmap[i]];
2347                 }
2348         }
2349         
2350         /*find-replace merged vertices with target vertices*/   
2351         ml = cddm->mloop;
2352         c = 0;
2353         for (i=0; i<totloop; i++, ml++) {
2354                 if (ml->v == -1)
2355                         continue;
2356                 
2357                 if (vtargetmap[ml->v] != -1) {
2358                         me = &cddm->medge[ml->e];
2359                         if (me->v1 == ml->v)
2360                                 me->v1 = vtargetmap[ml->v];
2361                         else
2362                                 me->v2 = vtargetmap[ml->v];
2363                         
2364                         ml->v = vtargetmap[ml->v];
2365                 }
2366         }
2367         
2368         /*now go through and fix edges and faces*/
2369         me = cddm->medge;
2370         c = 0;
2371         for (i=0; i<dm->numEdgeData; i++, me++) {
2372                 int v1, v2;
2373                 
2374                 if (me->v1 == me->v2) {
2375                         newe[i] = -1;
2376                         continue;
2377                 }
2378                 
2379                 if (vtargetmap[me->v1] != -1)
2380                         v1 = vtargetmap[me->v1];
2381                 else
2382                         v1 = me->v1;
2383                 
2384                 if (vtargetmap[me->v2] != -1)
2385                         v2 = vtargetmap[me->v2];
2386                 else
2387                         v2 = me->v2;
2388                 
2389                 if (BLI_edgehash_haskey(ehash, v1, v2)) {
2390                         newe[i] = GET_INT_FROM_POINTER(BLI_edgehash_lookup(ehash, v1, v2));
2391                 } else {
2392                         BLI_array_append(olde, i);
2393                         newe[i] = c;
2394                         BLI_array_append(medge, *me);
2395                         BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c));
2396                         c++;
2397                 }
2398         }
2399         
2400         mp = cddm->mpoly;
2401         for (i=0; i<totpoly; i++, mp++) {
2402                 MPoly *mp2;
2403                 
2404                 ml = cddm->mloop + mp->loopstart;
2405                 
2406                 c = 0;
2407                 for (j=0; j<mp->totloop; j++, ml++) {
2408                         if (ml->v == -1)
2409                                 continue;
2410                         
2411                         me = cddm->medge + ml->e;
2412                         if (me->v1 != me->v2) {
2413                                 BLI_array_append(oldl, j+mp->loopstart);
2414                                 BLI_array_append(mloop, *ml);
2415                                 newl[j+mp->loopstart] = BLI_array_count(mloop)-1;
2416                                 c++;
2417                         }
2418                 }
2419                 
2420                 if (!c)
2421                         continue;
2422                 
2423                 mp2 = BLI_array_append(mpoly, *mp);
2424                 mp2->totloop = c;
2425                 mp2->loopstart = BLI_array_count(mloop) - c;
2426                 
2427                 BLI_array_append(oldp, i);
2428         }
2429         
2430         /*create new cddm*/     
2431         cddm2 = (CDDerivedMesh*) CDDM_from_template((DerivedMesh*)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
2432         
2433         /*update edge indices and copy customdata*/
2434         me = medge;
2435         for (i=0; i<cddm2->dm.numEdgeData; i++, me++) {
2436                 if (newv[me->v1] != -1)
2437                         me->v1 = newv[me->v1];
2438                 if (newv[me->v2] != -1)
2439                         me->v2 = newv[me->v2];
2440                 
2441                 CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1);
2442         }
2443         
2444         /*update loop indices and copy customdata*/
2445         ml = mloop;
2446         for (i=0; i<cddm2->dm.numLoopData; i++, ml++) {
2447                 if (newe[ml->e] != -1)
2448                         ml->e = newe[ml->e];
2449                 if (newv[ml->v] != -1)
2450                         ml->v = newv[ml->v];
2451                         
2452                 CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
2453         }
2454         
2455         /*copy vertex customdata*/      
2456         mv = mvert;
2457         for (i=0; i<cddm2->dm.numVertData; i++, mv++) {
2458                 CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1);
2459         }
2460         
2461         /*copy poly customdata*/
2462         mp = mpoly;
2463         for (i=0; i<cddm2->dm.numPolyData; i++, mp++) {
2464                 CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1);
2465         }
2466         
2467         /*copy over data.  CustomData_add_layer can do this, need to look it up.*/
2468         memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert));
2469         memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge));
2470         memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop));
2471         memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
2472         BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
2473
2474         CDDM_recalc_tesselation((DerivedMesh*)cddm2, 1);
2475         
2476         if (newv) 
2477                 MEM_freeN(newv); 
2478         if (newe)
2479                 MEM_freeN(newe); 
2480         if (newl)
2481                 MEM_freeN(newl);
2482         if (oldv) 
2483                 MEM_freeN(oldv); 
2484         if (olde) 
2485                 MEM_freeN(olde); 
2486         if (oldl) 
2487                 MEM_freeN(oldl); 
2488         if (oldp) 
2489                 MEM_freeN(oldp);
2490         if (ehash)
2491                 BLI_edgehash_free(ehash, NULL);
2492
2493         /*free old derivedmesh*/
2494         dm->needsFree = 1;
2495         dm->release(dm);
2496         
2497         return (DerivedMesh*)cddm2;
2498 }
2499 #endif
2500
2501 void CDDM_calc_edges(DerivedMesh *dm)
2502 {
2503         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2504         CustomData edgeData;
2505         EdgeHashIterator *ehi;
2506         MFace *mf = cddm->mface;
2507         MEdge *med;
2508         EdgeHash *eh = BLI_edgehash_new();
2509         int i, *index, numEdges, maxFaces = dm->numFaceData;
2510
2511         for (i = 0; i < maxFaces; i++, mf++) {
2512                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
2513                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
2514                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
2515                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
2516                 
2517                 if (mf->v4) {
2518                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
2519                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
2520                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
2521                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
2522                 } else {
2523                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
2524                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
2525                 }
2526         }
2527
2528         numEdges = BLI_edgehash_size(eh);
2529
2530         /* write new edges into a temporary CustomData */
2531         memset(&edgeData, 0, sizeof(edgeData));
2532         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2533         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2534
2535         ehi = BLI_edgehashIterator_new(eh);
2536         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2537         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2538         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2539                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2540                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2541
2542                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2543                 *index = ORIGINDEX_NONE;
2544         }
2545         BLI_edgehashIterator_free(ehi);
2546
2547         /* free old CustomData and assign new one */
2548         CustomData_free(&dm->edgeData, dm->numEdgeData);
2549         dm->edgeData = edgeData;
2550         dm->numEdgeData = numEdges;
2551
2552         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2553
2554         BLI_edgehash_free(eh, NULL);
2555 }
2556
2557
2558 void CDDM_calc_edges_poly(DerivedMesh *dm)
2559 {
2560         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2561         CustomData edgeData;
2562         EdgeHashIterator *ehi;
2563         MPoly *mp = cddm->mpoly;
2564         MLoop *ml;
2565         MEdge *med;
2566         EdgeHash *eh = BLI_edgehash_new();
2567         int v1, v2;
2568         int *eindex;
2569         int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
2570
2571         eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
2572
2573         med = cddm->medge;
2574         if (med) {
2575                 for (i=0; i < numEdges; i++, med++) {
2576                         BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
2577                 }
2578         }
2579
2580         for (i=0; i < maxFaces; i++, mp++) {
2581                 ml = cddm->mloop + mp->loopstart;
2582                 for (j=0; j<mp->totloop; j++, ml++) {
2583                         v1 = ml->v;
2584                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2585                         if (!BLI_edgehash_haskey(eh, v1, v2)) {
2586                                 BLI_edgehash_insert(eh, v1, v2, NULL);
2587                         }
2588                 }
2589         }
2590
2591         k = numEdges;
2592         numEdges = BLI_edgehash_size(eh);
2593
2594         /* write new edges into a temporary CustomData */
2595         memset(&edgeData, 0, sizeof(edgeData));
2596         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2597         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2598
2599         ehi = BLI_edgehashIterator_new(eh);
2600         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2601         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2602         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2603             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2604                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2605                 j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
2606
2607                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2608                 *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
2609
2610                 BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
2611         }
2612         BLI_edgehashIterator_free(ehi);
2613
2614         /* free old CustomData and assign new one */
2615         CustomData_free(&dm->edgeData, dm->numEdgeData);
2616         dm->edgeData = edgeData;
2617         dm->numEdgeData = numEdges;
2618
2619         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2620
2621         mp = cddm->mpoly;
2622         for (i=0; i < maxFaces; i++, mp++) {
2623                 ml = cddm->mloop + mp->loopstart;
2624                 for (j=0; j<mp->totloop; j++, ml++) {
2625                         v1 = ml->v;
2626                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2627                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
2628                 }
2629         }
2630
2631         BLI_edgehash_free(eh, NULL);
2632 }
2633
2634 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
2635 {
2636         if (numVerts < dm->numVertData)
2637                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
2638
2639         dm->numVertData = numVerts;
2640 }
2641
2642 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
2643 {
2644         if (numEdges < dm->numEdgeData)
2645                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
2646
2647         dm->numEdgeData = numEdges;
2648 }
2649
2650 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
2651 {
2652         if (numFaces < dm->numFaceData)
2653                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
2654
2655         dm->numFaceData = numFaces;
2656 }
2657
2658 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
2659 {
2660         return &((CDDerivedMesh*)dm)->mvert[index];
2661 }
2662
2663 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
2664 {
2665         return &((CDDerivedMesh*)dm)->medge[index];
2666 }
2667
2668 MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
2669 {
2670         return &((CDDerivedMesh*)dm)->mface[index];
2671 }
2672
2673 MVert *CDDM_get_verts(DerivedMesh *dm)
2674 {
2675         return ((CDDerivedMesh*)dm)->mvert;
2676 }
2677
2678 MEdge *CDDM_get_edges(DerivedMesh *dm)
2679 {
2680         return ((CDDerivedMesh*)dm)->medge;
2681 }
2682
2683 MFace *CDDM_get_tessfaces(DerivedMesh *dm)
2684 {
2685         return ((CDDerivedMesh*)dm)->mface;
2686 }
2687
2688 MLoop *CDDM_get_loops(DerivedMesh *dm)
2689 {
2690         return ((CDDerivedMesh*)dm)->mloop;
2691 }
2692
2693 MPoly *CDDM_get_polys(DerivedMesh *dm)
2694 {
2695         return ((CDDerivedMesh*)dm)->mpoly;
2696 }
2697
2698 void CDDM_tessfaces_to_faces(DerivedMesh *dm)
2699 {
2700         /*converts mfaces to mpolys/mloops*/
2701         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2702         MFace *mf;
2703         MEdge *me;
2704         MLoop *ml;
2705         MPoly *mp;
2706         EdgeHash *eh = BLI_edgehash_new();
2707         int i, l, totloop, *index1, *index2;
2708         
2709         /*ensure we have all the edges we need*/
2710         CDDM_calc_edges(dm);
2711
2712         /*build edge hash*/
2713         me = cddm->medge;
2714         for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
2715                 BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
2716         }
2717
2718         mf = cddm->mface;
2719         totloop = 0;
2720         for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
2721                 totloop += mf->v4 ? 4 : 3;
2722         }
2723
2724         CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
2725         CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
2726         
2727         cddm->dm.numLoopData = totloop;
2728         cddm->dm.numPolyData = cddm->dm.numFaceData;
2729
2730         if (!totloop) return;
2731
2732         cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
2733         cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
2734         
2735         CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
2736         CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
2737         CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, 
2738                 CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData);
2739
2740         index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
2741         index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
2742
2743         mf = cddm->mface;
2744         mp = cddm->mpoly;
2745         ml = cddm->mloop;
2746         l = 0;
2747         for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
2748                 mp->flag = mf->flag;
2749                 mp->loopstart = l;
2750                 mp->mat_nr = mf->mat_nr;
2751                 mp->totloop = mf->v4 ? 4 : 3;
2752                 
2753                 ml->v = mf->v1;
2754                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
2755                 ml++, l++;
2756
2757                 ml->v = mf->v2;
2758                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
2759                 ml++, l++;
2760
2761                 ml->v = mf->v3;
2762                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
2763                 ml++, l++;
2764
2765                 if (mf->v4) {
2766                         ml->v = mf->v4;
2767                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
2768                         ml++, l++;
2769                 }
2770
2771         }
2772
2773         BLI_edgehash_free(eh, NULL);
2774 }
2775
2776 void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
2777 {
2778         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2779         
2780         if (!CustomData_has_layer(&dm->vertData, CD_MVERT))
2781                 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData);
2782                                 
2783         cddm->mvert = mvert;
2784 }
2785
2786 void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
2787 {
2788         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2789
2790         if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE))
2791                 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData);
2792
2793         cddm->medge = medge;
2794 }
2795
2796 void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
2797 {
2798         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2799
2800         if (!CustomData_has_layer(&dm->faceData, CD_MFACE))
2801                 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numFaceData);
2802
2803         cddm->mface = mface;
2804 }