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