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