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