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