Merging trunk up to r38329.
[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                                 }
1291                                 curface++;
1292                                 if(mface->v4) {
1293                                         if( numdata != 0 ) {
1294                                                 offset = 0;
1295                                                 if(attribs.totorco) {
1296                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1297                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1298                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1299                                                         offset += sizeof(float)*3;
1300                                                 }
1301                                                 for(b = 0; b < attribs.tottface; b++) {
1302                                                         MTFace *tf = &attribs.tface[b].array[a];
1303                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1304                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1305                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1306                                                         offset += sizeof(float)*2;
1307                                                 }
1308                                                 for(b = 0; b < attribs.totmcol; b++) {
1309                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1310                                                         GLubyte col[4];
1311                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1312                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1313                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1314                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1315                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1316                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1317                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1318                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1319                                                         offset += sizeof(unsigned char)*4;
1320                                                 }       
1321                                                 if(attribs.tottang) {
1322                                                         float *tang = attribs.tang.array[a*4 + 2];
1323                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1324                                                         tang = attribs.tang.array[a*4 + 3];
1325                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1326                                                         tang = attribs.tang.array[a*4 + 0];
1327                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1328                                                         offset += sizeof(float)*4;
1329                                                 }
1330                                         }
1331                                         curface++;
1332                                         i++;
1333                                 }
1334                         }
1335                         numfaces = curface - start;
1336                         if( numfaces > 0 ) {
1337                                 if( dodraw ) {
1338                                         if( numdata != 0 ) {
1339                                                 GPU_buffer_unlock(buffer);
1340                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1341                                         }
1342                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1343                                 }
1344                         }
1345                         GPU_buffer_unbind();
1346                 }
1347                 GPU_buffer_free(buffer);
1348         }
1349
1350         glShadeModel(GL_FLAT);
1351 }
1352
1353 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1354 {
1355         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1356 }
1357
1358 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1359 {
1360         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1361         MVert *vert = cddm->mvert;
1362         MEdge *edge = cddm->medge;
1363         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1364
1365         glBegin(GL_LINES);
1366         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1367                 if(index) {
1368                         orig = *index++;
1369                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1370                 }
1371                 else
1372                         orig = i;
1373
1374                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1375                         glVertex3fv(vert[edge->v1].co);
1376                         glVertex3fv(vert[edge->v2].co);
1377                 }
1378         }
1379         glEnd();
1380 }
1381
1382 static void cdDM_foreachMappedVert(
1383                                                    DerivedMesh *dm,
1384                                                    void (*func)(void *userData, int index, float *co,
1385                                                                                 float *no_f, short *no_s),
1386                                                    void *userData)
1387 {
1388         MVert *mv = CDDM_get_verts(dm);
1389         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1390
1391         for(i = 0; i < dm->numVertData; i++, mv++) {
1392                 if(index) {
1393                         orig = *index++;
1394                         if(orig == ORIGINDEX_NONE) continue;
1395                         func(userData, orig, mv->co, NULL, mv->no);
1396                 }
1397                 else
1398                         func(userData, i, mv->co, NULL, mv->no);
1399         }
1400 }
1401
1402 static void cdDM_foreachMappedEdge(
1403                                                    DerivedMesh *dm,
1404                                                    void (*func)(void *userData, int index,
1405                                                                                 float *v0co, float *v1co),
1406                                                    void *userData)
1407 {
1408         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1409         MVert *mv = cddm->mvert;
1410         MEdge *med = cddm->medge;
1411         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1412
1413         for(i = 0; i < dm->numEdgeData; i++, med++) {
1414                 if (index) {
1415                         orig = *index++;
1416                         if(orig == ORIGINDEX_NONE) continue;
1417                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1418                 }
1419                 else
1420                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1421         }
1422 }
1423
1424 static void cdDM_foreachMappedFaceCenter(
1425                                                    DerivedMesh *dm,
1426                                                    void (*func)(void *userData, int index,
1427                                                                                 float *cent, float *no),
1428                                                    void *userData)
1429 {
1430         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1431         MVert *mv = cddm->mvert;
1432         MFace *mf = cddm->mface;
1433         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1434
1435         for(i = 0; i < dm->numFaceData; i++, mf++) {
1436                 float cent[3];
1437                 float no[3];
1438
1439                 if (index) {
1440                         orig = *index++;
1441                         if(orig == ORIGINDEX_NONE) continue;
1442                 }
1443                 else
1444                         orig = i;
1445
1446                 VECCOPY(cent, mv[mf->v1].co);
1447                 add_v3_v3(cent, mv[mf->v2].co);
1448                 add_v3_v3(cent, mv[mf->v3].co);
1449
1450                 if (mf->v4) {
1451                         normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1452                         add_v3_v3(cent, mv[mf->v4].co);
1453                         mul_v3_fl(cent, 0.25f);
1454                 } else {
1455                         normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1456                         mul_v3_fl(cent, 0.33333333333f);
1457                 }
1458
1459                 func(userData, orig, cent, no);
1460         }
1461 }
1462
1463 static void cdDM_free_internal(CDDerivedMesh *cddm)
1464 {
1465         if(cddm->fmap) MEM_freeN(cddm->fmap);
1466         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1467 }
1468
1469 static void cdDM_release(DerivedMesh *dm)
1470 {
1471         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1472
1473         if (DM_release(dm)) {
1474                 cdDM_free_internal(cddm);
1475                 MEM_freeN(cddm);
1476         }
1477 }
1478
1479 /**************** CDDM interface functions ****************/
1480 static CDDerivedMesh *cdDM_create(const char *desc)
1481 {
1482         CDDerivedMesh *cddm;
1483         DerivedMesh *dm;
1484
1485         cddm = MEM_callocN(sizeof(*cddm), desc);
1486         dm = &cddm->dm;
1487
1488         dm->getMinMax = cdDM_getMinMax;
1489
1490         dm->getNumVerts = cdDM_getNumVerts;
1491         dm->getNumFaces = cdDM_getNumFaces;
1492         dm->getNumEdges = cdDM_getNumEdges;
1493
1494         dm->getVert = cdDM_getVert;
1495         dm->getEdge = cdDM_getEdge;
1496         dm->getFace = cdDM_getFace;
1497         dm->copyVertArray = cdDM_copyVertArray;
1498         dm->copyEdgeArray = cdDM_copyEdgeArray;
1499         dm->copyFaceArray = cdDM_copyFaceArray;
1500         dm->getVertData = DM_get_vert_data;
1501         dm->getEdgeData = DM_get_edge_data;
1502         dm->getFaceData = DM_get_face_data;
1503         dm->getVertDataArray = DM_get_vert_data_layer;
1504         dm->getEdgeDataArray = DM_get_edge_data_layer;
1505         dm->getFaceDataArray = DM_get_face_data_layer;
1506
1507         dm->getVertCos = cdDM_getVertCos;
1508         dm->getVertCo = cdDM_getVertCo;
1509         dm->getVertNo = cdDM_getVertNo;
1510
1511         dm->getPBVH = cdDM_getPBVH;
1512         dm->getFaceMap = cdDM_getFaceMap;
1513
1514         dm->drawVerts = cdDM_drawVerts;
1515
1516         dm->drawUVEdges = cdDM_drawUVEdges;
1517         dm->drawEdges = cdDM_drawEdges;
1518         dm->drawLooseEdges = cdDM_drawLooseEdges;
1519         dm->drawMappedEdges = cdDM_drawMappedEdges;
1520
1521         dm->drawFacesSolid = cdDM_drawFacesSolid;
1522         dm->drawFacesColored = cdDM_drawFacesColored;
1523         dm->drawFacesTex = cdDM_drawFacesTex;
1524         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1525         dm->drawMappedFaces = cdDM_drawMappedFaces;
1526         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1527         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1528
1529         dm->foreachMappedVert = cdDM_foreachMappedVert;
1530         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1531         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1532
1533         dm->release = cdDM_release;
1534
1535         return cddm;
1536 }
1537
1538 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1539 {
1540         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1541         DerivedMesh *dm = &cddm->dm;
1542
1543         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1544
1545         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1546         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1547         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1548
1549         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1550         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1551         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1552
1553         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1554         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1555         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1556
1557         return dm;
1558 }
1559
1560 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1561 {
1562         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1563         DerivedMesh *dm = &cddm->dm;
1564         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1565         int alloctype;
1566
1567         /* this does a referenced copy, with an exception for fluidsim */
1568
1569         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1570
1571         dm->deformedOnly = 1;
1572
1573         alloctype= CD_REFERENCE;
1574
1575         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1576                                          mesh->totvert);
1577         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1578                                          mesh->totedge);
1579         CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1580                                          mesh->totface);
1581
1582         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1583         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1584         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1585
1586         return dm;
1587 }
1588
1589 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1590 {
1591         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1592                                                            BLI_countlist(&em->edges),
1593                                                            BLI_countlist(&em->faces));
1594         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1595         EditVert *eve;
1596         EditEdge *eed;
1597         EditFace *efa;
1598         MVert *mvert = cddm->mvert;
1599         MEdge *medge = cddm->medge;
1600         MFace *mface = cddm->mface;
1601         int i, *index;
1602
1603         dm->deformedOnly = 1;
1604
1605         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1606                                          CD_CALLOC, dm->numVertData);
1607         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1608                                          CD_CALLOC, dm->numEdgeData); */
1609         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1610                                          CD_CALLOC, dm->numFaceData);
1611
1612         /* set eve->hash to vert index */
1613         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1614                 eve->tmp.l = i;
1615
1616         /* Need to be able to mark loose edges */
1617         for(eed = em->edges.first; eed; eed = eed->next) {
1618                 eed->f2 = 0;
1619         }
1620         for(efa = em->faces.first; efa; efa = efa->next) {
1621                 efa->e1->f2 = 1;
1622                 efa->e2->f2 = 1;
1623                 efa->e3->f2 = 1;
1624                 if(efa->e4) efa->e4->f2 = 1;
1625         }
1626
1627         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1628         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1629                 i++, eve = eve->next, index++) {
1630                 MVert *mv = &mvert[i];
1631
1632                 VECCOPY(mv->co, eve->co);
1633
1634                 normal_float_to_short_v3(mv->no, eve->no);
1635                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1636
1637                 mv->flag = 0;
1638
1639                 *index = i;
1640
1641                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1642         }
1643
1644         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1645         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1646                 i++, eed = eed->next, index++) {
1647                 MEdge *med = &medge[i];
1648
1649                 med->v1 = eed->v1->tmp.l;
1650                 med->v2 = eed->v2->tmp.l;
1651                 med->crease = (unsigned char) (eed->crease * 255.0f);
1652                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1653                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1654                 
1655                 if(eed->seam) med->flag |= ME_SEAM;
1656                 if(eed->sharp) med->flag |= ME_SHARP;
1657                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1658
1659                 *index = i;
1660
1661                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1662         }
1663
1664         index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1665         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1666                 i++, efa = efa->next, index++) {
1667                 MFace *mf = &mface[i];
1668
1669                 mf->v1 = efa->v1->tmp.l;
1670                 mf->v2 = efa->v2->tmp.l;
1671                 mf->v3 = efa->v3->tmp.l;
1672                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1673                 mf->mat_nr = efa->mat_nr;
1674                 mf->flag = efa->flag;
1675
1676                 *index = i;
1677
1678                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1679                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1680         }
1681
1682         return dm;
1683 }
1684
1685 DerivedMesh *CDDM_from_curve(Object *ob)
1686 {
1687         return CDDM_from_curve_customDB(ob, &ob->disp);
1688 }
1689
1690 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1691 {
1692         DerivedMesh *dm;
1693         CDDerivedMesh *cddm;
1694         MVert *allvert;
1695         MEdge *alledge;
1696         MFace *allface;
1697         int totvert, totedge, totface;
1698
1699         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1700                 &totedge, &allface, &totface) != 0) {
1701                 /* Error initializing mdata. This often happens when curve is empty */
1702                 return CDDM_new(0, 0, 0);
1703         }
1704
1705         dm = CDDM_new(totvert, totedge, totface);
1706         dm->deformedOnly = 1;
1707
1708         cddm = (CDDerivedMesh*)dm;
1709
1710         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1711         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1712         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1713
1714         MEM_freeN(allvert);
1715         MEM_freeN(alledge);
1716         MEM_freeN(allface);
1717
1718         return dm;
1719 }
1720
1721 DerivedMesh *CDDM_copy(DerivedMesh *source)
1722 {
1723         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1724         DerivedMesh *dm = &cddm->dm;
1725         int numVerts = source->numVertData;
1726         int numEdges = source->numEdgeData;
1727         int numFaces = source->numFaceData;
1728
1729         /* ensure these are created if they are made on demand */
1730         source->getVertDataArray(source, CD_ORIGINDEX);
1731         source->getEdgeDataArray(source, CD_ORIGINDEX);
1732         source->getFaceDataArray(source, CD_ORIGINDEX);
1733
1734         /* this initializes dm, and copies all non mvert/medge/mface layers */
1735         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1736         dm->deformedOnly = source->deformedOnly;
1737
1738         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1739         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1740         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1741
1742         /* now add mvert/medge/mface layers */
1743         cddm->mvert = source->dupVertArray(source);
1744         cddm->medge = source->dupEdgeArray(source);
1745         cddm->mface = source->dupFaceArray(source);
1746
1747         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1748         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1749         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1750
1751         return dm;
1752 }
1753
1754 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
1755  * relationship betwen mesh data this needs to be set by the caller. */
1756 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1757                                                                 int numVerts, int numEdges, int numFaces)
1758 {
1759         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1760         DerivedMesh *dm = &cddm->dm;
1761
1762         /* ensure these are created if they are made on demand */
1763         source->getVertDataArray(source, CD_ORIGINDEX);
1764         source->getEdgeDataArray(source, CD_ORIGINDEX);
1765         source->getFaceDataArray(source, CD_ORIGINDEX);
1766
1767         /* this does a copy of all non mvert/medge/mface layers */
1768         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1769
1770         /* now add mvert/medge/mface layers */
1771         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1772         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1773         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1774
1775         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1776                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1777         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1778                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1779         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1780                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1781
1782         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1783         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1784         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1785
1786         return dm;
1787 }
1788
1789 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1790 {
1791         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1792         MVert *vert;
1793         int i;
1794
1795         /* this will just return the pointer if it wasn't a referenced layer */
1796         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1797         cddm->mvert = vert;
1798
1799         for(i = 0; i < dm->numVertData; ++i, ++vert)
1800                 VECCOPY(vert->co, vertCoords[i]);
1801 }
1802
1803 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1804 {
1805         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1806         MVert *vert;
1807         int i;
1808
1809         /* this will just return the pointer if it wasn't a referenced layer */
1810         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1811         cddm->mvert = vert;
1812
1813         for(i = 0; i < dm->numVertData; ++i, ++vert)
1814                 VECCOPY(vert->no, vertNormals[i]);
1815 }
1816
1817 void CDDM_calc_normals(DerivedMesh *dm)
1818 {
1819         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1820         float (*face_nors)[3];
1821
1822         if(dm->numVertData == 0) return;
1823
1824         /* we don't want to overwrite any referenced layers */
1825         cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1826
1827         /* make a face normal layer if not present */
1828         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1829         if(!face_nors)
1830                 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1831                                                                                  NULL, dm->numFaceData);
1832
1833         /* calculate face normals */
1834         mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
1835 }
1836
1837 void CDDM_calc_edges(DerivedMesh *dm)
1838 {
1839         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1840         CustomData edgeData;
1841         EdgeHashIterator *ehi;
1842         MFace *mf = cddm->mface;
1843         MEdge *med;
1844         EdgeHash *eh = BLI_edgehash_new();
1845         int i, *index, numEdges, maxFaces = dm->numFaceData;
1846
1847         for (i = 0; i < maxFaces; i++, mf++) {
1848                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1849                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1850                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1851                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1852                 
1853                 if (mf->v4) {
1854                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1855                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1856                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1857                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1858                 } else {
1859                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1860                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1861                 }
1862         }
1863
1864         numEdges = BLI_edgehash_size(eh);
1865
1866         /* write new edges into a temporary CustomData */
1867         memset(&edgeData, 0, sizeof(edgeData));
1868         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1869         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1870
1871         ehi = BLI_edgehashIterator_new(eh);
1872         med = CustomData_get_layer(&edgeData, CD_MEDGE);
1873         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1874         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1875                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1876                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1877
1878                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1879                 *index = ORIGINDEX_NONE;
1880         }
1881         BLI_edgehashIterator_free(ehi);
1882
1883         /* free old CustomData and assign new one */
1884         CustomData_free(&dm->edgeData, dm->numEdgeData);
1885         dm->edgeData = edgeData;
1886         dm->numEdgeData = numEdges;
1887
1888         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1889
1890         BLI_edgehash_free(eh, NULL);
1891 }
1892
1893 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1894 {
1895         if (numVerts < dm->numVertData)
1896                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1897
1898         dm->numVertData = numVerts;
1899 }
1900
1901 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1902 {
1903         if (numEdges < dm->numEdgeData)
1904                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1905
1906         dm->numEdgeData = numEdges;
1907 }
1908
1909 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1910 {
1911         if (numFaces < dm->numFaceData)
1912                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1913
1914         dm->numFaceData = numFaces;
1915 }
1916
1917 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1918 {
1919         return &((CDDerivedMesh*)dm)->mvert[index];
1920 }
1921
1922 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1923 {
1924         return &((CDDerivedMesh*)dm)->medge[index];
1925 }
1926
1927 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1928 {
1929         return &((CDDerivedMesh*)dm)->mface[index];
1930 }
1931
1932 MVert *CDDM_get_verts(DerivedMesh *dm)
1933 {
1934         return ((CDDerivedMesh*)dm)->mvert;
1935 }
1936
1937 MEdge *CDDM_get_edges(DerivedMesh *dm)
1938 {
1939         return ((CDDerivedMesh*)dm)->medge;
1940 }
1941
1942 MFace *CDDM_get_faces(DerivedMesh *dm)
1943 {
1944         return ((CDDerivedMesh*)dm)->mface;
1945 }
1946