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