Sculpting on shapekeys
[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         short *no = cddm->mvert[index].no;
176
177         no_r[0] = no[0]/32767.f;
178         no_r[1] = no[1]/32767.f;
179         no_r[2] = no[2]/32767.f;
180 }
181
182 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
183 {
184         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
185
186         if(!cddm->fmap && ob->type == OB_MESH) {
187                 Mesh *me= ob->data;
188
189                 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
190                                          me->totvert, me->totface);
191         }
192
193         return cddm->fmap;
194 }
195
196 static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
197 {
198         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
199         Mesh *me= ob->data;
200         int deformed= 0;
201
202         /* active modifiers means extra deformation, which can't be handled correct
203            on bith of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
204            stuff and show final DerivedMesh so user would see actual object shape */
205         deformed|= ob->sculpt->modifiers_active;
206
207         /* as in case with modifiers, we can't synchronize deformation made against
208            PBVH and non-locked keyblock, so also use PBVH only for brushes and
209            final DM to give final result to user */
210         deformed|= ob->sculpt->kb && (ob->shapeflag&OB_SHAPE_LOCK) == 0;
211
212         if(deformed)
213                 return 0;
214
215         return (cddm->mvert == me->mvert) || ob->sculpt->kb;
216 }
217
218 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
219 {
220         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
221
222         if(!ob) {
223                 cddm->pbvh= NULL;
224                 return NULL;
225         }
226
227         if(!ob->sculpt)
228                 return NULL;
229         if(ob->sculpt->pbvh) {
230                 cddm->pbvh= ob->sculpt->pbvh;
231                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
232         }
233
234         /* always build pbvh from original mesh, and only use it for drawing if
235            this derivedmesh is just original mesh. it's the multires subsurf dm
236            that this is actually for, to support a pbvh on a modified mesh */
237         if(!cddm->pbvh && ob->type == OB_MESH) {
238                 Mesh *me= ob->data;
239                 cddm->pbvh = BLI_pbvh_new();
240                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
241                 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
242                                    me->totface, me->totvert);
243
244                 if(ob->sculpt->modifiers_active) {
245                         float (*vertCos)[3];
246                         int totvert;
247
248                         totvert= dm->getNumVerts(dm);
249                         vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
250                         dm->getVertCos(dm, vertCos);
251                         BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
252                         MEM_freeN(vertCos);
253                 }
254         }
255
256         return cddm->pbvh;
257 }
258
259 /* update vertex normals so that drawing smooth faces works during sculpt
260    TODO: proper fix is to support the pbvh in all drawing modes */
261 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
262 {
263         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
264         float (*face_nors)[3];
265
266         if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
267                 return;
268
269         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
270
271         BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
272 }
273
274 static void cdDM_drawVerts(DerivedMesh *dm)
275 {
276         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
277         MVert *mv = cddm->mvert;
278         int i;
279
280         if( GPU_buffer_legacy(dm) ) {
281                 glBegin(GL_POINTS);
282                 for(i = 0; i < dm->numVertData; i++, mv++)
283                         glVertex3fv(mv->co);
284                 glEnd();
285         }
286         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
287                 GPU_vertex_setup(dm);
288                 if( !GPU_buffer_legacy(dm) ) {
289                         if(dm->drawObject->nelements)   glDrawArrays(GL_POINTS,0, dm->drawObject->nelements);
290                         else                                                    glDrawArrays(GL_POINTS,0, dm->drawObject->nlooseverts);
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->nmaterials; a++ ) {
553                                 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
554                                         glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
555                         }
556                 }
557                 GPU_buffer_unbind( );
558         }
559
560 #undef PASSVERT
561         glShadeModel(GL_FLAT);
562 }
563
564 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
565 {
566         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
567         int a, glmode;
568         unsigned char *cp1, *cp2;
569         MVert *mvert = cddm->mvert;
570         MFace *mface = cddm->mface;
571
572         cp1 = col1;
573         if(col2) {
574                 cp2 = col2;
575         } else {
576                 cp2 = NULL;
577                 useTwoSided = 0;
578         }
579
580         /* there's a conflict here... twosided colors versus culling...? */
581         /* defined by history, only texture faces have culling option */
582         /* we need that as mesh option builtin, next to double sided lighting */
583         if(col1 && col2)
584                 glEnable(GL_CULL_FACE);
585
586         cdDM_update_normals_from_pbvh(dm);
587
588         if( GPU_buffer_legacy(dm) ) {
589                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
590                 glShadeModel(GL_SMOOTH);
591                 glBegin(glmode = GL_QUADS);
592                 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
593                         int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
594
595                         if(new_glmode != glmode) {
596                                 glEnd();
597                                 glBegin(glmode = new_glmode);
598                         }
599                                 
600                         glColor3ub(cp1[0], cp1[1], cp1[2]);
601                         glVertex3fv(mvert[mface->v1].co);
602                         glColor3ub(cp1[4], cp1[5], cp1[6]);
603                         glVertex3fv(mvert[mface->v2].co);
604                         glColor3ub(cp1[8], cp1[9], cp1[10]);
605                         glVertex3fv(mvert[mface->v3].co);
606                         if(mface->v4) {
607                                 glColor3ub(cp1[12], cp1[13], cp1[14]);
608                                 glVertex3fv(mvert[mface->v4].co);
609                         }
610                                 
611                         if(useTwoSided) {
612                                 glColor3ub(cp2[8], cp2[9], cp2[10]);
613                                 glVertex3fv(mvert[mface->v3].co );
614                                 glColor3ub(cp2[4], cp2[5], cp2[6]);
615                                 glVertex3fv(mvert[mface->v2].co );
616                                 glColor3ub(cp2[0], cp2[1], cp2[2]);
617                                 glVertex3fv(mvert[mface->v1].co );
618                                 if(mface->v4) {
619                                         glColor3ub(cp2[12], cp2[13], cp2[14]);
620                                         glVertex3fv(mvert[mface->v4].co );
621                                 }
622                         }
623                         if(col2) cp2 += 16;
624                 }
625                 glEnd();
626         }
627         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
628                 GPU_color4_upload(dm,cp1);
629                 GPU_vertex_setup(dm);
630                 GPU_color_setup(dm);
631                 if( !GPU_buffer_legacy(dm) ) {
632                         glShadeModel(GL_SMOOTH);
633                         glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
634
635                         if( useTwoSided ) {
636                                 GPU_color4_upload(dm,cp2);
637                                 GPU_color_setup(dm);
638                                 glCullFace(GL_FRONT);
639                                 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
640                                 glCullFace(GL_BACK);
641                         }
642                 }
643                 GPU_buffer_unbind();
644         }
645
646         glShadeModel(GL_FLAT);
647         glDisable(GL_CULL_FACE);
648 }
649
650 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
651                            int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
652                            int (*drawParamsMapped)(void *userData, int index),
653                            void *userData) 
654 {
655         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
656         MVert *mv = cddm->mvert;
657         MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
658         MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
659         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
660         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
661         int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
662         int startFace = 0, lastFlag = 0xdeadbeef;
663         MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
664         if(!mcol)
665                 mcol = dm->getFaceDataArray(dm, CD_MCOL);
666
667         cdDM_update_normals_from_pbvh(dm);
668
669         if( GPU_buffer_legacy(dm) ) {
670                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
671                 for(i = 0; i < dm->numFaceData; i++, mf++) {
672                         MVert *mvert;
673                         int flag;
674                         unsigned char *cp = NULL;
675
676                         if(drawParams) {
677                                 flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
678                         }
679                         else {
680                                 if(index) {
681                                         orig = *index++;
682                                         if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
683                                         if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
684                                         else    { if(nors) nors += 3; continue; }
685                                 }
686                                 else
687                                         if(drawParamsMapped) flag = drawParamsMapped(userData, i);
688                                         else    { if(nors) nors += 3; continue; }
689                         }
690                         
691                         if(flag != 0) {
692                                 if (flag==1 && mcol)
693                                         cp= (unsigned char*) &mcol[i*4];
694
695                                 if(!(mf->flag&ME_SMOOTH)) {
696                                         if (nors) {
697                                                 glNormal3fv(nors);
698                                         }
699                                         else {
700                                                 float nor[3];
701                                                 if(mf->v4) {
702                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
703                                                 } else {
704                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
705                                                 }
706                                                 glNormal3fv(nor);
707                                         }
708                                 }
709
710                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
711                                 if(tf) glTexCoord2fv(tf[i].uv[0]);
712                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
713                                 mvert = &mv[mf->v1];
714                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
715                                 glVertex3fv(mvert->co);
716                                         
717                                 if(tf) glTexCoord2fv(tf[i].uv[1]);
718                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
719                                 mvert = &mv[mf->v2];
720                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
721                                 glVertex3fv(mvert->co);
722
723                                 if(tf) glTexCoord2fv(tf[i].uv[2]);
724                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
725                                 mvert = &mv[mf->v3];
726                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
727                                 glVertex3fv(mvert->co);
728
729                                 if(mf->v4) {
730                                         if(tf) glTexCoord2fv(tf[i].uv[3]);
731                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
732                                         mvert = &mv[mf->v4];
733                                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
734                                         glVertex3fv(mvert->co);
735                                 }
736                                 glEnd();
737                         }
738                         
739                         if(nors) nors += 3;
740                 }
741         } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
742                 MCol *col = realcol;
743                 if(!col)
744                         col = mcol;
745
746                 GPU_vertex_setup( dm );
747                 GPU_normal_setup( dm );
748                 GPU_uv_setup( dm );
749                 if( col != NULL ) {
750                         /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL )  {
751                                 col = 0;
752                         } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
753                                 col = 0;
754                         }
755                         
756                         if( col != 0 ) {*/
757                                 unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
758                                 for( i=0; i < dm->getNumFaces(dm); i++ ) {
759                                         for( j=0; j < 4; j++ ) {
760                                                 colors[i*12+j*3] = col[i*4+j].r;
761                                                 colors[i*12+j*3+1] = col[i*4+j].g;
762                                                 colors[i*12+j*3+2] = col[i*4+j].b;
763                                         }
764                                 }
765                                 GPU_color3_upload(dm,colors);
766                                 MEM_freeN(colors);
767                                 if(realcol)
768                                         dm->drawObject->colType = CD_TEXTURE_MCOL;
769                                 else if(mcol)
770                                         dm->drawObject->colType = CD_MCOL;
771                         //}
772                         GPU_color_setup( dm );
773                 }
774
775                 if( !GPU_buffer_legacy(dm) ) {
776                         glShadeModel( GL_SMOOTH );
777                         lastFlag = 0;
778                         for(i = 0; i < dm->drawObject->nelements/3; i++) {
779                                 int actualFace = dm->drawObject->faceRemap[i];
780                                 int flag = 1;
781
782                                 if(drawParams) {
783                                         flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
784                                 }
785                                 else {
786                                         if(index) {
787                                                 orig = index[actualFace];
788                                                 if(orig == ORIGINDEX_NONE) continue;
789                                                 if(drawParamsMapped)
790                                                         flag = drawParamsMapped(userData, orig);
791                                         }
792                                         else
793                                                 if(drawParamsMapped)
794                                                         flag = drawParamsMapped(userData, actualFace);
795                                 }
796                                 if( flag != lastFlag ) {
797                                         if( startFace < i ) {
798                                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
799                                                         if (lastFlag==1 && col)
800                                                                 GPU_color_switch(1);
801                                                         else
802                                                                 GPU_color_switch(0);
803                                                         glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
804                                                 }
805                                         }
806                                         lastFlag = flag;
807                                         startFace = i;
808                                 }
809                         }
810                         if( startFace < dm->drawObject->nelements/3 ) {
811                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
812                                         if (lastFlag==1 && col)
813                                                 GPU_color_switch(1);
814                                         else
815                                                 GPU_color_switch(0);
816                                         glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
817                                 }
818                         }
819                 }
820
821                 GPU_buffer_unbind();
822                 glShadeModel( GL_FLAT );
823         }
824 }
825
826 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
827 {
828         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
829 }
830
831 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs))
832 {
833         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
834         MVert *mv = cddm->mvert;
835         MFace *mf = cddm->mface;
836         MCol *mc;
837         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
838         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
839
840         mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
841         if(!mc)
842                 mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
843         if(!mc)
844                 mc = DM_get_face_data_layer(dm, CD_MCOL);
845
846         cdDM_update_normals_from_pbvh(dm);
847
848         /* back-buffer always uses legacy since VBO's would need the
849          * color array temporarily overwritten for drawing, then reset. */
850         if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
851                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
852                 for(i = 0; i < dm->numFaceData; i++, mf++) {
853                         int drawSmooth = (mf->flag & ME_SMOOTH);
854                         int draw= 1;
855
856                         orig= (index==NULL) ? i : *index++;
857                         
858                         if(orig == ORIGINDEX_NONE)
859                                 draw= setMaterial(mf->mat_nr + 1, NULL);
860                         else if (setDrawOptions != NULL)
861                                 draw= setDrawOptions(userData, orig, &drawSmooth);
862
863                         if(draw) {
864                                 unsigned char *cp = NULL;
865
866                                 if(useColors && mc)
867                                         cp = (unsigned char *)&mc[i * 4];
868
869                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
870                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
871
872                                 if (!drawSmooth) {
873                                         if (nors) {
874                                                 glNormal3fv(nors);
875                                         }
876                                         else {
877                                                 float nor[3];
878                                                 if(mf->v4) {
879                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
880                                                 } else {
881                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
882                                                 }
883                                                 glNormal3fv(nor);
884                                         }
885
886                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
887                                         glVertex3fv(mv[mf->v1].co);
888                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
889                                         glVertex3fv(mv[mf->v2].co);
890                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
891                                         glVertex3fv(mv[mf->v3].co);
892                                         if(mf->v4) {
893                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
894                                                 glVertex3fv(mv[mf->v4].co);
895                                         }
896                                 } else {
897                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
898                                         glNormal3sv(mv[mf->v1].no);
899                                         glVertex3fv(mv[mf->v1].co);
900                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
901                                         glNormal3sv(mv[mf->v2].no);
902                                         glVertex3fv(mv[mf->v2].co);
903                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
904                                         glNormal3sv(mv[mf->v3].no);
905                                         glVertex3fv(mv[mf->v3].co);
906                                         if(mf->v4) {
907                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
908                                                 glNormal3sv(mv[mf->v4].no);
909                                                 glVertex3fv(mv[mf->v4].co);
910                                         }
911                                 }
912
913                                 glEnd();
914                         }
915                         
916                         if (nors) nors += 3;
917                 }
918         }
919         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
920                 int prevstart = 0;
921                 GPU_vertex_setup(dm);
922                 GPU_normal_setup(dm);
923                 if( useColors && mc )
924                         GPU_color_setup(dm);
925                 if( !GPU_buffer_legacy(dm) ) {
926                         int tottri = dm->drawObject->nelements/3;
927                         glShadeModel(GL_SMOOTH);
928                         
929                         if(tottri == 0) {
930                                 /* avoid buffer problems in following code */
931                         }
932                         if(setDrawOptions == NULL) {
933                                 /* just draw the entire face array */
934                                 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
935                         }
936                         else {
937                                 /* we need to check if the next material changes */
938                                 int next_actualFace= dm->drawObject->faceRemap[0];
939                                 
940                                 for( i = 0; i < tottri; i++ ) {
941                                         //int actualFace = dm->drawObject->faceRemap[i];
942                                         int actualFace = next_actualFace;
943                                         MFace *mface= mf + actualFace;
944                                         int drawSmooth= (mface->flag & ME_SMOOTH);
945                                         int draw = 1;
946
947                                         if(i != tottri-1)
948                                                 next_actualFace= dm->drawObject->faceRemap[i+1];
949
950                                         orig= (index==NULL) ? actualFace : index[actualFace];
951
952                                         if(orig == ORIGINDEX_NONE)
953                                                 draw= setMaterial(mface->mat_nr + 1, NULL);
954                                         else if (setDrawOptions != NULL)
955                                                 draw= setDrawOptions(userData, orig, &drawSmooth);
956         
957                                         /* Goal is to draw as long of a contiguous triangle
958                                            array as possible, so draw when we hit either an
959                                            invisible triangle or at the end of the array */
960                                         if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
961                                                 if(prevstart != i)
962                                                         /* Add one to the length (via `draw')
963                                                            if we're drawing at the end of the array */
964                                                         glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
965                                                 prevstart = i + 1;
966                                         }
967                                 }
968                         }
969
970                         glShadeModel(GL_FLAT);
971                 }
972                 GPU_buffer_unbind();
973         }
974 }
975
976 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
977 {
978         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
979 }
980
981 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
982 {
983         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
984         GPUVertexAttribs gattribs;
985         DMVertexAttribs attribs;
986         MVert *mvert = cddm->mvert;
987         MFace *mface = cddm->mface;
988         MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
989         float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
990         int a, b, dodraw, matnr, new_matnr;
991         int transp, new_transp, orig_transp;
992         int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
993
994         cdDM_update_normals_from_pbvh(dm);
995
996         matnr = -1;
997         dodraw = 0;
998         transp = GPU_get_material_blend_mode();
999         orig_transp = transp;
1000
1001         glShadeModel(GL_SMOOTH);
1002
1003         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1004                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1005                 memset(&attribs, 0, sizeof(attribs));
1006
1007                 glBegin(GL_QUADS);
1008
1009                 for(a = 0; a < dm->numFaceData; a++, mface++) {
1010                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1011                         new_matnr = mface->mat_nr + 1;
1012
1013                         if(new_matnr != matnr) {
1014                                 glEnd();
1015
1016                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1017                                 if(dodraw)
1018                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1019
1020                                 glBegin(GL_QUADS);
1021                         }
1022
1023                         if(!dodraw) {
1024                                 continue;
1025                         }
1026                         else if(setDrawOptions) {
1027                                 orig = (index)? index[a]: a;
1028
1029                                 if(orig == ORIGINDEX_NONE) {
1030                                         /* since the material is set by setMaterial(), faces with no
1031                                          * origin can be assumed to be generated by a modifier */ 
1032                                         
1033                                         /* continue */
1034                                 }
1035                                 else if(!setDrawOptions(userData, orig))
1036                                         continue;
1037                         }
1038
1039                         if(tf) {
1040                                 new_transp = tf[a].transp;
1041
1042                                 if(new_transp != transp) {
1043                                         glEnd();
1044
1045                                         if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1046                                                 GPU_set_material_blend_mode(orig_transp);
1047                                         else
1048                                                 GPU_set_material_blend_mode(new_transp);
1049                                         transp = new_transp;
1050
1051                                         glBegin(GL_QUADS);
1052                                 }
1053                         }
1054
1055                         if(!smoothnormal) {
1056                                 if(nors) {
1057                                         glNormal3fv(nors[a]);
1058                                 }
1059                                 else {
1060                                         /* TODO ideally a normal layer should always be available */
1061                                         float nor[3];
1062                                         if(mface->v4) {
1063                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1064                                         } else {
1065                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1066                                         }
1067                                         glNormal3fv(nor);
1068                                 }
1069                         }
1070
1071 #define PASSVERT(index, vert) {                                                                                                 \
1072                 if(attribs.totorco)                                                                                                                     \
1073                         glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
1074                 for(b = 0; b < attribs.tottface; b++) {                                                                         \
1075                         MTFace *tf = &attribs.tface[b].array[a];                                                                \
1076                         glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
1077                 }                                                                                                                                                       \
1078                 for(b = 0; b < attribs.totmcol; b++) {                                                                          \
1079                         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
1080                         GLubyte col[4];                                                                                                                 \
1081                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
1082                         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
1083                 }                                                                                                                                                       \
1084                 if(attribs.tottang) {                                                                                                           \
1085                         float *tang = attribs.tang.array[a*4 + vert];                                                   \
1086                         glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
1087                 }                                                                                                                                                       \
1088                 if(smoothnormal)                                                                                                                        \
1089                         glNormal3sv(mvert[index].no);                                                                                   \
1090                 glVertex3fv(mvert[index].co);                                                                                           \
1091         }
1092
1093                         PASSVERT(mface->v1, 0);
1094                         PASSVERT(mface->v2, 1);
1095                         PASSVERT(mface->v3, 2);
1096                         if(mface->v4)
1097                                 PASSVERT(mface->v4, 3)
1098                         else
1099                                 PASSVERT(mface->v3, 2)
1100
1101 #undef PASSVERT
1102                 }
1103                 glEnd();
1104         }
1105         else {
1106                 GPUBuffer *buffer = NULL;
1107                 char *varray = NULL;
1108                 int numdata = 0, elementsize = 0, offset;
1109                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1110                 int i;
1111
1112                 MFace *mf = mface;
1113                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1114                 memset(&attribs, 0, sizeof(attribs));
1115
1116                 GPU_vertex_setup(dm);
1117                 GPU_normal_setup(dm);
1118
1119                 if( !GPU_buffer_legacy(dm) ) {
1120                         for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
1121
1122                                 a = dm->drawObject->faceRemap[i];
1123
1124                                 mface = mf + a;
1125                                 new_matnr = mface->mat_nr + 1;
1126
1127                                 if(new_matnr != matnr ) {
1128                                         numfaces = curface - start;
1129                                         if( numfaces > 0 ) {
1130
1131                                                 if( dodraw ) {
1132
1133                                                         if( numdata != 0 ) {
1134
1135                                                                 GPU_buffer_unlock(buffer);
1136
1137                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1138                                                         }
1139
1140                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1141
1142                                                         if( numdata != 0 ) {
1143
1144                                                                 GPU_buffer_free(buffer, NULL);
1145
1146                                                                 buffer = NULL;
1147                                                         }
1148
1149                                                 }
1150                                         }
1151                                         numdata = 0;
1152                                         start = curface;
1153                                         prevdraw = dodraw;
1154                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1155                                         if(dodraw) {
1156                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1157
1158                                                 if(attribs.totorco) {
1159                                                         datatypes[numdata].index = attribs.orco.glIndex;
1160                                                         datatypes[numdata].size = 3;
1161                                                         datatypes[numdata].type = GL_FLOAT;
1162                                                         numdata++;
1163                                                 }
1164                                                 for(b = 0; b < attribs.tottface; b++) {
1165                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1166                                                         datatypes[numdata].size = 2;
1167                                                         datatypes[numdata].type = GL_FLOAT;
1168                                                         numdata++;
1169                                                 }       
1170                                                 for(b = 0; b < attribs.totmcol; b++) {
1171                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1172                                                         datatypes[numdata].size = 4;
1173                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1174                                                         numdata++;
1175                                                 }       
1176                                                 if(attribs.tottang) {
1177                                                         datatypes[numdata].index = attribs.tang.glIndex;
1178                                                         datatypes[numdata].size = 4;
1179                                                         datatypes[numdata].type = GL_FLOAT;
1180                                                         numdata++;
1181                                                 }
1182                                                 if( numdata != 0 ) {
1183                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1184                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL );
1185                                                         if( buffer == NULL ) {
1186                                                                 GPU_buffer_unbind();
1187                                                                 dm->drawObject->legacy = 1;
1188                                                                 return;
1189                                                         }
1190                                                         varray = GPU_buffer_lock_stream(buffer);
1191                                                         if( varray == NULL ) {
1192                                                                 GPU_buffer_unbind();
1193                                                                 GPU_buffer_free(buffer, NULL);
1194                                                                 dm->drawObject->legacy = 1;
1195                                                                 return;
1196                                                         }
1197                                                 }
1198                                                 else {
1199                                                         /* if the buffer was set, dont use it again.
1200                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1201                                                         prevdraw= 0;
1202                                                         buffer= NULL;
1203                                                 }
1204                                         }
1205                                 }
1206                                 if(!dodraw) {
1207                                         continue;
1208                                 }
1209
1210                                 if(tf) {
1211                                         new_transp = tf[a].transp;
1212
1213                                         if(new_transp != transp) {
1214                                                 numfaces = curface - start;
1215                                                 if( numfaces > 0 ) {
1216                                                         if( dodraw ) {
1217                                                                 if( numdata != 0 ) {
1218                                                                         GPU_buffer_unlock(buffer);
1219                                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1220                                                                 }
1221                                                                 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1222                                                                 if( numdata != 0 ) {
1223                                                                         varray = GPU_buffer_lock_stream(buffer);
1224                                                                 }
1225                                                         }
1226                                                 }
1227                                                 start = curface;
1228
1229                                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1230                                                         GPU_set_material_blend_mode(orig_transp);
1231                                                 else
1232                                                         GPU_set_material_blend_mode(new_transp);
1233                                                 transp = new_transp;
1234                                         }
1235                                 }
1236                                 
1237                                 if( numdata != 0 ) {
1238                                         offset = 0;
1239                                         if(attribs.totorco) {
1240                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1241                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1242                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1243                                                 offset += sizeof(float)*3;
1244                                         }
1245                                         for(b = 0; b < attribs.tottface; b++) {
1246                                                 MTFace *tf = &attribs.tface[b].array[a];
1247                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1248                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1249
1250                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1251                                                 offset += sizeof(float)*2;
1252                                         }
1253                                         for(b = 0; b < attribs.totmcol; b++) {
1254                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1255                                                 GLubyte col[4];
1256                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1257                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1258                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1259                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1260                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1261                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1262                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1263                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1264                                                 offset += sizeof(unsigned char)*4;
1265                                         }       
1266                                         if(attribs.tottang) {
1267                                                 float *tang = attribs.tang.array[a*4 + 0];
1268                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1269                                                 tang = attribs.tang.array[a*4 + 1];
1270                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1271                                                 tang = attribs.tang.array[a*4 + 2];
1272                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1273                                                 offset += sizeof(float)*4;
1274                                         }
1275                                 }
1276                                 curface++;
1277                                 if(mface->v4) {
1278                                         if( numdata != 0 ) {
1279                                                 offset = 0;
1280                                                 if(attribs.totorco) {
1281                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1282                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1283                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1284                                                         offset += sizeof(float)*3;
1285                                                 }
1286                                                 for(b = 0; b < attribs.tottface; b++) {
1287                                                         MTFace *tf = &attribs.tface[b].array[a];
1288                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1289                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1290                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1291                                                         offset += sizeof(float)*2;
1292                                                 }
1293                                                 for(b = 0; b < attribs.totmcol; b++) {
1294                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1295                                                         GLubyte col[4];
1296                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1297                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1298                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1299                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1300                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1301                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1302                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1303                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1304                                                         offset += sizeof(unsigned char)*4;
1305                                                 }       
1306                                                 if(attribs.tottang) {
1307                                                         float *tang = attribs.tang.array[a*4 + 2];
1308                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1309                                                         tang = attribs.tang.array[a*4 + 3];
1310                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1311                                                         tang = attribs.tang.array[a*4 + 0];
1312                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1313                                                         offset += sizeof(float)*4;
1314                                                 }
1315                                         }
1316                                         curface++;
1317                                         i++;
1318                                 }
1319                         }
1320                         numfaces = curface - start;
1321                         if( numfaces > 0 ) {
1322                                 if( dodraw ) {
1323                                         if( numdata != 0 ) {
1324                                                 GPU_buffer_unlock(buffer);
1325                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1326                                         }
1327                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1328                                 }
1329                         }
1330                         GPU_buffer_unbind();
1331                 }
1332                 GPU_buffer_free( buffer, NULL );
1333         }
1334
1335         glShadeModel(GL_FLAT);
1336 }
1337
1338 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1339 {
1340         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1341 }
1342
1343 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1344 {
1345         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1346         MVert *vert = cddm->mvert;
1347         MEdge *edge = cddm->medge;
1348         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1349
1350         glBegin(GL_LINES);
1351         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1352                 if(index) {
1353                         orig = *index++;
1354                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1355                 }
1356                 else
1357                         orig = i;
1358
1359                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1360                         glVertex3fv(vert[edge->v1].co);
1361                         glVertex3fv(vert[edge->v2].co);
1362                 }
1363         }
1364         glEnd();
1365 }
1366
1367 static void cdDM_foreachMappedVert(
1368                                                    DerivedMesh *dm,
1369                                                    void (*func)(void *userData, int index, float *co,
1370                                                                                 float *no_f, short *no_s),
1371                                                    void *userData)
1372 {
1373         MVert *mv = CDDM_get_verts(dm);
1374         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1375
1376         for(i = 0; i < dm->numVertData; i++, mv++) {
1377                 if(index) {
1378                         orig = *index++;
1379                         if(orig == ORIGINDEX_NONE) continue;
1380                         func(userData, orig, mv->co, NULL, mv->no);
1381                 }
1382                 else
1383                         func(userData, i, mv->co, NULL, mv->no);
1384         }
1385 }
1386
1387 static void cdDM_foreachMappedEdge(
1388                                                    DerivedMesh *dm,
1389                                                    void (*func)(void *userData, int index,
1390                                                                                 float *v0co, float *v1co),
1391                                                    void *userData)
1392 {
1393         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1394         MVert *mv = cddm->mvert;
1395         MEdge *med = cddm->medge;
1396         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1397
1398         for(i = 0; i < dm->numEdgeData; i++, med++) {
1399                 if (index) {
1400                         orig = *index++;
1401                         if(orig == ORIGINDEX_NONE) continue;
1402                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1403                 }
1404                 else
1405                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1406         }
1407 }
1408
1409 static void cdDM_foreachMappedFaceCenter(
1410                                                    DerivedMesh *dm,
1411                                                    void (*func)(void *userData, int index,
1412                                                                                 float *cent, float *no),
1413                                                    void *userData)
1414 {
1415         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1416         MVert *mv = cddm->mvert;
1417         MFace *mf = cddm->mface;
1418         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1419
1420         for(i = 0; i < dm->numFaceData; i++, mf++) {
1421                 float cent[3];
1422                 float no[3];
1423
1424                 if (index) {
1425                         orig = *index++;
1426                         if(orig == ORIGINDEX_NONE) continue;
1427                 }
1428                 else
1429                         orig = i;
1430
1431                 VECCOPY(cent, mv[mf->v1].co);
1432                 add_v3_v3(cent, mv[mf->v2].co);
1433                 add_v3_v3(cent, mv[mf->v3].co);
1434
1435                 if (mf->v4) {
1436                         normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1437                         add_v3_v3(cent, mv[mf->v4].co);
1438                         mul_v3_fl(cent, 0.25f);
1439                 } else {
1440                         normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1441                         mul_v3_fl(cent, 0.33333333333f);
1442                 }
1443
1444                 func(userData, orig, cent, no);
1445         }
1446 }
1447
1448 static void cdDM_free_internal(CDDerivedMesh *cddm)
1449 {
1450         if(cddm->fmap) MEM_freeN(cddm->fmap);
1451         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1452 }
1453
1454 static void cdDM_release(DerivedMesh *dm)
1455 {
1456         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1457
1458         if (DM_release(dm)) {
1459                 cdDM_free_internal(cddm);
1460                 MEM_freeN(cddm);
1461         }
1462 }
1463
1464 /**************** CDDM interface functions ****************/
1465 static CDDerivedMesh *cdDM_create(const char *desc)
1466 {
1467         CDDerivedMesh *cddm;
1468         DerivedMesh *dm;
1469
1470         cddm = MEM_callocN(sizeof(*cddm), desc);
1471         dm = &cddm->dm;
1472
1473         dm->getMinMax = cdDM_getMinMax;
1474
1475         dm->getNumVerts = cdDM_getNumVerts;
1476         dm->getNumFaces = cdDM_getNumFaces;
1477         dm->getNumEdges = cdDM_getNumEdges;
1478
1479         dm->getVert = cdDM_getVert;
1480         dm->getEdge = cdDM_getEdge;
1481         dm->getFace = cdDM_getFace;
1482         dm->copyVertArray = cdDM_copyVertArray;
1483         dm->copyEdgeArray = cdDM_copyEdgeArray;
1484         dm->copyFaceArray = cdDM_copyFaceArray;
1485         dm->getVertData = DM_get_vert_data;
1486         dm->getEdgeData = DM_get_edge_data;
1487         dm->getFaceData = DM_get_face_data;
1488         dm->getVertDataArray = DM_get_vert_data_layer;
1489         dm->getEdgeDataArray = DM_get_edge_data_layer;
1490         dm->getFaceDataArray = DM_get_face_data_layer;
1491
1492         dm->getVertCos = cdDM_getVertCos;
1493         dm->getVertCo = cdDM_getVertCo;
1494         dm->getVertNo = cdDM_getVertNo;
1495
1496         dm->getPBVH = cdDM_getPBVH;
1497         dm->getFaceMap = cdDM_getFaceMap;
1498
1499         dm->drawVerts = cdDM_drawVerts;
1500
1501         dm->drawUVEdges = cdDM_drawUVEdges;
1502         dm->drawEdges = cdDM_drawEdges;
1503         dm->drawLooseEdges = cdDM_drawLooseEdges;
1504         dm->drawMappedEdges = cdDM_drawMappedEdges;
1505
1506         dm->drawFacesSolid = cdDM_drawFacesSolid;
1507         dm->drawFacesColored = cdDM_drawFacesColored;
1508         dm->drawFacesTex = cdDM_drawFacesTex;
1509         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1510         dm->drawMappedFaces = cdDM_drawMappedFaces;
1511         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1512         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1513
1514         dm->foreachMappedVert = cdDM_foreachMappedVert;
1515         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1516         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1517
1518         dm->release = cdDM_release;
1519
1520         return cddm;
1521 }
1522
1523 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1524 {
1525         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1526         DerivedMesh *dm = &cddm->dm;
1527
1528         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1529
1530         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1531         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1532         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1533
1534         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1535         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1536         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1537
1538         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1539         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1540         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1541
1542         return dm;
1543 }
1544
1545 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1546 {
1547         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1548         DerivedMesh *dm = &cddm->dm;
1549         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1550         int alloctype;
1551
1552         /* this does a referenced copy, with an exception for fluidsim */
1553
1554         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1555
1556         dm->deformedOnly = 1;
1557
1558         alloctype= CD_REFERENCE;
1559
1560         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1561                                          mesh->totvert);
1562         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1563                                          mesh->totedge);
1564         CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1565                                          mesh->totface);
1566
1567         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1568         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1569         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1570
1571         return dm;
1572 }
1573
1574 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1575 {
1576         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1577                                                            BLI_countlist(&em->edges),
1578                                                            BLI_countlist(&em->faces));
1579         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1580         EditVert *eve;
1581         EditEdge *eed;
1582         EditFace *efa;
1583         MVert *mvert = cddm->mvert;
1584         MEdge *medge = cddm->medge;
1585         MFace *mface = cddm->mface;
1586         int i, *index;
1587
1588         dm->deformedOnly = 1;
1589
1590         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1591                                          CD_CALLOC, dm->numVertData);
1592         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1593                                          CD_CALLOC, dm->numEdgeData); */
1594         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1595                                          CD_CALLOC, dm->numFaceData);
1596
1597         /* set eve->hash to vert index */
1598         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1599                 eve->tmp.l = i;
1600
1601         /* Need to be able to mark loose edges */
1602         for(eed = em->edges.first; eed; eed = eed->next) {
1603                 eed->f2 = 0;
1604         }
1605         for(efa = em->faces.first; efa; efa = efa->next) {
1606                 efa->e1->f2 = 1;
1607                 efa->e2->f2 = 1;
1608                 efa->e3->f2 = 1;
1609                 if(efa->e4) efa->e4->f2 = 1;
1610         }
1611
1612         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1613         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1614                 i++, eve = eve->next, index++) {
1615                 MVert *mv = &mvert[i];
1616
1617                 VECCOPY(mv->co, eve->co);
1618
1619                 normal_float_to_short_v3(mv->no, eve->no);
1620                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1621
1622                 mv->flag = 0;
1623
1624                 *index = i;
1625
1626                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1627         }
1628
1629         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1630         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1631                 i++, eed = eed->next, index++) {
1632                 MEdge *med = &medge[i];
1633
1634                 med->v1 = eed->v1->tmp.l;
1635                 med->v2 = eed->v2->tmp.l;
1636                 med->crease = (unsigned char) (eed->crease * 255.0f);
1637                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1638                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1639                 
1640                 if(eed->seam) med->flag |= ME_SEAM;
1641                 if(eed->sharp) med->flag |= ME_SHARP;
1642                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1643
1644                 *index = i;
1645
1646                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1647         }
1648
1649         index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1650         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1651                 i++, efa = efa->next, index++) {
1652                 MFace *mf = &mface[i];
1653
1654                 mf->v1 = efa->v1->tmp.l;
1655                 mf->v2 = efa->v2->tmp.l;
1656                 mf->v3 = efa->v3->tmp.l;
1657                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1658                 mf->mat_nr = efa->mat_nr;
1659                 mf->flag = efa->flag;
1660
1661                 *index = i;
1662
1663                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1664                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1665         }
1666
1667         return dm;
1668 }
1669
1670 DerivedMesh *CDDM_from_curve(Object *ob)
1671 {
1672         return CDDM_from_curve_customDB(ob, &ob->disp);
1673 }
1674
1675 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1676 {
1677         DerivedMesh *dm;
1678         CDDerivedMesh *cddm;
1679         MVert *allvert;
1680         MEdge *alledge;
1681         MFace *allface;
1682         int totvert, totedge, totface;
1683
1684         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1685                 &totedge, &allface, &totface) != 0) {
1686                 /* Error initializing mdata. This often happens when curve is empty */
1687                 return CDDM_new(0, 0, 0);
1688         }
1689
1690         dm = CDDM_new(totvert, totedge, totface);
1691         dm->deformedOnly = 1;
1692
1693         cddm = (CDDerivedMesh*)dm;
1694
1695         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1696         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1697         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1698
1699         MEM_freeN(allvert);
1700         MEM_freeN(alledge);
1701         MEM_freeN(allface);
1702
1703         return dm;
1704 }
1705
1706 DerivedMesh *CDDM_copy(DerivedMesh *source)
1707 {
1708         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1709         DerivedMesh *dm = &cddm->dm;
1710         int numVerts = source->numVertData;
1711         int numEdges = source->numEdgeData;
1712         int numFaces = source->numFaceData;
1713
1714         /* ensure these are created if they are made on demand */
1715         source->getVertDataArray(source, CD_ORIGINDEX);
1716         source->getEdgeDataArray(source, CD_ORIGINDEX);
1717         source->getFaceDataArray(source, CD_ORIGINDEX);
1718
1719         /* this initializes dm, and copies all non mvert/medge/mface layers */
1720         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1721         dm->deformedOnly = source->deformedOnly;
1722
1723         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1724         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1725         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1726
1727         /* now add mvert/medge/mface layers */
1728         cddm->mvert = source->dupVertArray(source);
1729         cddm->medge = source->dupEdgeArray(source);
1730         cddm->mface = source->dupFaceArray(source);
1731
1732         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1733         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1734         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1735
1736         return dm;
1737 }
1738
1739 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
1740  * relationship betwen mesh data this needs to be set by the caller. */
1741 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1742                                                                 int numVerts, int numEdges, int numFaces)
1743 {
1744         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1745         DerivedMesh *dm = &cddm->dm;
1746
1747         /* ensure these are created if they are made on demand */
1748         source->getVertDataArray(source, CD_ORIGINDEX);
1749         source->getEdgeDataArray(source, CD_ORIGINDEX);
1750         source->getFaceDataArray(source, CD_ORIGINDEX);
1751
1752         /* this does a copy of all non mvert/medge/mface layers */
1753         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1754
1755         /* now add mvert/medge/mface layers */
1756         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1757         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1758         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1759
1760         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1761                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1762         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1763                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1764         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1765                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1766
1767         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1768         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1769         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1770
1771         return dm;
1772 }
1773
1774 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1775 {
1776         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1777         MVert *vert;
1778         int i;
1779
1780         /* this will just return the pointer if it wasn't a referenced layer */
1781         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1782         cddm->mvert = vert;
1783
1784         for(i = 0; i < dm->numVertData; ++i, ++vert)
1785                 VECCOPY(vert->co, vertCoords[i]);
1786 }
1787
1788 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1789 {
1790         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1791         MVert *vert;
1792         int i;
1793
1794         /* this will just return the pointer if it wasn't a referenced layer */
1795         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1796         cddm->mvert = vert;
1797
1798         for(i = 0; i < dm->numVertData; ++i, ++vert)
1799                 VECCOPY(vert->no, vertNormals[i]);
1800 }
1801
1802 void CDDM_calc_normals(DerivedMesh *dm)
1803 {
1804         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1805         float (*face_nors)[3];
1806
1807         if(dm->numVertData == 0) return;
1808
1809         /* we don't want to overwrite any referenced layers */
1810         cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1811
1812         /* make a face normal layer if not present */
1813         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1814         if(!face_nors)
1815                 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1816                                                                                  NULL, dm->numFaceData);
1817
1818         /* calculate face normals */
1819         mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
1820 }
1821
1822 void CDDM_calc_edges(DerivedMesh *dm)
1823 {
1824         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1825         CustomData edgeData;
1826         EdgeHashIterator *ehi;
1827         MFace *mf = cddm->mface;
1828         MEdge *med;
1829         EdgeHash *eh = BLI_edgehash_new();
1830         int i, *index, numEdges, maxFaces = dm->numFaceData;
1831
1832         for (i = 0; i < maxFaces; i++, mf++) {
1833                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1834                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1835                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1836                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1837                 
1838                 if (mf->v4) {
1839                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1840                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1841                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1842                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1843                 } else {
1844                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1845                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1846                 }
1847         }
1848
1849         numEdges = BLI_edgehash_size(eh);
1850
1851         /* write new edges into a temporary CustomData */
1852         memset(&edgeData, 0, sizeof(edgeData));
1853         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1854         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1855
1856         ehi = BLI_edgehashIterator_new(eh);
1857         med = CustomData_get_layer(&edgeData, CD_MEDGE);
1858         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1859         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1860                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1861                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1862
1863                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1864                 *index = ORIGINDEX_NONE;
1865         }
1866         BLI_edgehashIterator_free(ehi);
1867
1868         /* free old CustomData and assign new one */
1869         CustomData_free(&dm->edgeData, dm->numEdgeData);
1870         dm->edgeData = edgeData;
1871         dm->numEdgeData = numEdges;
1872
1873         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1874
1875         BLI_edgehash_free(eh, NULL);
1876 }
1877
1878 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1879 {
1880         if (numVerts < dm->numVertData)
1881                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1882
1883         dm->numVertData = numVerts;
1884 }
1885
1886 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1887 {
1888         if (numEdges < dm->numEdgeData)
1889                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1890
1891         dm->numEdgeData = numEdges;
1892 }
1893
1894 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1895 {
1896         if (numFaces < dm->numFaceData)
1897                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1898
1899         dm->numFaceData = numFaces;
1900 }
1901
1902 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1903 {
1904         return &((CDDerivedMesh*)dm)->mvert[index];
1905 }
1906
1907 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1908 {
1909         return &((CDDerivedMesh*)dm)->medge[index];
1910 }
1911
1912 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1913 {
1914         return &((CDDerivedMesh*)dm)->mface[index];
1915 }
1916
1917 MVert *CDDM_get_verts(DerivedMesh *dm)
1918 {
1919         return ((CDDerivedMesh*)dm)->mvert;
1920 }
1921
1922 MEdge *CDDM_get_edges(DerivedMesh *dm)
1923 {
1924         return ((CDDerivedMesh*)dm)->medge;
1925 }
1926
1927 MFace *CDDM_get_faces(DerivedMesh *dm)
1928 {
1929         return ((CDDerivedMesh*)dm)->mface;
1930 }
1931