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