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