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