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