cadf5f375b5cb90240d8dce4b7804c0d63c985fd
[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 state = 1;
857                 int prevstate = 1;
858                 int prevstart = 0;
859                 GPU_vertex_setup(dm);
860                 GPU_normal_setup(dm);
861                 if( useColors && mc )
862                         GPU_color_setup(dm);
863                 if( !GPU_buffer_legacy(dm) ) {
864                         glShadeModel(GL_SMOOTH);
865                         for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
866                                 int actualFace = dm->drawObject->faceRemap[i];
867                                 int drawSmooth = (mf[actualFace].flag & ME_SMOOTH);
868                                 int dontdraw = 0;
869                                 if(index) {
870                                         orig = index[actualFace];
871                                         if(setDrawOptions && orig == ORIGINDEX_NONE)
872                                                 dontdraw = 1;
873                                 }
874                                 else
875                                         orig = actualFace;
876                                 if( dontdraw ) {
877                                         state = 0;
878                                 }
879                                 else {
880                                         if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
881                                                 state = 1;
882                                         }
883                                         else {
884                                                 state = 0;
885                                         }
886                                 }
887                                 if( prevstate != state && prevstate == 1 ) {
888                                         if( i-prevstart > 0 ) {
889                                                 glDrawArrays(GL_TRIANGLES,prevstart*3,(i-prevstart)*3);
890                                         }
891                                         prevstart = i;
892                                 }
893                                 prevstate = state;
894                         }
895                         if(state==1) {
896                                 glDrawArrays(GL_TRIANGLES,prevstart*3,dm->drawObject->nelements-prevstart*3);
897                         }
898                         glShadeModel(GL_FLAT);
899                 }
900                 GPU_buffer_unbind();
901         }
902 }
903
904 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
905 {
906         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
907 }
908
909 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
910 {
911         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
912         GPUVertexAttribs gattribs;
913         DMVertexAttribs attribs;
914         MVert *mvert = cddm->mvert;
915         MFace *mface = cddm->mface;
916         MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
917         float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
918         int a, b, dodraw, smoothnormal, matnr, new_matnr;
919         int transp, new_transp, orig_transp;
920         int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
921
922         matnr = -1;
923         smoothnormal = 0;
924         dodraw = 0;
925         transp = GPU_get_material_blend_mode();
926         orig_transp = transp;
927
928         glShadeModel(GL_SMOOTH);
929
930         if( GPU_buffer_legacy(dm) || setDrawOptions != 0 ) {
931                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
932                 memset(&attribs, 0, sizeof(attribs));
933
934                 glBegin(GL_QUADS);
935
936                 for(a = 0; a < dm->numFaceData; a++, mface++) {
937                         new_matnr = mface->mat_nr + 1;
938
939                         if(new_matnr != matnr) {
940                                 glEnd();
941
942                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
943                                 if(dodraw)
944                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
945
946                                 glBegin(GL_QUADS);
947                         }
948
949                         if(!dodraw) {
950                                 continue;
951                         }
952                         else if(setDrawOptions) {
953                                 orig = (index)? index[a]: a;
954
955                                 if(orig == ORIGINDEX_NONE)
956                                         continue;
957                                 else if(!setDrawOptions(userData, orig))
958                                         continue;
959                         }
960
961                         if(tf) {
962                                 new_transp = tf[a].transp;
963
964                                 if(new_transp != transp) {
965                                         glEnd();
966
967                                         if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
968                                                 GPU_set_material_blend_mode(orig_transp);
969                                         else
970                                                 GPU_set_material_blend_mode(new_transp);
971                                         transp = new_transp;
972
973                                         glBegin(GL_QUADS);
974                                 }
975                         }
976
977                         smoothnormal = (mface->flag & ME_SMOOTH);
978
979                         if(!smoothnormal) {
980                                 if(nors) {
981                                         glNormal3fv(nors[a]);
982                                 }
983                                 else {
984                                         /* TODO ideally a normal layer should always be available */
985                                         float nor[3];
986                                         if(mface->v4) {
987                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
988                                         } else {
989                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
990                                         }
991                                         glNormal3fv(nor);
992                                 }
993                         }
994
995 #define PASSVERT(index, vert) {                                                                                                 \
996                 if(attribs.totorco)                                                                                                                     \
997                         glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
998                 for(b = 0; b < attribs.tottface; b++) {                                                                         \
999                         MTFace *tf = &attribs.tface[b].array[a];                                                                \
1000                         glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
1001                 }                                                                                                                                                       \
1002                 for(b = 0; b < attribs.totmcol; b++) {                                                                          \
1003                         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
1004                         GLubyte col[4];                                                                                                                 \
1005                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
1006                         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
1007                 }                                                                                                                                                       \
1008                 if(attribs.tottang) {                                                                                                           \
1009                         float *tang = attribs.tang.array[a*4 + vert];                                                   \
1010                         glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
1011                 }                                                                                                                                                       \
1012                 if(smoothnormal)                                                                                                                        \
1013                         glNormal3sv(mvert[index].no);                                                                                   \
1014                 glVertex3fv(mvert[index].co);                                                                                           \
1015         }
1016
1017                         PASSVERT(mface->v1, 0);
1018                         PASSVERT(mface->v2, 1);
1019                         PASSVERT(mface->v3, 2);
1020                         if(mface->v4)
1021                                 PASSVERT(mface->v4, 3)
1022                         else
1023                                 PASSVERT(mface->v3, 2)
1024
1025 #undef PASSVERT
1026                 }
1027                 glEnd();
1028         }
1029         else {
1030                 GPUBuffer *buffer = 0;
1031                 char *varray = 0;
1032                 int numdata = 0, elementsize = 0, offset;
1033                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1034                 int i;
1035
1036                 MFace *mf = mface;
1037                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1038                 memset(&attribs, 0, sizeof(attribs));
1039
1040                 GPU_vertex_setup(dm);
1041                 GPU_normal_setup(dm);
1042
1043                 if( !GPU_buffer_legacy(dm) ) {
1044                         for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
1045
1046                                 a = dm->drawObject->faceRemap[i];
1047
1048                                 mface = mf + a;
1049                                 new_matnr = mface->mat_nr + 1;
1050
1051                                 if(new_matnr != matnr ) {
1052                                         numfaces = curface - start;
1053                                         if( numfaces > 0 ) {
1054
1055                                                 if( dodraw ) {
1056
1057                                                         if( numdata != 0 ) {
1058
1059                                                                 GPU_buffer_unlock(buffer);
1060
1061                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1062                                                         }
1063
1064                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1065
1066                                                         if( numdata != 0 ) {
1067
1068                                                                 GPU_buffer_free(buffer,0);
1069
1070                                                                 buffer = 0;
1071                                                         }
1072
1073                                                 }
1074                                         }
1075                                         numdata = 0;
1076                                         start = curface;
1077                                         prevdraw = dodraw;
1078                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1079                                         if(dodraw) {
1080                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1081
1082                                                 if(attribs.totorco) {
1083                                                         datatypes[numdata].index = attribs.orco.glIndex;
1084                                                         datatypes[numdata].size = 3;
1085                                                         datatypes[numdata].type = GL_FLOAT;
1086                                                         numdata++;
1087                                                 }
1088                                                 for(b = 0; b < attribs.tottface; b++) {
1089                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1090                                                         datatypes[numdata].size = 2;
1091                                                         datatypes[numdata].type = GL_FLOAT;
1092                                                         numdata++;
1093                                                 }       
1094                                                 for(b = 0; b < attribs.totmcol; b++) {
1095                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1096                                                         datatypes[numdata].size = 4;
1097                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1098                                                         numdata++;
1099                                                 }       
1100                                                 if(attribs.tottang) {
1101                                                         datatypes[numdata].index = attribs.tang.glIndex;
1102                                                         datatypes[numdata].size = 3;
1103                                                         datatypes[numdata].type = GL_FLOAT;
1104                                                         numdata++;
1105                                                 }
1106                                                 if( numdata != 0 ) {
1107                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1108                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, 0 );
1109                                                         if( buffer == 0 ) {
1110                                                                 GPU_buffer_unbind();
1111                                                                 dm->drawObject->legacy = 1;
1112                                                                 return;
1113                                                         }
1114                                                         varray = GPU_buffer_lock_stream(buffer);
1115                                                         if( varray == 0 ) {
1116                                                                 GPU_buffer_unbind();
1117                                                                 GPU_buffer_free(buffer, 0);
1118                                                                 dm->drawObject->legacy = 1;
1119                                                                 return;
1120                                                         }
1121                                                 }
1122                                                 else {
1123                                                         /* if the buffer was set, dont use it again.
1124                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1125                                                         prevdraw= 0;
1126                                                         buffer= NULL;
1127                                                 }
1128                                         }
1129                                 }
1130                                 if(!dodraw) {
1131                                         continue;
1132                                 }
1133
1134                                 if(tf) {
1135                                         new_transp = tf[a].transp;
1136
1137                                         if(new_transp != transp) {
1138                                                 numfaces = curface - start;
1139                                                 if( numfaces > 0 ) {
1140                                                         if( dodraw ) {
1141                                                                 if( numdata != 0 ) {
1142                                                                         GPU_buffer_unlock(buffer);
1143                                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1144                                                                 }
1145                                                                 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1146                                                                 if( numdata != 0 ) {
1147                                                                         varray = GPU_buffer_lock_stream(buffer);
1148                                                                 }
1149                                                         }
1150                                                 }
1151                                                 start = curface;
1152
1153                                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1154                                                         GPU_set_material_blend_mode(orig_transp);
1155                                                 else
1156                                                         GPU_set_material_blend_mode(new_transp);
1157                                                 transp = new_transp;
1158                                         }
1159                                 }
1160                                 
1161                                 if( numdata != 0 ) {
1162                                         offset = 0;
1163                                         if(attribs.totorco) {
1164                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1165                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1166                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1167                                                 offset += sizeof(float)*3;
1168                                         }
1169                                         for(b = 0; b < attribs.tottface; b++) {
1170                                                 MTFace *tf = &attribs.tface[b].array[a];
1171                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1172                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1173
1174                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1175                                                 offset += sizeof(float)*2;
1176                                         }
1177                                         for(b = 0; b < attribs.totmcol; b++) {
1178                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1179                                                 GLubyte col[4];
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], col);
1182                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1183                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1184                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1185                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1186                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1187                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1188                                                 offset += sizeof(unsigned char)*4;
1189                                         }       
1190                                         if(attribs.tottang) {
1191                                                 float *tang = attribs.tang.array[a*4 + 0];
1192                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1193                                                 tang = attribs.tang.array[a*4 + 1];
1194                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1195                                                 tang = attribs.tang.array[a*4 + 2];
1196                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1197                                                 offset += sizeof(float)*3;
1198                                         }
1199                                 }
1200                                 curface++;
1201                                 if(mface->v4) {
1202                                         if( numdata != 0 ) {
1203                                                 offset = 0;
1204                                                 if(attribs.totorco) {
1205                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1206                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1207                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1208                                                         offset += sizeof(float)*3;
1209                                                 }
1210                                                 for(b = 0; b < attribs.tottface; b++) {
1211                                                         MTFace *tf = &attribs.tface[b].array[a];
1212                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1213                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1214                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1215                                                         offset += sizeof(float)*2;
1216                                                 }
1217                                                 for(b = 0; b < attribs.totmcol; b++) {
1218                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1219                                                         GLubyte col[4];
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], col);
1222                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1223                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1224                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1225                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1226                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1227                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1228                                                         offset += sizeof(unsigned char)*4;
1229                                                 }       
1230                                                 if(attribs.tottang) {
1231                                                         float *tang = attribs.tang.array[a*4 + 2];
1232                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1233                                                         tang = attribs.tang.array[a*4 + 3];
1234                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1235                                                         tang = attribs.tang.array[a*4 + 0];
1236                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1237                                                         offset += sizeof(float)*3;
1238                                                 }
1239                                         }
1240                                         curface++;
1241                                         i++;
1242                                 }
1243                         }
1244                         numfaces = curface - start;
1245                         if( numfaces > 0 ) {
1246                                 if( dodraw ) {
1247                                         if( numdata != 0 ) {
1248                                                 GPU_buffer_unlock(buffer);
1249                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1250                                         }
1251                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1252                                 }
1253                         }
1254                         GPU_buffer_unbind();
1255                 }
1256                 GPU_buffer_free( buffer, 0 );
1257         }
1258
1259         glShadeModel(GL_FLAT);
1260 }
1261
1262 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1263 {
1264         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1265 }
1266
1267 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1268 {
1269         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1270         MVert *vert = cddm->mvert;
1271         MEdge *edge = cddm->medge;
1272         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1273
1274         glBegin(GL_LINES);
1275         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1276                 if(index) {
1277                         orig = *index++;
1278                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1279                 }
1280                 else
1281                         orig = i;
1282
1283                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1284                         glVertex3fv(vert[edge->v1].co);
1285                         glVertex3fv(vert[edge->v2].co);
1286                 }
1287         }
1288         glEnd();
1289 }
1290
1291 static void cdDM_foreachMappedVert(
1292                                                    DerivedMesh *dm,
1293                                                    void (*func)(void *userData, int index, float *co,
1294                                                                                 float *no_f, short *no_s),
1295                                                    void *userData)
1296 {
1297         MVert *mv = CDDM_get_verts(dm);
1298         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1299
1300         for(i = 0; i < dm->numVertData; i++, mv++) {
1301                 if(index) {
1302                         orig = *index++;
1303                         if(orig == ORIGINDEX_NONE) continue;
1304                         func(userData, orig, mv->co, NULL, mv->no);
1305                 }
1306                 else
1307                         func(userData, i, mv->co, NULL, mv->no);
1308         }
1309 }
1310
1311 static void cdDM_foreachMappedEdge(
1312                                                    DerivedMesh *dm,
1313                                                    void (*func)(void *userData, int index,
1314                                                                                 float *v0co, float *v1co),
1315                                                    void *userData)
1316 {
1317         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1318         MVert *mv = cddm->mvert;
1319         MEdge *med = cddm->medge;
1320         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1321
1322         for(i = 0; i < dm->numEdgeData; i++, med++) {
1323                 if (index) {
1324                         orig = *index++;
1325                         if(orig == ORIGINDEX_NONE) continue;
1326                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1327                 }
1328                 else
1329                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1330         }
1331 }
1332
1333 static void cdDM_foreachMappedFaceCenter(
1334                                                    DerivedMesh *dm,
1335                                                    void (*func)(void *userData, int index,
1336                                                                                 float *cent, float *no),
1337                                                    void *userData)
1338 {
1339         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1340         MVert *mv = cddm->mvert;
1341         MFace *mf = cddm->mface;
1342         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1343
1344         for(i = 0; i < dm->numFaceData; i++, mf++) {
1345                 float cent[3];
1346                 float no[3];
1347
1348                 if (index) {
1349                         orig = *index++;
1350                         if(orig == ORIGINDEX_NONE) continue;
1351                 }
1352                 else
1353                         orig = i;
1354
1355                 VECCOPY(cent, mv[mf->v1].co);
1356                 add_v3_v3(cent, mv[mf->v2].co);
1357                 add_v3_v3(cent, mv[mf->v3].co);
1358
1359                 if (mf->v4) {
1360                         normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1361                         add_v3_v3(cent, mv[mf->v4].co);
1362                         mul_v3_fl(cent, 0.25f);
1363                 } else {
1364                         normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1365                         mul_v3_fl(cent, 0.33333333333f);
1366                 }
1367
1368                 func(userData, orig, cent, no);
1369         }
1370 }
1371
1372 static void cdDM_free_internal(CDDerivedMesh *cddm)
1373 {
1374         if(cddm->fmap) MEM_freeN(cddm->fmap);
1375         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1376 }
1377
1378 static void cdDM_release(DerivedMesh *dm)
1379 {
1380         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1381
1382         if (DM_release(dm)) {
1383                 cdDM_free_internal(cddm);
1384                 MEM_freeN(cddm);
1385         }
1386 }
1387
1388 /**************** CDDM interface functions ****************/
1389 static CDDerivedMesh *cdDM_create(const char *desc)
1390 {
1391         CDDerivedMesh *cddm;
1392         DerivedMesh *dm;
1393
1394         cddm = MEM_callocN(sizeof(*cddm), desc);
1395         dm = &cddm->dm;
1396
1397         dm->getMinMax = cdDM_getMinMax;
1398
1399         dm->getNumVerts = cdDM_getNumVerts;
1400         dm->getNumFaces = cdDM_getNumFaces;
1401         dm->getNumEdges = cdDM_getNumEdges;
1402
1403         dm->getVert = cdDM_getVert;
1404         dm->getEdge = cdDM_getEdge;
1405         dm->getFace = cdDM_getFace;
1406         dm->copyVertArray = cdDM_copyVertArray;
1407         dm->copyEdgeArray = cdDM_copyEdgeArray;
1408         dm->copyFaceArray = cdDM_copyFaceArray;
1409         dm->getVertData = DM_get_vert_data;
1410         dm->getEdgeData = DM_get_edge_data;
1411         dm->getFaceData = DM_get_face_data;
1412         dm->getVertDataArray = DM_get_vert_data_layer;
1413         dm->getEdgeDataArray = DM_get_edge_data_layer;
1414         dm->getFaceDataArray = DM_get_face_data_layer;
1415
1416         dm->getVertCos = cdDM_getVertCos;
1417         dm->getVertCo = cdDM_getVertCo;
1418         dm->getVertNo = cdDM_getVertNo;
1419
1420         dm->getPBVH = cdDM_getPBVH;
1421         dm->getFaceMap = cdDM_getFaceMap;
1422
1423         dm->drawVerts = cdDM_drawVerts;
1424
1425         dm->drawUVEdges = cdDM_drawUVEdges;
1426         dm->drawEdges = cdDM_drawEdges;
1427         dm->drawLooseEdges = cdDM_drawLooseEdges;
1428         dm->drawMappedEdges = cdDM_drawMappedEdges;
1429
1430         dm->drawFacesSolid = cdDM_drawFacesSolid;
1431         dm->drawFacesColored = cdDM_drawFacesColored;
1432         dm->drawFacesTex = cdDM_drawFacesTex;
1433         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1434         dm->drawMappedFaces = cdDM_drawMappedFaces;
1435         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1436         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1437
1438         dm->foreachMappedVert = cdDM_foreachMappedVert;
1439         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1440         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1441
1442         dm->release = cdDM_release;
1443
1444         return cddm;
1445 }
1446
1447 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1448 {
1449         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1450         DerivedMesh *dm = &cddm->dm;
1451
1452         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1453
1454         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1455         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1456         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1457
1458         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1459         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1460         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1461
1462         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1463         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1464         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1465
1466         return dm;
1467 }
1468
1469 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
1470 {
1471         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1472         DerivedMesh *dm = &cddm->dm;
1473         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1474         int alloctype;
1475
1476         /* this does a referenced copy, with an exception for fluidsim */
1477
1478         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1479
1480         dm->deformedOnly = 1;
1481
1482         alloctype= CD_REFERENCE;
1483
1484         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1485                                          mesh->totvert);
1486         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1487                                          mesh->totedge);
1488         CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1489                                          mesh->totface);
1490
1491         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1492         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1493         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1494
1495         return dm;
1496 }
1497
1498 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
1499 {
1500         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1501                                                            BLI_countlist(&em->edges),
1502                                                            BLI_countlist(&em->faces));
1503         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1504         EditVert *eve;
1505         EditEdge *eed;
1506         EditFace *efa;
1507         MVert *mvert = cddm->mvert;
1508         MEdge *medge = cddm->medge;
1509         MFace *mface = cddm->mface;
1510         int i, *index;
1511
1512         dm->deformedOnly = 1;
1513
1514         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1515                                          CD_CALLOC, dm->numVertData);
1516         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1517                                          CD_CALLOC, dm->numEdgeData); */
1518         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1519                                          CD_CALLOC, dm->numFaceData);
1520
1521         /* set eve->hash to vert index */
1522         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1523                 eve->tmp.l = i;
1524
1525         /* Need to be able to mark loose edges */
1526         for(eed = em->edges.first; eed; eed = eed->next) {
1527                 eed->f2 = 0;
1528         }
1529         for(efa = em->faces.first; efa; efa = efa->next) {
1530                 efa->e1->f2 = 1;
1531                 efa->e2->f2 = 1;
1532                 efa->e3->f2 = 1;
1533                 if(efa->e4) efa->e4->f2 = 1;
1534         }
1535
1536         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1537         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1538                 i++, eve = eve->next, index++) {
1539                 MVert *mv = &mvert[i];
1540
1541                 VECCOPY(mv->co, eve->co);
1542
1543                 mv->no[0] = eve->no[0] * 32767.0;
1544                 mv->no[1] = eve->no[1] * 32767.0;
1545                 mv->no[2] = eve->no[2] * 32767.0;
1546                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1547
1548                 mv->mat_nr = 0;
1549                 mv->flag = 0;
1550
1551                 *index = i;
1552
1553                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1554         }
1555
1556         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1557         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1558                 i++, eed = eed->next, index++) {
1559                 MEdge *med = &medge[i];
1560
1561                 med->v1 = eed->v1->tmp.l;
1562                 med->v2 = eed->v2->tmp.l;
1563                 med->crease = (unsigned char) (eed->crease * 255.0f);
1564                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1565                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1566                 
1567                 if(eed->seam) med->flag |= ME_SEAM;
1568                 if(eed->sharp) med->flag |= ME_SHARP;
1569                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1570
1571                 *index = i;
1572
1573                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1574         }
1575
1576         index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1577         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1578                 i++, efa = efa->next, index++) {
1579                 MFace *mf = &mface[i];
1580
1581                 mf->v1 = efa->v1->tmp.l;
1582                 mf->v2 = efa->v2->tmp.l;
1583                 mf->v3 = efa->v3->tmp.l;
1584                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1585                 mf->mat_nr = efa->mat_nr;
1586                 mf->flag = efa->flag;
1587
1588                 *index = i;
1589
1590                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1591                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1592         }
1593
1594         return dm;
1595 }
1596
1597 DerivedMesh *CDDM_from_curve(Object *ob)
1598 {
1599         return CDDM_from_curve_customDB(ob, &((Curve *)ob->data)->disp);
1600 }
1601
1602 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1603 {
1604         DerivedMesh *dm;
1605         CDDerivedMesh *cddm;
1606         MVert *allvert;
1607         MEdge *alledge;
1608         MFace *allface;
1609         int totvert, totedge, totface;
1610
1611         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1612                 &totedge, &allface, &totface) != 0) {
1613                 /* Error initializing mdata. This often happens when curve is empty */
1614                 return CDDM_new(0, 0, 0);
1615         }
1616
1617         dm = CDDM_new(totvert, totedge, totface);
1618         dm->deformedOnly = 1;
1619
1620         cddm = (CDDerivedMesh*)dm;
1621
1622         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1623         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1624         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1625
1626         MEM_freeN(allvert);
1627         MEM_freeN(alledge);
1628         MEM_freeN(allface);
1629
1630         return dm;
1631 }
1632
1633 DerivedMesh *CDDM_copy(DerivedMesh *source)
1634 {
1635         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1636         DerivedMesh *dm = &cddm->dm;
1637         int numVerts = source->numVertData;
1638         int numEdges = source->numEdgeData;
1639         int numFaces = source->numFaceData;
1640
1641         /* ensure these are created if they are made on demand */
1642         source->getVertDataArray(source, CD_ORIGINDEX);
1643         source->getEdgeDataArray(source, CD_ORIGINDEX);
1644         source->getFaceDataArray(source, CD_ORIGINDEX);
1645
1646         /* this initializes dm, and copies all non mvert/medge/mface layers */
1647         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1648         dm->deformedOnly = source->deformedOnly;
1649
1650         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1651         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1652         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1653
1654         /* now add mvert/medge/mface layers */
1655         cddm->mvert = source->dupVertArray(source);
1656         cddm->medge = source->dupEdgeArray(source);
1657         cddm->mface = source->dupFaceArray(source);
1658
1659         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1660         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1661         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1662
1663         return dm;
1664 }
1665
1666 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1667                                                                 int numVerts, int numEdges, int numFaces)
1668 {
1669         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1670         DerivedMesh *dm = &cddm->dm;
1671
1672         /* this does a copy of all non mvert/medge/mface layers */
1673         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1674
1675         /* now add mvert/medge/mface layers */
1676         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1677         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1678         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1679
1680         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1681                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1682         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1683                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1684         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1685                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1686
1687         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1688         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1689         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1690
1691         return dm;
1692 }
1693
1694 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1695 {
1696         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1697         MVert *vert;
1698         int i;
1699
1700         /* this will just return the pointer if it wasn't a referenced layer */
1701         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1702         cddm->mvert = vert;
1703
1704         for(i = 0; i < dm->numVertData; ++i, ++vert)
1705                 VECCOPY(vert->co, vertCoords[i]);
1706 }
1707
1708 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1709 {
1710         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1711         MVert *vert;
1712         int i;
1713
1714         /* this will just return the pointer if it wasn't a referenced layer */
1715         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1716         cddm->mvert = vert;
1717
1718         for(i = 0; i < dm->numVertData; ++i, ++vert)
1719                 VECCOPY(vert->no, vertNormals[i]);
1720 }
1721
1722 /* adapted from mesh_calc_normals */
1723 void CDDM_calc_normals(DerivedMesh *dm)
1724 {
1725         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1726         float (*temp_nors)[3];
1727         float (*face_nors)[3];
1728         int i;
1729         int numVerts = dm->numVertData;
1730         int numFaces = dm->numFaceData;
1731         MFace *mf;
1732         MVert *mv;
1733
1734         if(numVerts == 0) return;
1735
1736         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
1737                                                         "CDDM_calc_normals temp_nors");
1738
1739         /* we don't want to overwrite any referenced layers */
1740         mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1741         cddm->mvert = mv;
1742
1743         /* make a face normal layer if not present */
1744         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1745         if(!face_nors)
1746                 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1747                                                                                  NULL, dm->numFaceData);
1748
1749         /* calculate face normals and add to vertex normals */
1750         mf = CDDM_get_faces(dm);
1751         for(i = 0; i < numFaces; i++, mf++) {
1752                 float *f_no = face_nors[i];
1753
1754                 if(mf->v4)
1755                         normal_quad_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1756                 else
1757                         normal_tri_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1758                 
1759                 add_v3_v3(temp_nors[mf->v1], f_no);
1760                 add_v3_v3(temp_nors[mf->v2], f_no);
1761                 add_v3_v3(temp_nors[mf->v3], f_no);
1762                 if(mf->v4)
1763                         add_v3_v3(temp_nors[mf->v4], f_no);
1764         }
1765
1766         /* normalize vertex normals and assign */
1767         for(i = 0; i < numVerts; i++, mv++) {
1768                 float *no = temp_nors[i];
1769                 
1770                 if (normalize_v3(no) == 0.0) {
1771                         VECCOPY(no, mv->co);
1772                         normalize_v3(no);
1773                 }
1774
1775                 mv->no[0] = (short)(no[0] * 32767.0);
1776                 mv->no[1] = (short)(no[1] * 32767.0);
1777                 mv->no[2] = (short)(no[2] * 32767.0);
1778         }
1779         
1780         MEM_freeN(temp_nors);
1781 }
1782
1783 void CDDM_calc_edges(DerivedMesh *dm)
1784 {
1785         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1786         CustomData edgeData;
1787         EdgeHashIterator *ehi;
1788         MFace *mf = cddm->mface;
1789         MEdge *med;
1790         EdgeHash *eh = BLI_edgehash_new();
1791         int i, *index, numEdges, maxFaces = dm->numFaceData;
1792
1793         for (i = 0; i < maxFaces; i++, mf++) {
1794                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1795                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1796                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1797                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1798                 
1799                 if (mf->v4) {
1800                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1801                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1802                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1803                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1804                 } else {
1805                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1806                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1807                 }
1808         }
1809
1810         numEdges = BLI_edgehash_size(eh);
1811
1812         /* write new edges into a temporary CustomData */
1813         memset(&edgeData, 0, sizeof(edgeData));
1814         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1815         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1816
1817         ehi = BLI_edgehashIterator_new(eh);
1818         med = CustomData_get_layer(&edgeData, CD_MEDGE);
1819         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1820         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1821                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1822                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1823
1824                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1825                 *index = ORIGINDEX_NONE;
1826         }
1827         BLI_edgehashIterator_free(ehi);
1828
1829         /* free old CustomData and assign new one */
1830         CustomData_free(&dm->edgeData, dm->numEdgeData);
1831         dm->edgeData = edgeData;
1832         dm->numEdgeData = numEdges;
1833
1834         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1835
1836         BLI_edgehash_free(eh, NULL);
1837 }
1838
1839 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1840 {
1841         if (numVerts < dm->numVertData)
1842                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1843
1844         dm->numVertData = numVerts;
1845 }
1846
1847 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1848 {
1849         if (numEdges < dm->numEdgeData)
1850                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1851
1852         dm->numEdgeData = numEdges;
1853 }
1854
1855 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1856 {
1857         if (numFaces < dm->numFaceData)
1858                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1859
1860         dm->numFaceData = numFaces;
1861 }
1862
1863 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1864 {
1865         return &((CDDerivedMesh*)dm)->mvert[index];
1866 }
1867
1868 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1869 {
1870         return &((CDDerivedMesh*)dm)->medge[index];
1871 }
1872
1873 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1874 {
1875         return &((CDDerivedMesh*)dm)->mface[index];
1876 }
1877
1878 MVert *CDDM_get_verts(DerivedMesh *dm)
1879 {
1880         return ((CDDerivedMesh*)dm)->mvert;
1881 }
1882
1883 MEdge *CDDM_get_edges(DerivedMesh *dm)
1884 {
1885         return ((CDDerivedMesh*)dm)->medge;
1886 }
1887
1888 MFace *CDDM_get_faces(DerivedMesh *dm)
1889 {
1890         return ((CDDerivedMesh*)dm)->mface;
1891 }
1892