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