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