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