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