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