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