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