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