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