BGE Animations: Fixing some refcount issues with KX_Scene::m_animatedlist (fixes...
[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);
1064         float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
1065         int a, b, dodraw, matnr, new_matnr;
1066         int transp, new_transp, orig_transp;
1067         int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1068
1069         cdDM_update_normals_from_pbvh(dm);
1070
1071         matnr = -1;
1072         dodraw = 0;
1073         transp = GPU_get_material_blend_mode();
1074         orig_transp = transp;
1075
1076         glShadeModel(GL_SMOOTH);
1077
1078         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1079                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1080                 memset(&attribs, 0, sizeof(attribs));
1081
1082                 glBegin(GL_QUADS);
1083
1084                 for(a = 0; a < dm->numFaceData; a++, mface++) {
1085                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1086                         new_matnr = mface->mat_nr + 1;
1087
1088                         if(new_matnr != matnr) {
1089                                 glEnd();
1090
1091                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1092                                 if(dodraw)
1093                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1094
1095                                 glBegin(GL_QUADS);
1096                         }
1097
1098                         if(!dodraw) {
1099                                 continue;
1100                         }
1101                         else if(setDrawOptions) {
1102                                 orig = (index)? index[a]: a;
1103
1104                                 if(orig == ORIGINDEX_NONE) {
1105                                         /* since the material is set by setMaterial(), faces with no
1106                                          * origin can be assumed to be generated by a modifier */ 
1107                                         
1108                                         /* continue */
1109                                 }
1110                                 else if(!setDrawOptions(userData, orig))
1111                                         continue;
1112                         }
1113
1114                         if(tf) {
1115                                 new_transp = tf[a].transp;
1116
1117                                 if(new_transp != transp) {
1118                                         glEnd();
1119
1120                                         if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1121                                                 GPU_set_material_blend_mode(orig_transp);
1122                                         else
1123                                                 GPU_set_material_blend_mode(new_transp);
1124                                         transp = new_transp;
1125
1126                                         glBegin(GL_QUADS);
1127                                 }
1128                         }
1129
1130                         if(!smoothnormal) {
1131                                 if(nors) {
1132                                         glNormal3fv(nors[a]);
1133                                 }
1134                                 else {
1135                                         /* TODO ideally a normal layer should always be available */
1136                                         float nor[3];
1137                                         if(mface->v4) {
1138                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1139                                         } else {
1140                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1141                                         }
1142                                         glNormal3fv(nor);
1143                                 }
1144                         }
1145
1146                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal);
1147                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal);
1148                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1149
1150                         if(mface->v4)
1151                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal);
1152                         else
1153                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1154                 }
1155                 glEnd();
1156         }
1157         else {
1158                 GPUBuffer *buffer = NULL;
1159                 char *varray = NULL;
1160                 int numdata = 0, elementsize = 0, offset;
1161                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1162                 int i;
1163
1164                 MFace *mf = mface;
1165                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1166                 memset(&attribs, 0, sizeof(attribs));
1167
1168                 GPU_vertex_setup(dm);
1169                 GPU_normal_setup(dm);
1170
1171                 if( !GPU_buffer_legacy(dm) ) {
1172                         for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
1173
1174                                 a = dm->drawObject->triangle_to_mface[i];
1175
1176                                 mface = mf + a;
1177                                 new_matnr = mface->mat_nr + 1;
1178
1179                                 if(new_matnr != matnr ) {
1180                                         numfaces = curface - start;
1181                                         if( numfaces > 0 ) {
1182
1183                                                 if( dodraw ) {
1184
1185                                                         if( numdata != 0 ) {
1186
1187                                                                 GPU_buffer_unlock(buffer);
1188
1189                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1190                                                         }
1191
1192                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1193
1194                                                         if( numdata != 0 ) {
1195
1196                                                                 GPU_buffer_free(buffer);
1197
1198                                                                 buffer = NULL;
1199                                                         }
1200
1201                                                 }
1202                                         }
1203                                         numdata = 0;
1204                                         start = curface;
1205                                         prevdraw = dodraw;
1206                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1207                                         if(dodraw) {
1208                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1209
1210                                                 if(attribs.totorco) {
1211                                                         datatypes[numdata].index = attribs.orco.glIndex;
1212                                                         datatypes[numdata].size = 3;
1213                                                         datatypes[numdata].type = GL_FLOAT;
1214                                                         numdata++;
1215                                                 }
1216                                                 for(b = 0; b < attribs.tottface; b++) {
1217                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1218                                                         datatypes[numdata].size = 2;
1219                                                         datatypes[numdata].type = GL_FLOAT;
1220                                                         numdata++;
1221                                                 }       
1222                                                 for(b = 0; b < attribs.totmcol; b++) {
1223                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1224                                                         datatypes[numdata].size = 4;
1225                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1226                                                         numdata++;
1227                                                 }       
1228                                                 if(attribs.tottang) {
1229                                                         datatypes[numdata].index = attribs.tang.glIndex;
1230                                                         datatypes[numdata].size = 4;
1231                                                         datatypes[numdata].type = GL_FLOAT;
1232                                                         numdata++;
1233                                                 }
1234                                                 if( numdata != 0 ) {
1235                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1236                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
1237                                                         if( buffer == NULL ) {
1238                                                                 GPU_buffer_unbind();
1239                                                                 dm->drawObject->legacy = 1;
1240                                                                 return;
1241                                                         }
1242                                                         varray = GPU_buffer_lock_stream(buffer);
1243                                                         if( varray == NULL ) {
1244                                                                 GPU_buffer_unbind();
1245                                                                 GPU_buffer_free(buffer);
1246                                                                 dm->drawObject->legacy = 1;
1247                                                                 return;
1248                                                         }
1249                                                 }
1250                                                 else {
1251                                                         /* if the buffer was set, dont use it again.
1252                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1253                                                         prevdraw= 0;
1254                                                         buffer= NULL;
1255                                                 }
1256                                         }
1257                                 }
1258                                 if(!dodraw) {
1259                                         continue;
1260                                 }
1261
1262                                 if(tf) {
1263                                         new_transp = tf[a].transp;
1264
1265                                         if(new_transp != transp) {
1266                                                 numfaces = curface - start;
1267                                                 if( numfaces > 0 ) {
1268                                                         if( dodraw ) {
1269                                                                 if( numdata != 0 ) {
1270                                                                         GPU_buffer_unlock(buffer);
1271                                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1272                                                                 }
1273                                                                 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1274                                                                 if( numdata != 0 ) {
1275                                                                         varray = GPU_buffer_lock_stream(buffer);
1276                                                                 }
1277                                                         }
1278                                                 }
1279                                                 start = curface;
1280
1281                                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1282                                                         GPU_set_material_blend_mode(orig_transp);
1283                                                 else
1284                                                         GPU_set_material_blend_mode(new_transp);
1285                                                 transp = new_transp;
1286                                         }
1287                                 }
1288                                 
1289                                 if( numdata != 0 ) {
1290                                         offset = 0;
1291                                         if(attribs.totorco) {
1292                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1293                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1294                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1295                                                 offset += sizeof(float)*3;
1296                                         }
1297                                         for(b = 0; b < attribs.tottface; b++) {
1298                                                 MTFace *tf = &attribs.tface[b].array[a];
1299                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1300                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1301
1302                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1303                                                 offset += sizeof(float)*2;
1304                                         }
1305                                         for(b = 0; b < attribs.totmcol; b++) {
1306                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1307                                                 GLubyte col[4];
1308                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1309                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1310                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1311                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1312                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1313                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1314                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1315                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1316                                                 offset += sizeof(unsigned char)*4;
1317                                         }       
1318                                         if(attribs.tottang) {
1319                                                 float *tang = attribs.tang.array[a*4 + 0];
1320                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1321                                                 tang = attribs.tang.array[a*4 + 1];
1322                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1323                                                 tang = attribs.tang.array[a*4 + 2];
1324                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1325                                                 offset += sizeof(float)*4;
1326                                         }
1327                                         (void)offset;
1328                                 }
1329                                 curface++;
1330                                 if(mface->v4) {
1331                                         if( numdata != 0 ) {
1332                                                 offset = 0;
1333                                                 if(attribs.totorco) {
1334                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1335                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1336                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1337                                                         offset += sizeof(float)*3;
1338                                                 }
1339                                                 for(b = 0; b < attribs.tottface; b++) {
1340                                                         MTFace *tf = &attribs.tface[b].array[a];
1341                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1342                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1343                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1344                                                         offset += sizeof(float)*2;
1345                                                 }
1346                                                 for(b = 0; b < attribs.totmcol; b++) {
1347                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1348                                                         GLubyte col[4];
1349                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1350                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1351                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1352                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1353                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1354                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1355                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1356                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1357                                                         offset += sizeof(unsigned char)*4;
1358                                                 }       
1359                                                 if(attribs.tottang) {
1360                                                         float *tang = attribs.tang.array[a*4 + 2];
1361                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1362                                                         tang = attribs.tang.array[a*4 + 3];
1363                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1364                                                         tang = attribs.tang.array[a*4 + 0];
1365                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1366                                                         offset += sizeof(float)*4;
1367                                                 }
1368                                                 (void)offset;
1369                                         }
1370                                         curface++;
1371                                         i++;
1372                                 }
1373                         }
1374                         numfaces = curface - start;
1375                         if( numfaces > 0 ) {
1376                                 if( dodraw ) {
1377                                         if( numdata != 0 ) {
1378                                                 GPU_buffer_unlock(buffer);
1379                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1380                                         }
1381                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1382                                 }
1383                         }
1384                         GPU_buffer_unbind();
1385                 }
1386                 GPU_buffer_free(buffer);
1387         }
1388
1389         glShadeModel(GL_FLAT);
1390 }
1391
1392 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1393 {
1394         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1395 }
1396
1397 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1398 {
1399         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1400         MVert *vert = cddm->mvert;
1401         MEdge *edge = cddm->medge;
1402         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1403
1404         glBegin(GL_LINES);
1405         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1406                 if(index) {
1407                         orig = *index++;
1408                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1409                 }
1410                 else
1411                         orig = i;
1412
1413                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1414                         glVertex3fv(vert[edge->v1].co);
1415                         glVertex3fv(vert[edge->v2].co);
1416                 }
1417         }
1418         glEnd();
1419 }
1420
1421 static void cdDM_foreachMappedVert(
1422                                                    DerivedMesh *dm,
1423                                                    void (*func)(void *userData, int index, float *co,
1424                                                                                 float *no_f, short *no_s),
1425                                                    void *userData)
1426 {
1427         MVert *mv = CDDM_get_verts(dm);
1428         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1429
1430         for(i = 0; i < dm->numVertData; i++, mv++) {
1431                 if(index) {
1432                         orig = *index++;
1433                         if(orig == ORIGINDEX_NONE) continue;
1434                         func(userData, orig, mv->co, NULL, mv->no);
1435                 }
1436                 else
1437                         func(userData, i, mv->co, NULL, mv->no);
1438         }
1439 }
1440
1441 static void cdDM_foreachMappedEdge(
1442                                                    DerivedMesh *dm,
1443                                                    void (*func)(void *userData, int index,
1444                                                                                 float *v0co, float *v1co),
1445                                                    void *userData)
1446 {
1447         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1448         MVert *mv = cddm->mvert;
1449         MEdge *med = cddm->medge;
1450         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1451
1452         for(i = 0; i < dm->numEdgeData; i++, med++) {
1453                 if (index) {
1454                         orig = *index++;
1455                         if(orig == ORIGINDEX_NONE) continue;
1456                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1457                 }
1458                 else
1459                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1460         }
1461 }
1462
1463 static void cdDM_foreachMappedFaceCenter(
1464                                                    DerivedMesh *dm,
1465                                                    void (*func)(void *userData, int index,
1466                                                                                 float *cent, float *no),
1467                                                    void *userData)
1468 {
1469         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1470         MVert *mv = cddm->mvert;
1471         MFace *mf = cddm->mface;
1472         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1473
1474         for(i = 0; i < dm->numFaceData; i++, mf++) {
1475                 float cent[3];
1476                 float no[3];
1477
1478                 if (index) {
1479                         orig = *index++;
1480                         if(orig == ORIGINDEX_NONE) continue;
1481                 }
1482                 else
1483                         orig = i;
1484
1485                 VECCOPY(cent, mv[mf->v1].co);
1486                 add_v3_v3(cent, mv[mf->v2].co);
1487                 add_v3_v3(cent, mv[mf->v3].co);
1488
1489                 if (mf->v4) {
1490                         normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1491                         add_v3_v3(cent, mv[mf->v4].co);
1492                         mul_v3_fl(cent, 0.25f);
1493                 } else {
1494                         normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1495                         mul_v3_fl(cent, 0.33333333333f);
1496                 }
1497
1498                 func(userData, orig, cent, no);
1499         }
1500 }
1501
1502 static void cdDM_free_internal(CDDerivedMesh *cddm)
1503 {
1504         if(cddm->fmap) MEM_freeN(cddm->fmap);
1505         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1506 }
1507
1508 static void cdDM_release(DerivedMesh *dm)
1509 {
1510         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1511
1512         if (DM_release(dm)) {
1513                 cdDM_free_internal(cddm);
1514                 MEM_freeN(cddm);
1515         }
1516 }
1517
1518 /**************** CDDM interface functions ****************/
1519 static CDDerivedMesh *cdDM_create(const char *desc)
1520 {
1521         CDDerivedMesh *cddm;
1522         DerivedMesh *dm;
1523
1524         cddm = MEM_callocN(sizeof(*cddm), desc);
1525         dm = &cddm->dm;
1526
1527         dm->getMinMax = cdDM_getMinMax;
1528
1529         dm->getNumVerts = cdDM_getNumVerts;
1530         dm->getNumFaces = cdDM_getNumFaces;
1531         dm->getNumEdges = cdDM_getNumEdges;
1532
1533         dm->getVert = cdDM_getVert;
1534         dm->getEdge = cdDM_getEdge;
1535         dm->getFace = cdDM_getFace;
1536         dm->copyVertArray = cdDM_copyVertArray;
1537         dm->copyEdgeArray = cdDM_copyEdgeArray;
1538         dm->copyFaceArray = cdDM_copyFaceArray;
1539         dm->getVertData = DM_get_vert_data;
1540         dm->getEdgeData = DM_get_edge_data;
1541         dm->getFaceData = DM_get_face_data;
1542         dm->getVertDataArray = DM_get_vert_data_layer;
1543         dm->getEdgeDataArray = DM_get_edge_data_layer;
1544         dm->getFaceDataArray = DM_get_face_data_layer;
1545
1546         dm->getVertCos = cdDM_getVertCos;
1547         dm->getVertCo = cdDM_getVertCo;
1548         dm->getVertNo = cdDM_getVertNo;
1549
1550         dm->getPBVH = cdDM_getPBVH;
1551         dm->getFaceMap = cdDM_getFaceMap;
1552
1553         dm->drawVerts = cdDM_drawVerts;
1554
1555         dm->drawUVEdges = cdDM_drawUVEdges;
1556         dm->drawEdges = cdDM_drawEdges;
1557         dm->drawLooseEdges = cdDM_drawLooseEdges;
1558         dm->drawMappedEdges = cdDM_drawMappedEdges;
1559
1560         dm->drawFacesSolid = cdDM_drawFacesSolid;
1561         dm->drawFacesColored = cdDM_drawFacesColored;
1562         dm->drawFacesTex = cdDM_drawFacesTex;
1563         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1564         dm->drawMappedFaces = cdDM_drawMappedFaces;
1565         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1566         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1567
1568         dm->foreachMappedVert = cdDM_foreachMappedVert;
1569         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1570         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1571
1572         dm->release = cdDM_release;
1573
1574         return cddm;
1575 }
1576
1577 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1578 {
1579         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1580         DerivedMesh *dm = &cddm->dm;
1581
1582         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1583
1584         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1585         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1586         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1587
1588         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1589         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1590         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1591
1592         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1593         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1594         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1595
1596         return dm;
1597 }
1598
1599 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1600 {
1601         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1602         DerivedMesh *dm = &cddm->dm;
1603         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1604         int alloctype;
1605
1606         /* this does a referenced copy, with an exception for fluidsim */
1607
1608         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1609
1610         dm->deformedOnly = 1;
1611
1612         alloctype= CD_REFERENCE;
1613
1614         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1615                                          mesh->totvert);
1616         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1617                                          mesh->totedge);
1618         CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1619                                          mesh->totface);
1620
1621         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1622         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1623         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1624
1625         return dm;
1626 }
1627
1628 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1629 {
1630         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1631                                                            BLI_countlist(&em->edges),
1632                                                            BLI_countlist(&em->faces));
1633         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1634         EditVert *eve;
1635         EditEdge *eed;
1636         EditFace *efa;
1637         MVert *mvert = cddm->mvert;
1638         MEdge *medge = cddm->medge;
1639         MFace *mface = cddm->mface;
1640         int i, *index;
1641
1642         dm->deformedOnly = 1;
1643
1644         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1645                                          CD_CALLOC, dm->numVertData);
1646         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1647                                          CD_CALLOC, dm->numEdgeData); */
1648         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1649                                          CD_CALLOC, dm->numFaceData);
1650
1651         /* set eve->hash to vert index */
1652         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1653                 eve->tmp.l = i;
1654
1655         /* Need to be able to mark loose edges */
1656         for(eed = em->edges.first; eed; eed = eed->next) {
1657                 eed->f2 = 0;
1658         }
1659         for(efa = em->faces.first; efa; efa = efa->next) {
1660                 efa->e1->f2 = 1;
1661                 efa->e2->f2 = 1;
1662                 efa->e3->f2 = 1;
1663                 if(efa->e4) efa->e4->f2 = 1;
1664         }
1665
1666         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1667         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1668                 i++, eve = eve->next, index++) {
1669                 MVert *mv = &mvert[i];
1670
1671                 VECCOPY(mv->co, eve->co);
1672
1673                 normal_float_to_short_v3(mv->no, eve->no);
1674                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1675
1676                 mv->flag = 0;
1677
1678                 *index = i;
1679
1680                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1681         }
1682
1683         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1684         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1685                 i++, eed = eed->next, index++) {
1686                 MEdge *med = &medge[i];
1687
1688                 med->v1 = eed->v1->tmp.l;
1689                 med->v2 = eed->v2->tmp.l;
1690                 med->crease = (unsigned char) (eed->crease * 255.0f);
1691                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1692                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1693                 
1694                 if(eed->seam) med->flag |= ME_SEAM;
1695                 if(eed->sharp) med->flag |= ME_SHARP;
1696                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1697
1698                 *index = i;
1699
1700                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1701         }
1702
1703         index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1704         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1705                 i++, efa = efa->next, index++) {
1706                 MFace *mf = &mface[i];
1707
1708                 mf->v1 = efa->v1->tmp.l;
1709                 mf->v2 = efa->v2->tmp.l;
1710                 mf->v3 = efa->v3->tmp.l;
1711                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1712                 mf->mat_nr = efa->mat_nr;
1713                 mf->flag = efa->flag;
1714
1715                 *index = i;
1716
1717                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1718                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1719         }
1720
1721         return dm;
1722 }
1723
1724 DerivedMesh *CDDM_from_curve(Object *ob)
1725 {
1726         return CDDM_from_curve_customDB(ob, &ob->disp);
1727 }
1728
1729 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1730 {
1731         DerivedMesh *dm;
1732         CDDerivedMesh *cddm;
1733         MVert *allvert;
1734         MEdge *alledge;
1735         MFace *allface;
1736         int totvert, totedge, totface;
1737
1738         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1739                 &totedge, &allface, &totface) != 0) {
1740                 /* Error initializing mdata. This often happens when curve is empty */
1741                 return CDDM_new(0, 0, 0);
1742         }
1743
1744         dm = CDDM_new(totvert, totedge, totface);
1745         dm->deformedOnly = 1;
1746
1747         cddm = (CDDerivedMesh*)dm;
1748
1749         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1750         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1751         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1752
1753         MEM_freeN(allvert);
1754         MEM_freeN(alledge);
1755         MEM_freeN(allface);
1756
1757         return dm;
1758 }
1759
1760 DerivedMesh *CDDM_copy(DerivedMesh *source)
1761 {
1762         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1763         DerivedMesh *dm = &cddm->dm;
1764         int numVerts = source->numVertData;
1765         int numEdges = source->numEdgeData;
1766         int numFaces = source->numFaceData;
1767
1768         /* ensure these are created if they are made on demand */
1769         source->getVertDataArray(source, CD_ORIGINDEX);
1770         source->getEdgeDataArray(source, CD_ORIGINDEX);
1771         source->getFaceDataArray(source, CD_ORIGINDEX);
1772
1773         /* this initializes dm, and copies all non mvert/medge/mface layers */
1774         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1775         dm->deformedOnly = source->deformedOnly;
1776
1777         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1778         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1779         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1780
1781         /* now add mvert/medge/mface layers */
1782         cddm->mvert = source->dupVertArray(source);
1783         cddm->medge = source->dupEdgeArray(source);
1784         cddm->mface = source->dupFaceArray(source);
1785
1786         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1787         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1788         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1789
1790         return dm;
1791 }
1792
1793 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
1794  * relationship betwen mesh data this needs to be set by the caller. */
1795 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1796                                                                 int numVerts, int numEdges, int numFaces)
1797 {
1798         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1799         DerivedMesh *dm = &cddm->dm;
1800
1801         /* ensure these are created if they are made on demand */
1802         source->getVertDataArray(source, CD_ORIGINDEX);
1803         source->getEdgeDataArray(source, CD_ORIGINDEX);
1804         source->getFaceDataArray(source, CD_ORIGINDEX);
1805
1806         /* this does a copy of all non mvert/medge/mface layers */
1807         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1808
1809         /* now add mvert/medge/mface layers */
1810         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1811         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1812         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1813
1814         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1815                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1816         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1817                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1818         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1819                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1820
1821         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1822         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1823         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1824
1825         return dm;
1826 }
1827
1828 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1829 {
1830         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1831         MVert *vert;
1832         int i;
1833
1834         /* this will just return the pointer if it wasn't a referenced layer */
1835         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1836         cddm->mvert = vert;
1837
1838         for(i = 0; i < dm->numVertData; ++i, ++vert)
1839                 VECCOPY(vert->co, vertCoords[i]);
1840 }
1841
1842 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1843 {
1844         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1845         MVert *vert;
1846         int i;
1847
1848         /* this will just return the pointer if it wasn't a referenced layer */
1849         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1850         cddm->mvert = vert;
1851
1852         for(i = 0; i < dm->numVertData; ++i, ++vert)
1853                 copy_v3_v3_short(vert->no, vertNormals[i]);
1854 }
1855
1856 void CDDM_calc_normals(DerivedMesh *dm)
1857 {
1858         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1859         float (*face_nors)[3];
1860
1861         if(dm->numVertData == 0) return;
1862
1863         /* we don't want to overwrite any referenced layers */
1864         cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1865
1866         /* make a face normal layer if not present */
1867         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1868         if(!face_nors)
1869                 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1870                                                                                  NULL, dm->numFaceData);
1871
1872         /* calculate face normals */
1873         mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
1874 }
1875
1876 void CDDM_calc_edges(DerivedMesh *dm)
1877 {
1878         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1879         CustomData edgeData;
1880         EdgeHashIterator *ehi;
1881         MFace *mf = cddm->mface;
1882         MEdge *med;
1883         EdgeHash *eh = BLI_edgehash_new();
1884         int i, *index, numEdges, maxFaces = dm->numFaceData;
1885
1886         for (i = 0; i < maxFaces; i++, mf++) {
1887                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1888                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1889                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1890                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1891                 
1892                 if (mf->v4) {
1893                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1894                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1895                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1896                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1897                 } else {
1898                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1899                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1900                 }
1901         }
1902
1903         numEdges = BLI_edgehash_size(eh);
1904
1905         /* write new edges into a temporary CustomData */
1906         memset(&edgeData, 0, sizeof(edgeData));
1907         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1908         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1909
1910         ehi = BLI_edgehashIterator_new(eh);
1911         med = CustomData_get_layer(&edgeData, CD_MEDGE);
1912         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1913         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1914                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1915                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1916
1917                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1918                 *index = ORIGINDEX_NONE;
1919         }
1920         BLI_edgehashIterator_free(ehi);
1921
1922         /* free old CustomData and assign new one */
1923         CustomData_free(&dm->edgeData, dm->numEdgeData);
1924         dm->edgeData = edgeData;
1925         dm->numEdgeData = numEdges;
1926
1927         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1928
1929         BLI_edgehash_free(eh, NULL);
1930 }
1931
1932 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1933 {
1934         if (numVerts < dm->numVertData)
1935                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1936
1937         dm->numVertData = numVerts;
1938 }
1939
1940 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1941 {
1942         if (numEdges < dm->numEdgeData)
1943                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1944
1945         dm->numEdgeData = numEdges;
1946 }
1947
1948 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1949 {
1950         if (numFaces < dm->numFaceData)
1951                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1952
1953         dm->numFaceData = numFaces;
1954 }
1955
1956 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1957 {
1958         return &((CDDerivedMesh*)dm)->mvert[index];
1959 }
1960
1961 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1962 {
1963         return &((CDDerivedMesh*)dm)->medge[index];
1964 }
1965
1966 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1967 {
1968         return &((CDDerivedMesh*)dm)->mface[index];
1969 }
1970
1971 MVert *CDDM_get_verts(DerivedMesh *dm)
1972 {
1973         return ((CDDerivedMesh*)dm)->mvert;
1974 }
1975
1976 MEdge *CDDM_get_edges(DerivedMesh *dm)
1977 {
1978         return ((CDDerivedMesh*)dm)->medge;
1979 }
1980
1981 MFace *CDDM_get_faces(DerivedMesh *dm)
1982 {
1983         return ((CDDerivedMesh*)dm)->mface;
1984 }
1985