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