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