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