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