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