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