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