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