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