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