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