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