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