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