=bmesh=
[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 #include "BKE_tessmesh.h"
45
46 #include "BLI_editVert.h"
47 #include "BLI_scanfill.h"
48 #include "BLI_math.h"
49 #include "BLI_blenlib.h"
50 #include "BLI_edgehash.h"
51 #include "BLI_editVert.h"
52 #include "BLI_math.h"
53 #include "BLI_pbvh.h"
54 #include "BLI_array.h"
55 #include "BLI_smallhash.h"
56 #include "BLI_utildefines.h"
57
58 #include "BKE_cdderivedmesh.h"
59 #include "BKE_global.h"
60 #include "BKE_mesh.h"
61 #include "BKE_paint.h"
62
63
64 #include "DNA_meshdata_types.h"
65 #include "DNA_object_types.h"
66 #include "DNA_curve_types.h" /* for Curve */
67
68 #include "MEM_guardedalloc.h"
69
70 #include "GPU_buffers.h"
71 #include "GPU_draw.h"
72 #include "GPU_extensions.h"
73 #include "GPU_material.h"
74
75 #include <string.h>
76 #include <limits.h>
77 #include <math.h>
78
79 typedef struct {
80         DerivedMesh dm;
81
82         /* these point to data in the DerivedMesh custom data layers,
83            they are only here for efficiency and convenience **/
84         MVert *mvert;
85         MEdge *medge;
86         MFace *mface;
87         MLoop *mloop;
88         MPoly *mpoly;
89
90         /* Cached */
91         struct PBVH *pbvh;
92         int pbvh_draw;
93
94         /* Mesh connectivity */
95         struct ListBase *fmap;
96         struct IndexNode *fmap_mem;
97 } CDDerivedMesh;
98
99 DMFaceIter *cdDM_newFaceIter(DerivedMesh *source);
100
101 /**************** DerivedMesh interface functions ****************/
102 static int cdDM_getNumVerts(DerivedMesh *dm)
103 {
104         return dm->numVertData;
105 }
106
107 static int cdDM_getNumEdges(DerivedMesh *dm)
108 {
109         return dm->numEdgeData;
110 }
111
112 static int cdDM_getNumTessFaces(DerivedMesh *dm)
113 {
114         return dm->numFaceData;
115 }
116
117 static int cdDM_getNumFaces(DerivedMesh *dm)
118 {
119         return dm->numPolyData;
120 }
121
122 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
123 {
124         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
125         *vert_r = cddm->mvert[index];
126 }
127
128 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
129 {
130         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
131         *edge_r = cddm->medge[index];
132 }
133
134 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
135 {
136         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
137         *face_r = cddm->mface[index];
138 }
139
140 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
141 {
142         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
143         memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
144 }
145
146 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
147 {
148         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
149         memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
150 }
151
152 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
153 {
154         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
155         memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
156 }
157
158 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
159 {
160         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
161         int i;
162
163         if (dm->numVertData) {
164                 for (i=0; i<dm->numVertData; i++) {
165                         DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
166                 }
167         } else {
168                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
169         }
170 }
171
172 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
173 {
174         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
175
176         VECCOPY(co_r, cddm->mvert[index].co);
177 }
178
179 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
180 {
181         MVert *mv = CDDM_get_verts(dm);
182         int i;
183
184         for(i = 0; i < dm->numVertData; i++, mv++)
185                 VECCOPY(cos_r[i], mv->co);
186 }
187
188 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
189 {
190         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
191         short *no = cddm->mvert[index].no;
192
193         no_r[0] = no[0]/32767.f;
194         no_r[1] = no[1]/32767.f;
195         no_r[2] = no[2]/32767.f;
196 }
197
198 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
199 {
200         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
201
202         if(!cddm->fmap && ob->type == OB_MESH) {
203                 Mesh *me= ob->data;
204
205                 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
206                                          me->totvert, me->totface);
207         }
208
209         return cddm->fmap;
210 }
211
212 static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
213 {
214         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
215         Mesh *me= ob->data;
216
217         if(ob->sculpt->modifiers_active) return 0;
218
219         return (cddm->mvert == me->mvert) || ob->sculpt->kb;
220 }
221
222 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
223 {
224         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
225
226         if(!ob) {
227                 cddm->pbvh= NULL;
228                 return NULL;
229         }
230
231         if(!ob->sculpt)
232                 return NULL;
233         if(ob->sculpt->pbvh) {
234                 cddm->pbvh= ob->sculpt->pbvh;
235                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
236         }
237
238         /* always build pbvh from original mesh, and only use it for drawing if
239            this derivedmesh is just original mesh. it's the multires subsurf dm
240            that this is actually for, to support a pbvh on a modified mesh */
241         if(!cddm->pbvh && ob->type == OB_MESH) {
242                 Mesh *me= ob->data;
243                 cddm->pbvh = BLI_pbvh_new();
244                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
245                 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
246                                    me->totface, me->totvert);
247
248                 if(ob->sculpt->modifiers_active) {
249                         float (*vertCos)[3];
250                         int totvert;
251
252                         totvert= dm->getNumVerts(dm);
253                         vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
254                         dm->getVertCos(dm, vertCos);
255                         BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
256                         MEM_freeN(vertCos);
257                 }
258         }
259
260         return cddm->pbvh;
261 }
262
263 /* update vertex normals so that drawing smooth faces works during sculpt
264    TODO: proper fix is to support the pbvh in all drawing modes */
265 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
266 {
267         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
268         float (*face_nors)[3];
269
270         if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
271                 return;
272
273         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
274
275         BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
276 }
277
278 static void cdDM_drawVerts(DerivedMesh *dm)
279 {
280         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
281         MVert *mv = cddm->mvert;
282         int i;
283
284         if( GPU_buffer_legacy(dm) ) {
285                 glBegin(GL_POINTS);
286                 for(i = 0; i < dm->numVertData; i++, mv++)
287                         glVertex3fv(mv->co);
288                 glEnd();
289         }
290         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
291                 GPU_vertex_setup(dm);
292                 if( !GPU_buffer_legacy(dm) ) {
293                         if(dm->drawObject->nelements)   glDrawArrays(GL_POINTS,0, dm->drawObject->nelements);
294                         else                                                    glDrawArrays(GL_POINTS,0, dm->drawObject->nlooseverts);
295                 }
296                 GPU_buffer_unbind();
297         }
298 }
299
300 static void cdDM_drawUVEdges(DerivedMesh *dm)
301 {
302         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
303         MFace *mf = cddm->mface;
304         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
305         int i;
306
307         if(mf) {
308                 if( GPU_buffer_legacy(dm) ) {
309                         glBegin(GL_LINES);
310                         for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
311                                 if(!(mf->flag&ME_HIDE)) {
312                                         glVertex2fv(tf->uv[0]);
313                                         glVertex2fv(tf->uv[1]);
314
315                                         glVertex2fv(tf->uv[1]);
316                                         glVertex2fv(tf->uv[2]);
317
318                                         if(!mf->v4) {
319                                                 glVertex2fv(tf->uv[2]);
320                                                 glVertex2fv(tf->uv[0]);
321                                         } else {
322                                                 glVertex2fv(tf->uv[2]);
323                                                 glVertex2fv(tf->uv[3]);
324
325                                                 glVertex2fv(tf->uv[3]);
326                                                 glVertex2fv(tf->uv[0]);
327                                         }
328                                 }
329                         }
330                         glEnd();
331                 }
332                 else {
333                         int prevstart = 0;
334                         int prevdraw = 1;
335                         int draw = 1;
336                         int curpos = 0;
337
338                         GPU_uvedge_setup(dm);
339                         if( !GPU_buffer_legacy(dm) ) {
340                                 for(i = 0; i < dm->numFaceData; i++, mf++) {
341                                         if(!(mf->flag&ME_HIDE)) {
342                                                 draw = 1;
343                                         } 
344                                         else {
345                                                 draw = 0;
346                                         }
347                                         if( prevdraw != draw ) {
348                                                 if( prevdraw > 0 && (curpos-prevstart) > 0) {
349                                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
350                                                 }
351                                                 prevstart = curpos;
352                                         }
353                                         if( mf->v4 ) {
354                                                 curpos += 8;
355                                         }
356                                         else {
357                                                 curpos += 6;
358                                         }
359                                         prevdraw = draw;
360                                 }
361                                 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
362                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
363                                 }
364                         }
365                         GPU_buffer_unbind();
366                 }
367         }
368 }
369
370 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges)
371 {
372         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
373         MVert *mvert = cddm->mvert;
374         MEdge *medge = cddm->medge;
375         int i;
376         
377         if( GPU_buffer_legacy(dm) ) {
378                 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
379                 glBegin(GL_LINES);
380                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
381                         if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
382                            && (drawLooseEdges || !(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((drawAllEdges || (medge->flag&ME_EDGEDRAW))
398                                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
399                                         draw = 1;
400                                 } 
401                                 else {
402                                         draw = 0;
403                                 }
404                                 if( prevdraw != draw ) {
405                                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
406                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
407                                         }
408                                         prevstart = i;
409                                 }
410                                 prevdraw = draw;
411                         }
412                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
413                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
414                         }
415                 }
416                 GPU_buffer_unbind();
417         }
418 }
419
420 static void cdDM_drawLooseEdges(DerivedMesh *dm)
421 {
422         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
423         MVert *mvert = cddm->mvert;
424         MEdge *medge = cddm->medge;
425         int i;
426
427         if( GPU_buffer_legacy(dm) ) {
428                 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
429                 glBegin(GL_LINES);
430                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
431                         if(medge->flag&ME_LOOSEEDGE) {
432                                 glVertex3fv(mvert[medge->v1].co);
433                                 glVertex3fv(mvert[medge->v2].co);
434                         }
435                 }
436                 glEnd();
437         }
438         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
439                 int prevstart = 0;
440                 int prevdraw = 1;
441                 int draw = 1;
442
443                 GPU_edge_setup(dm);
444                 if( !GPU_buffer_legacy(dm) ) {
445                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
446                                 if(medge->flag&ME_LOOSEEDGE) {
447                                         draw = 1;
448                                 } 
449                                 else {
450                                         draw = 0;
451                                 }
452                                 if( prevdraw != draw ) {
453                                         if( prevdraw > 0 && (i-prevstart) > 0) {
454                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
455                                         }
456                                         prevstart = i;
457                                 }
458                                 prevdraw = draw;
459                         }
460                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
461                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
462                         }
463                 }
464                 GPU_buffer_unbind();
465         }
466 }
467
468 static void cdDM_drawFacesSolid(DerivedMesh *dm,
469                                 float (*partial_redraw_planes)[4],
470                                 int UNUSED(fast), int (*setMaterial)(int, void *attribs))
471 {
472         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
473         MVert *mvert = cddm->mvert;
474         MFace *mface = cddm->mface;
475         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
476         int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
477
478 #define PASSVERT(index) {                                               \
479         if(shademodel == GL_SMOOTH) {                           \
480                 short *no = mvert[index].no;                    \
481                 glNormal3sv(no);                                                \
482         }                                                                                       \
483         glVertex3fv(mvert[index].co);   \
484 }
485
486         if(cddm->pbvh && cddm->pbvh_draw) {
487                 if(dm->numFaceData) {
488                         float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
489
490                         /* should be per face */
491                         if(!setMaterial(mface->mat_nr+1, NULL))
492                                 return;
493
494                         glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
495                         BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH));
496                         glShadeModel(GL_FLAT);
497                 }
498
499                 return;
500         }
501
502         if( GPU_buffer_legacy(dm) ) {
503                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
504                 glBegin(glmode = GL_QUADS);
505                 for(a = 0; a < dm->numFaceData; a++, mface++) {
506                         int new_glmode, new_matnr, new_shademodel;
507
508                         new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
509                         new_matnr = mface->mat_nr + 1;
510                         new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
511                         
512                         if(new_glmode != glmode || new_matnr != matnr
513                            || new_shademodel != shademodel) {
514                                 glEnd();
515
516                                 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
517
518                                 glShadeModel(shademodel = new_shademodel);
519                                 glBegin(glmode = new_glmode);
520                         } 
521                         
522                         if(drawCurrentMat) {
523                                 if(shademodel == GL_FLAT) {
524                                         if (nors) {
525                                                 glNormal3fv(nors);
526                                         }
527                                         else {
528                                                 /* TODO make this better (cache facenormals as layer?) */
529                                                 float nor[3];
530                                                 if(mface->v4) {
531                                                         normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
532                                                 } else {
533                                                         normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
534                                                 }
535                                                 glNormal3fv(nor);
536                                         }
537                                 }
538
539                                 PASSVERT(mface->v1);
540                                 PASSVERT(mface->v2);
541                                 PASSVERT(mface->v3);
542                                 if(mface->v4) {
543                                         PASSVERT(mface->v4);
544                                 }
545                         }
546
547                         if(nors) nors += 3;
548                 }
549                 glEnd();
550         }
551         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
552                 GPU_vertex_setup( dm );
553                 GPU_normal_setup( dm );
554                 if( !GPU_buffer_legacy(dm) ) {
555                         glShadeModel(GL_SMOOTH);
556                         for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
557                                 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
558                                         glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
559                         }
560                 }
561                 GPU_buffer_unbind( );
562         }
563
564 #undef PASSVERT
565         glShadeModel(GL_FLAT);
566 }
567
568 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
569 {
570         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
571         int a, glmode;
572         unsigned char *cp1, *cp2;
573         MVert *mvert = cddm->mvert;
574         MFace *mface = cddm->mface;
575
576         cp1 = col1;
577         if(col2) {
578                 cp2 = col2;
579         } else {
580                 cp2 = NULL;
581                 useTwoSided = 0;
582         }
583
584         /* there's a conflict here... twosided colors versus culling...? */
585         /* defined by history, only texture faces have culling option */
586         /* we need that as mesh option builtin, next to double sided lighting */
587         if(col1 && col2)
588                 glEnable(GL_CULL_FACE);
589
590         cdDM_update_normals_from_pbvh(dm);
591
592         if( GPU_buffer_legacy(dm) ) {
593                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
594                 glShadeModel(GL_SMOOTH);
595                 glBegin(glmode = GL_QUADS);
596                 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
597                         int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
598
599                         if(new_glmode != glmode) {
600                                 glEnd();
601                                 glBegin(glmode = new_glmode);
602                         }
603                                 
604                         glColor3ub(cp1[0], cp1[1], cp1[2]);
605                         glVertex3fv(mvert[mface->v1].co);
606                         glColor3ub(cp1[4], cp1[5], cp1[6]);
607                         glVertex3fv(mvert[mface->v2].co);
608                         glColor3ub(cp1[8], cp1[9], cp1[10]);
609                         glVertex3fv(mvert[mface->v3].co);
610                         if(mface->v4) {
611                                 glColor3ub(cp1[12], cp1[13], cp1[14]);
612                                 glVertex3fv(mvert[mface->v4].co);
613                         }
614                                 
615                         if(useTwoSided) {
616                                 glColor3ub(cp2[8], cp2[9], cp2[10]);
617                                 glVertex3fv(mvert[mface->v3].co );
618                                 glColor3ub(cp2[4], cp2[5], cp2[6]);
619                                 glVertex3fv(mvert[mface->v2].co );
620                                 glColor3ub(cp2[0], cp2[1], cp2[2]);
621                                 glVertex3fv(mvert[mface->v1].co );
622                                 if(mface->v4) {
623                                         glColor3ub(cp2[12], cp2[13], cp2[14]);
624                                         glVertex3fv(mvert[mface->v4].co );
625                                 }
626                         }
627                         if(col2) cp2 += 16;
628                 }
629                 glEnd();
630         }
631         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
632                 GPU_color4_upload(dm,cp1);
633                 GPU_vertex_setup(dm);
634                 GPU_color_setup(dm);
635                 if( !GPU_buffer_legacy(dm) ) {
636                         glShadeModel(GL_SMOOTH);
637                         glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
638
639                         if( useTwoSided ) {
640                                 GPU_color4_upload(dm,cp2);
641                                 GPU_color_setup(dm);
642                                 glCullFace(GL_FRONT);
643                                 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
644                                 glCullFace(GL_BACK);
645                         }
646                 }
647                 GPU_buffer_unbind();
648         }
649
650         glShadeModel(GL_FLAT);
651         glDisable(GL_CULL_FACE);
652 }
653
654 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
655                int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
656                int (*drawParamsMapped)(void *userData, int index),
657                void *userData) 
658 {
659         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
660         MVert *mv = cddm->mvert;
661         MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
662         MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
663         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
664         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
665         int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
666         int startFace = 0, lastFlag = 0xdeadbeef;
667         MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
668         if(!mcol)
669                 mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
670
671         cdDM_update_normals_from_pbvh(dm);
672
673         if( GPU_buffer_legacy(dm) ) {
674                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
675                 for(i = 0; i < dm->numFaceData; i++, mf++) {
676                         MVert *mvert;
677                         int flag;
678                         unsigned char *cp = NULL;
679
680                         if(drawParams) {
681                                 flag = drawParams(tf? &tf[i]: NULL, mcol!=NULL, mf->mat_nr);
682                         }
683                         else {
684                                 if(index) {
685                                         orig = *index++;
686                                         if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
687                                         if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
688                                         else    { if(nors) nors += 3; continue; }
689                                 }
690                                 else
691                                         if(drawParamsMapped) flag = drawParamsMapped(userData, i);
692                                         else    { if(nors) nors += 3; continue; }
693                         }
694                         
695                         if(flag != 0) {
696                                 if (flag==1 && mcol)
697                                         cp= (unsigned char*) &mcol[i*4];
698
699                                 if(!(mf->flag&ME_SMOOTH)) {
700                                         if (nors) {
701                                                 glNormal3fv(nors);
702                                         }
703                                         else {
704                                                 float nor[3];
705                                                 if(mf->v4) {
706                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
707                                                 } else {
708                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
709                                                 }
710                                                 glNormal3fv(nor);
711                                         }
712                                 }
713
714                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
715                                 if(tf) glTexCoord2fv(tf[i].uv[0]);
716                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
717                                 mvert = &mv[mf->v1];
718                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
719                                 glVertex3fv(mvert->co);
720                                         
721                                 if(tf) glTexCoord2fv(tf[i].uv[1]);
722                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
723                                 mvert = &mv[mf->v2];
724                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
725                                 glVertex3fv(mvert->co);
726
727                                 if(tf) glTexCoord2fv(tf[i].uv[2]);
728                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
729                                 mvert = &mv[mf->v3];
730                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
731                                 glVertex3fv(mvert->co);
732
733                                 if(mf->v4) {
734                                         if(tf) glTexCoord2fv(tf[i].uv[3]);
735                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
736                                         mvert = &mv[mf->v4];
737                                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
738                                         glVertex3fv(mvert->co);
739                                 }
740                                 glEnd();
741                         }
742                         
743                         if(nors) nors += 3;
744                 }
745         } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
746                 MCol *col = realcol;
747                 if(!col)
748                         col = mcol;
749
750                 GPU_vertex_setup( dm );
751                 GPU_normal_setup( dm );
752                 GPU_uv_setup( dm );
753                 if( col != NULL ) {
754                         /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL )  {
755                                 col = 0;
756                         } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
757                                 col = 0;
758                         }
759                         
760                         if( col != 0 ) {*/
761                                 unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
762                                 for( i=0; i < dm->getNumTessFaces(dm); i++ ) {
763                                         for( j=0; j < 4; j++ ) {
764                                                 colors[i*12+j*3] = col[i*4+j].r;
765                                                 colors[i*12+j*3+1] = col[i*4+j].g;
766                                                 colors[i*12+j*3+2] = col[i*4+j].b;
767                                         }
768                                 }
769                                 GPU_color3_upload(dm,colors);
770                                 MEM_freeN(colors);
771                                 if(realcol)
772                                         dm->drawObject->colType = CD_TEXTURE_MCOL;
773                                 else if(mcol)
774                                         dm->drawObject->colType = CD_MCOL;
775                         //}
776                         GPU_color_setup( dm );
777                 }
778
779                 if( !GPU_buffer_legacy(dm) ) {
780                         glShadeModel( GL_SMOOTH );
781                         lastFlag = 0;
782                         for(i = 0; i < dm->drawObject->nelements/3; i++) {
783                                 int actualFace = dm->drawObject->faceRemap[i];
784                                 int flag = 1;
785
786                                 if(drawParams) {
787                                         flag = drawParams(tf? &tf[actualFace]: NULL, mcol!=NULL, mf[actualFace].mat_nr);
788                                 }
789                                 else {
790                                         if(index) {
791                                                 orig = index[actualFace];
792                                                 if(orig == ORIGINDEX_NONE) continue;
793                                                 if(drawParamsMapped)
794                                                         flag = drawParamsMapped(userData, orig);
795                                         }
796                                         else
797                                                 if(drawParamsMapped)
798                                                         flag = drawParamsMapped(userData, actualFace);
799                                 }
800                                 if( flag != lastFlag ) {
801                                         if( startFace < i ) {
802                                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
803                                                         if (lastFlag==1 && col)
804                                                                 GPU_color_switch(1);
805                                                         else
806                                                                 GPU_color_switch(0);
807                                                         glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
808                                                 }
809                                         }
810                                         lastFlag = flag;
811                                         startFace = i;
812                                 }
813                         }
814                         if( startFace < dm->drawObject->nelements/3 ) {
815                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
816                                         if (lastFlag==1 && col)
817                                                 GPU_color_switch(1);
818                                         else
819                                                 GPU_color_switch(0);
820                                         glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
821                                 }
822                         }
823                 }
824
825                 GPU_buffer_unbind();
826                 glShadeModel( GL_FLAT );
827         }
828 }
829
830 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
831 {
832         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
833 }
834
835 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs))
836 {
837         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
838         MVert *mv = cddm->mvert;
839         MFace *mf = cddm->mface;
840         MCol *mc;
841         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
842         int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
843
844         mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL);
845         if(!mc)
846                 mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL);
847         if(!mc)
848                 mc = DM_get_tessface_data_layer(dm, CD_MCOL);
849
850         cdDM_update_normals_from_pbvh(dm);
851
852         /* back-buffer always uses legacy since VBO's would need the
853          * color array temporarily overwritten for drawing, then reset. */
854         if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
855                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
856                 for(i = 0; i < dm->numFaceData; i++, mf++) {
857                         int drawSmooth = (mf->flag & ME_SMOOTH);
858                         int draw= 1;
859
860                         orig= (index==NULL) ? i : *index++;
861                         
862                         if(orig == ORIGINDEX_NONE)
863                                 draw= setMaterial(mf->mat_nr + 1, NULL);
864                         else if (setDrawOptions != NULL)
865                                 draw= setDrawOptions(userData, orig, &drawSmooth);
866
867                         if(draw) {
868                                 unsigned char *cp = NULL;
869
870                                 if(useColors && mc)
871                                         cp = (unsigned char *)&mc[i * 4];
872
873                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
874                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
875
876                                 if (!drawSmooth) {
877                                         if (nors) {
878                                                 glNormal3fv(nors);
879                                         }
880                                         else {
881                                                 float nor[3];
882                                                 if(mf->v4) {
883                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
884                                                 } else {
885                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
886                                                 }
887                                                 glNormal3fv(nor);
888                                         }
889
890                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
891                                         glVertex3fv(mv[mf->v1].co);
892                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
893                                         glVertex3fv(mv[mf->v2].co);
894                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
895                                         glVertex3fv(mv[mf->v3].co);
896                                         if(mf->v4) {
897                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
898                                                 glVertex3fv(mv[mf->v4].co);
899                                         }
900                                 } else {
901                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
902                                         glNormal3sv(mv[mf->v1].no);
903                                         glVertex3fv(mv[mf->v1].co);
904                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
905                                         glNormal3sv(mv[mf->v2].no);
906                                         glVertex3fv(mv[mf->v2].co);
907                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
908                                         glNormal3sv(mv[mf->v3].no);
909                                         glVertex3fv(mv[mf->v3].co);
910                                         if(mf->v4) {
911                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
912                                                 glNormal3sv(mv[mf->v4].no);
913                                                 glVertex3fv(mv[mf->v4].co);
914                                         }
915                                 }
916
917                                 glEnd();
918                         }
919                         
920                         if (nors) nors += 3;
921                 }
922         }
923         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
924                 int prevstart = 0;
925                 GPU_vertex_setup(dm);
926                 GPU_normal_setup(dm);
927                 if( useColors && mc )
928                         GPU_color_setup(dm);
929                 if( !GPU_buffer_legacy(dm) ) {
930                         int tottri = dm->drawObject->nelements/3;
931                         glShadeModel(GL_SMOOTH);
932                         
933                         if(tottri == 0) {
934                                 /* avoid buffer problems in following code */
935                         }
936                         if(setDrawOptions == NULL) {
937                                 /* just draw the entire face array */
938                                 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
939                         }
940                         else {
941                                 /* we need to check if the next material changes */
942                                 int next_actualFace= dm->drawObject->faceRemap[0];
943                                 
944                                 for( i = 0; i < tottri; i++ ) {
945                                         //int actualFace = dm->drawObject->faceRemap[i];
946                                         int actualFace = next_actualFace;
947                                         MFace *mface= mf + actualFace;
948                                         int drawSmooth= (mface->flag & ME_SMOOTH);
949                                         int draw = 1;
950
951                                         if(i != tottri-1)
952                                                 next_actualFace= dm->drawObject->faceRemap[i+1];
953
954                                         orig= (index==NULL) ? actualFace : index[actualFace];
955
956                                         if(orig == ORIGINDEX_NONE)
957                                                 draw= setMaterial(mface->mat_nr + 1, NULL);
958                                         else if (setDrawOptions != NULL)
959                                                 draw= setDrawOptions(userData, orig, &drawSmooth);
960         
961                                         /* Goal is to draw as long of a contiguous triangle
962                                            array as possible, so draw when we hit either an
963                                            invisible triangle or at the end of the array */
964                                         if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
965                                                 if(prevstart != i)
966                                                         /* Add one to the length (via `draw')
967                                                            if we're drawing at the end of the array */
968                                                         glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
969                                                 prevstart = i + 1;
970                                         }
971                                 }
972                         }
973
974                         glShadeModel(GL_FLAT);
975                 }
976                 GPU_buffer_unbind();
977         }
978 }
979
980 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
981 {
982         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
983 }
984
985 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
986 {
987         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
988         GPUVertexAttribs gattribs;
989         DMVertexAttribs attribs;
990         MVert *mvert = cddm->mvert;
991         MFace *mface = cddm->mface;
992         MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
993         float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
994         int a, b, dodraw, matnr, new_matnr;
995         int transp, new_transp, orig_transp;
996         int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
997
998         cdDM_update_normals_from_pbvh(dm);
999
1000         matnr = -1;
1001         dodraw = 0;
1002         transp = GPU_get_material_blend_mode();
1003         orig_transp = transp;
1004
1005         glShadeModel(GL_SMOOTH);
1006
1007         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1008                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1009                 memset(&attribs, 0, sizeof(attribs));
1010
1011                 glBegin(GL_QUADS);
1012
1013                 for(a = 0; a < dm->numFaceData; a++, mface++) {
1014                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1015                         new_matnr = mface->mat_nr + 1;
1016
1017                         if(new_matnr != matnr) {
1018                                 glEnd();
1019
1020                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1021                                 if(dodraw)
1022                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1023
1024                                 glBegin(GL_QUADS);
1025                         }
1026
1027                         if(!dodraw) {
1028                                 continue;
1029                         }
1030                         else if(setDrawOptions) {
1031                                 orig = (index)? index[a]: a;
1032
1033                                 if(orig == ORIGINDEX_NONE) {
1034                                         /* since the material is set by setMaterial(), faces with no
1035                                          * origin can be assumed to be generated by a modifier */ 
1036                                         
1037                                         /* continue */
1038                                 }
1039                                 else if(!setDrawOptions(userData, orig))
1040                                         continue;
1041                         }
1042
1043                         if(tf) {
1044                                 new_transp = tf[a].transp;
1045
1046                                 if(new_transp != transp) {
1047                                         glEnd();
1048
1049                                         if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1050                                                 GPU_set_material_blend_mode(orig_transp);
1051                                         else
1052                                                 GPU_set_material_blend_mode(new_transp);
1053                                         transp = new_transp;
1054
1055                                         glBegin(GL_QUADS);
1056                                 }
1057                         }
1058
1059                         if(!smoothnormal) {
1060                                 if(nors) {
1061                                         glNormal3fv(nors[a]);
1062                                 }
1063                                 else {
1064                                         /* TODO ideally a normal layer should always be available */
1065                                         float nor[3];
1066                                         if(mface->v4) {
1067                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1068                                         } else {
1069                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1070                                         }
1071                                         glNormal3fv(nor);
1072                                 }
1073                         }
1074
1075 #define PASSVERT(index, vert) {                                                                                                 \
1076                 if(attribs.totorco)                                                                                                                     \
1077                         glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
1078                 for(b = 0; b < attribs.tottface; b++) {                                                                         \
1079                         MTFace *tf = &attribs.tface[b].array[a];                                                                \
1080                         glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
1081                 }                                                                                                                                                       \
1082                 for(b = 0; b < attribs.totmcol; b++) {                                                                          \
1083                         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
1084                         GLubyte col[4];                                                                                                                 \
1085                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
1086                         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
1087                 }                                                                                                                                                       \
1088                 if(attribs.tottang) {                                                                                                           \
1089                         float *tang = attribs.tang.array[a*4 + vert];                                                   \
1090                         glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
1091                 }                                                                                                                                                       \
1092                 if(smoothnormal)                                                                                                                        \
1093                         glNormal3sv(mvert[index].no);                                                                                   \
1094                 glVertex3fv(mvert[index].co);                                                                                           \
1095         }
1096
1097                         PASSVERT(mface->v1, 0);
1098                         PASSVERT(mface->v2, 1);
1099                         PASSVERT(mface->v3, 2);
1100                         if(mface->v4)
1101                                 PASSVERT(mface->v4, 3)
1102                         else
1103                                 PASSVERT(mface->v3, 2)
1104
1105                 }
1106                 glEnd();
1107         }
1108         else {
1109                 GPUBuffer *buffer = NULL;
1110                 char *varray = NULL;
1111                 int numdata = 0, elementsize = 0, offset;
1112                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1113                 int i;
1114
1115                 MFace *mf = mface;
1116                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1117                 memset(&attribs, 0, sizeof(attribs));
1118
1119                 GPU_vertex_setup(dm);
1120                 GPU_normal_setup(dm);
1121
1122                 if( !GPU_buffer_legacy(dm) ) {
1123                         for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
1124
1125                                 a = dm->drawObject->faceRemap[i];
1126
1127                                 mface = mf + a;
1128                                 new_matnr = mface->mat_nr + 1;
1129
1130                                 if(new_matnr != matnr ) {
1131                                         numfaces = curface - start;
1132                                         if( numfaces > 0 ) {
1133
1134                                                 if( dodraw ) {
1135
1136                                                         if( numdata != 0 ) {
1137
1138                                                                 GPU_buffer_unlock(buffer);
1139
1140                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1141                                                         }
1142
1143                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1144
1145                                                         if( numdata != 0 ) {
1146
1147                                                                 GPU_buffer_free(buffer, NULL);
1148
1149                                                                 buffer = NULL;
1150                                                         }
1151
1152                                                 }
1153                                         }
1154                                         numdata = 0;
1155                                         start = curface;
1156                                         prevdraw = dodraw;
1157                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1158                                         if(dodraw) {
1159                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1160
1161                                                 if(attribs.totorco) {
1162                                                         datatypes[numdata].index = attribs.orco.glIndex;
1163                                                         datatypes[numdata].size = 3;
1164                                                         datatypes[numdata].type = GL_FLOAT;
1165                                                         numdata++;
1166                                                 }
1167                                                 for(b = 0; b < attribs.tottface; b++) {
1168                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1169                                                         datatypes[numdata].size = 2;
1170                                                         datatypes[numdata].type = GL_FLOAT;
1171                                                         numdata++;
1172                                                 }       
1173                                                 for(b = 0; b < attribs.totmcol; b++) {
1174                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1175                                                         datatypes[numdata].size = 4;
1176                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1177                                                         numdata++;
1178                                                 }       
1179                                                 if(attribs.tottang) {
1180                                                         datatypes[numdata].index = attribs.tang.glIndex;
1181                                                         datatypes[numdata].size = 4;
1182                                                         datatypes[numdata].type = GL_FLOAT;
1183                                                         numdata++;
1184                                                 }
1185                                                 if( numdata != 0 ) {
1186                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1187                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL );
1188                                                         if( buffer == NULL ) {
1189                                                                 GPU_buffer_unbind();
1190                                                                 dm->drawObject->legacy = 1;
1191                                                                 return;
1192                                                         }
1193                                                         varray = GPU_buffer_lock_stream(buffer);
1194                                                         if( varray == NULL ) {
1195                                                                 GPU_buffer_unbind();
1196                                                                 GPU_buffer_free(buffer, NULL);
1197                                                                 dm->drawObject->legacy = 1;
1198                                                                 return;
1199                                                         }
1200                                                 }
1201                                                 else {
1202                                                         /* if the buffer was set, dont use it again.
1203                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1204                                                         prevdraw= 0;
1205                                                         buffer= NULL;
1206                                                 }
1207                                         }
1208                                 }
1209                                 if(!dodraw) {
1210                                         continue;
1211                                 }
1212
1213                                 if(tf) {
1214                                         new_transp = tf[a].transp;
1215
1216                                         if(new_transp != transp) {
1217                                                 numfaces = curface - start;
1218                                                 if( numfaces > 0 ) {
1219                                                         if( dodraw ) {
1220                                                                 if( numdata != 0 ) {
1221                                                                         GPU_buffer_unlock(buffer);
1222                                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1223                                                                 }
1224                                                                 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1225                                                                 if( numdata != 0 ) {
1226                                                                         varray = GPU_buffer_lock_stream(buffer);
1227                                                                 }
1228                                                         }
1229                                                 }
1230                                                 start = curface;
1231
1232                                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1233                                                         GPU_set_material_blend_mode(orig_transp);
1234                                                 else
1235                                                         GPU_set_material_blend_mode(new_transp);
1236                                                 transp = new_transp;
1237                                         }
1238                                 }
1239                                 
1240                                 if( numdata != 0 ) {
1241                                         offset = 0;
1242                                         if(attribs.totorco) {
1243                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1244                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1245                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1246                                                 offset += sizeof(float)*3;
1247                                         }
1248                                         for(b = 0; b < attribs.tottface; b++) {
1249                                                 MTFace *tf = &attribs.tface[b].array[a];
1250                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1251                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1252
1253                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1254                                                 offset += sizeof(float)*2;
1255                                         }
1256                                         for(b = 0; b < attribs.totmcol; b++) {
1257                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1258                                                 GLubyte col[4];
1259                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1260                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1261                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1262                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1263                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1264                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1265                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1266                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1267                                                 offset += sizeof(unsigned char)*4;
1268                                         }       
1269                                         if(attribs.tottang) {
1270                                                 float *tang = attribs.tang.array[a*4 + 0];
1271                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1272                                                 tang = attribs.tang.array[a*4 + 1];
1273                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1274                                                 tang = attribs.tang.array[a*4 + 2];
1275                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1276                                                 offset += sizeof(float)*4;
1277                                         }
1278                                 }
1279                                 curface++;
1280                                 if(mface->v4) {
1281                                         if( numdata != 0 ) {
1282                                                 offset = 0;
1283                                                 if(attribs.totorco) {
1284                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1285                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1286                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1287                                                         offset += sizeof(float)*3;
1288                                                 }
1289                                                 for(b = 0; b < attribs.tottface; b++) {
1290                                                         MTFace *tf = &attribs.tface[b].array[a];
1291                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1292                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1293                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1294                                                         offset += sizeof(float)*2;
1295                                                 }
1296                                                 for(b = 0; b < attribs.totmcol; b++) {
1297                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1298                                                         GLubyte col[4];
1299                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1300                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1301                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1302                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1303                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1304                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1305                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1306                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1307                                                         offset += sizeof(unsigned char)*4;
1308                                                 }       
1309                                                 if(attribs.tottang) {
1310                                                         float *tang = attribs.tang.array[a*4 + 2];
1311                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1312                                                         tang = attribs.tang.array[a*4 + 3];
1313                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1314                                                         tang = attribs.tang.array[a*4 + 0];
1315                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1316                                                         offset += sizeof(float)*4;
1317                                                 }
1318                                         }
1319                                         curface++;
1320                                         i++;
1321                                 }
1322                         }
1323                         numfaces = curface - start;
1324                         if( numfaces > 0 ) {
1325                                 if( dodraw ) {
1326                                         if( numdata != 0 ) {
1327                                                 GPU_buffer_unlock(buffer);
1328                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1329                                         }
1330                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1331                                 }
1332                         }
1333                         GPU_buffer_unbind();
1334                 }
1335                 GPU_buffer_free( buffer, NULL );
1336         }
1337
1338         glShadeModel(GL_FLAT);
1339 }
1340
1341 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1342 {
1343         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1344 }
1345
1346 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1347 {
1348         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1349         MVert *vert = cddm->mvert;
1350         MEdge *edge = cddm->medge;
1351         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1352
1353         glBegin(GL_LINES);
1354         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1355                 if(index) {
1356                         orig = *index++;
1357                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1358                 }
1359                 else
1360                         orig = i;
1361
1362                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1363                         glVertex3fv(vert[edge->v1].co);
1364                         glVertex3fv(vert[edge->v2].co);
1365                 }
1366         }
1367         glEnd();
1368 }
1369
1370 static void cdDM_foreachMappedVert(
1371                                                    DerivedMesh *dm,
1372                                                    void (*func)(void *userData, int index, float *co,
1373                                                                                 float *no_f, short *no_s),
1374                                                    void *userData)
1375 {
1376         MVert *mv = CDDM_get_verts(dm);
1377         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1378
1379         for(i = 0; i < dm->numVertData; i++, mv++) {
1380                 if(index) {
1381                         orig = *index++;
1382                         if(orig == ORIGINDEX_NONE) continue;
1383                         func(userData, orig, mv->co, NULL, mv->no);
1384                 }
1385                 else
1386                         func(userData, i, mv->co, NULL, mv->no);
1387         }
1388 }
1389
1390 static void cdDM_foreachMappedEdge(
1391                                                    DerivedMesh *dm,
1392                                                    void (*func)(void *userData, int index,
1393                                                                                 float *v0co, float *v1co),
1394                                                    void *userData)
1395 {
1396         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1397         MVert *mv = cddm->mvert;
1398         MEdge *med = cddm->medge;
1399         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1400
1401         for(i = 0; i < dm->numEdgeData; i++, med++) {
1402                 if (index) {
1403                         orig = *index++;
1404                         if(orig == ORIGINDEX_NONE) continue;
1405                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1406                 }
1407                 else
1408                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1409         }
1410 }
1411
1412 static void cdDM_foreachMappedFaceCenter(
1413                                                    DerivedMesh *dm,
1414                                                    void (*func)(void *userData, int index,
1415                                                                                 float *cent, float *no),
1416                                                    void *userData)
1417 {
1418         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1419         MVert *mv = cddm->mvert;
1420         MPoly *mf = cddm->mpoly;
1421         MLoop *ml = cddm->mloop;
1422         int i, j, orig, *index;
1423
1424         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1425         mf = cddm->mpoly;
1426         for(i = 0; i < dm->numPolyData; i++, mf++) {
1427                 float cent[3];
1428                 float no[3];
1429
1430                 if (index) {
1431                         orig = *index++;
1432                         if(orig == ORIGINDEX_NONE) continue;
1433                 } else
1434                         orig = i;
1435                 
1436                 ml = &cddm->mloop[mf->loopstart];
1437                 cent[0] = cent[1] = cent[2] = 0.0f;
1438                 for (j=0; j<mf->totloop; j++, ml++) {
1439                         add_v3_v3v3(cent, cent, mv[ml->v].co);
1440                 }
1441                 mul_v3_fl(cent, 1.0f / (float)j);
1442
1443                 ml = &cddm->mloop[mf->loopstart];
1444                 if (j > 3) {
1445                         normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1446                                        mv[(ml+2)->v].co, mv[(ml+3)->v].co);
1447                 } else {
1448                         normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1449                                        mv[(ml+2)->v].co);
1450                 }
1451
1452                 func(userData, orig, cent, no);
1453         }
1454
1455 }
1456
1457 static void cdDM_recalcTesselation(DerivedMesh *dm)
1458 {
1459         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1460
1461         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1462                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1463                 dm->numPolyData, 1, 0);
1464         
1465         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1466 }
1467
1468 /*ignores original poly origindex layer*/
1469 static void cdDM_recalcTesselation2(DerivedMesh *dm)
1470 {
1471         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1472
1473         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1474                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1475                 dm->numPolyData, 0, 0);
1476         
1477         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1478 }
1479
1480 void CDDM_recalc_tesselation(DerivedMesh *dm, int orig_use_polyorig)
1481 {
1482         if (orig_use_polyorig)
1483                 cdDM_recalcTesselation(dm);
1484         else
1485                 cdDM_recalcTesselation2(dm);
1486 }
1487
1488 static void cdDM_free_internal(CDDerivedMesh *cddm)
1489 {
1490         if(cddm->fmap) MEM_freeN(cddm->fmap);
1491         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1492 }
1493
1494 static void cdDM_release(DerivedMesh *dm)
1495 {
1496         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1497
1498         if (DM_release(dm)) {
1499                 cdDM_free_internal(cddm);
1500                 MEM_freeN(cddm);
1501         }
1502 }
1503
1504 int CDDM_Check(DerivedMesh *dm)
1505 {
1506         return dm && dm->getMinMax == cdDM_getMinMax;
1507 }
1508
1509 /**************** CDDM interface functions ****************/
1510 static CDDerivedMesh *cdDM_create(const char *desc)
1511 {
1512         CDDerivedMesh *cddm;
1513         DerivedMesh *dm;
1514
1515         cddm = MEM_callocN(sizeof(*cddm), desc);
1516         dm = &cddm->dm;
1517
1518         dm->getMinMax = cdDM_getMinMax;
1519
1520         dm->getNumVerts = cdDM_getNumVerts;
1521         dm->getNumEdges = cdDM_getNumEdges;
1522         dm->getNumTessFaces = cdDM_getNumTessFaces;
1523         dm->getNumFaces = cdDM_getNumFaces;
1524
1525         dm->newFaceIter = cdDM_newFaceIter;
1526
1527         dm->getVert = cdDM_getVert;
1528         dm->getEdge = cdDM_getEdge;
1529         dm->getTessFace = cdDM_getFace;
1530         dm->copyVertArray = cdDM_copyVertArray;
1531         dm->copyEdgeArray = cdDM_copyEdgeArray;
1532         dm->copyTessFaceArray = cdDM_copyFaceArray;
1533         dm->getVertData = DM_get_vert_data;
1534         dm->getEdgeData = DM_get_edge_data;
1535         dm->getTessFaceData = DM_get_face_data;
1536         dm->getVertDataArray = DM_get_vert_data_layer;
1537         dm->getEdgeDataArray = DM_get_edge_data_layer;
1538         dm->getTessFaceDataArray = DM_get_tessface_data_layer;
1539         
1540         //doesn't work yet for all cases
1541         //dm->recalcTesselation = cdDM_recalcTesselation;
1542
1543         dm->getVertCos = cdDM_getVertCos;
1544         dm->getVertCo = cdDM_getVertCo;
1545         dm->getVertNo = cdDM_getVertNo;
1546
1547         dm->getPBVH = cdDM_getPBVH;
1548         dm->getFaceMap = cdDM_getFaceMap;
1549
1550         dm->drawVerts = cdDM_drawVerts;
1551
1552         dm->drawUVEdges = cdDM_drawUVEdges;
1553         dm->drawEdges = cdDM_drawEdges;
1554         dm->drawLooseEdges = cdDM_drawLooseEdges;
1555         dm->drawMappedEdges = cdDM_drawMappedEdges;
1556
1557         dm->drawFacesSolid = cdDM_drawFacesSolid;
1558         dm->drawFacesColored = cdDM_drawFacesColored;
1559         dm->drawFacesTex = cdDM_drawFacesTex;
1560         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1561         dm->drawMappedFaces = cdDM_drawMappedFaces;
1562         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1563         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1564
1565         dm->foreachMappedVert = cdDM_foreachMappedVert;
1566         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1567         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1568
1569         dm->release = cdDM_release;
1570
1571         return cddm;
1572 }
1573
1574 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
1575 {
1576         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1577         DerivedMesh *dm = &cddm->dm;
1578
1579         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
1580
1581         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1582         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1583         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1584         CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
1585
1586         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1587         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1588         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1589         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
1590         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
1591
1592         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1593         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1594         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1595         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1596         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1597
1598         return dm;
1599 }
1600
1601 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1602 {
1603         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1604         DerivedMesh *dm = &cddm->dm;
1605         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1606         int alloctype;
1607
1608         /* this does a referenced copy, with an exception for fluidsim */
1609
1610         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
1611                     mesh->totloop, mesh->totpoly);
1612
1613         dm->deformedOnly = 1;
1614
1615         alloctype= CD_REFERENCE;
1616
1617         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1618                                          mesh->totvert);
1619         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1620                                          mesh->totedge);
1621         CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype,
1622                                          mesh->totface);
1623         CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
1624                          mesh->totloop);
1625         CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
1626                          mesh->totpoly);
1627
1628         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1629         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1630         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1631         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1632         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1633
1634         if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
1635                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
1636
1637         return dm;
1638 }
1639
1640 DerivedMesh *disabled__CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1641 {
1642         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1643                                    BLI_countlist(&em->edges),
1644                                    BLI_countlist(&em->faces), 0, 0);
1645         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1646         EditVert *eve;
1647         EditEdge *eed;
1648         EditFace *efa;
1649         MVert *mvert = cddm->mvert;
1650         MEdge *medge = cddm->medge;
1651         MFace *mface = cddm->mface;
1652         int i, *index;
1653
1654         dm->deformedOnly = 1;
1655
1656         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1657                                          CD_CALLOC, dm->numVertData);
1658         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1659                                          CD_CALLOC, dm->numEdgeData); */
1660         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1661                                          CD_CALLOC, dm->numFaceData);
1662         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1663                          CD_CALLOC, dm->numFaceData);
1664
1665         /* set eve->hash to vert index */
1666         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1667                 eve->tmp.l = i;
1668
1669         /* Need to be able to mark loose edges */
1670         for(eed = em->edges.first; eed; eed = eed->next) {
1671                 eed->f2 = 0;
1672         }
1673         for(efa = em->faces.first; efa; efa = efa->next) {
1674                 efa->e1->f2 = 1;
1675                 efa->e2->f2 = 1;
1676                 efa->e3->f2 = 1;
1677                 if(efa->e4) efa->e4->f2 = 1;
1678         }
1679
1680         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1681         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1682                 i++, eve = eve->next, index++) {
1683                 MVert *mv = &mvert[i];
1684
1685                 VECCOPY(mv->co, eve->co);
1686
1687                 mv->no[0] = eve->no[0] * 32767.0;
1688                 mv->no[1] = eve->no[1] * 32767.0;
1689                 mv->no[2] = eve->no[2] * 32767.0;
1690                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1691
1692                 mv->flag = 0;
1693
1694                 *index = i;
1695
1696                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1697         }
1698
1699         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1700         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1701                 i++, eed = eed->next, index++) {
1702                 MEdge *med = &medge[i];
1703
1704                 med->v1 = eed->v1->tmp.l;
1705                 med->v2 = eed->v2->tmp.l;
1706                 med->crease = (unsigned char) (eed->crease * 255.0f);
1707                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1708                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1709                 
1710                 if(eed->seam) med->flag |= ME_SEAM;
1711                 if(eed->sharp) med->flag |= ME_SHARP;
1712                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1713
1714                 *index = i;
1715
1716                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1717         }
1718
1719         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1720         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1721                 i++, efa = efa->next, index++) {
1722                 MFace *mf = &mface[i];
1723
1724                 mf->v1 = efa->v1->tmp.l;
1725                 mf->v2 = efa->v2->tmp.l;
1726                 mf->v3 = efa->v3->tmp.l;
1727                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1728                 mf->mat_nr = efa->mat_nr;
1729                 mf->flag = efa->flag;
1730
1731                 *index = i;
1732
1733                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1734                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1735         }
1736
1737         return dm;
1738 }
1739
1740 DerivedMesh *CDDM_from_curve(Object *ob)
1741 {
1742         return CDDM_from_curve_customDB(ob, &ob->disp);
1743 }
1744
1745 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1746 {
1747         DerivedMesh *dm;
1748         CDDerivedMesh *cddm;
1749         MVert *allvert;
1750         MEdge *alledge;
1751         MFace *allface;
1752         int totvert, totedge, totface;
1753
1754         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1755                 &totedge, &allface, &totface) != 0) {
1756                 /* Error initializing mdata. This often happens when curve is empty */
1757                 return CDDM_new(0, 0, 0, 0, 0);
1758         }
1759
1760         dm = CDDM_new(totvert, totedge, totface, totface*4, totface);
1761         dm->deformedOnly = 1;
1762
1763         cddm = (CDDerivedMesh*)dm;
1764
1765         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1766         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1767         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1768
1769         MEM_freeN(allvert);
1770         MEM_freeN(alledge);
1771         MEM_freeN(allface);
1772
1773         return dm;
1774 }
1775
1776 static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
1777                                           int cdindex, BMLoop *l3[3],
1778                                           int numCol, int numTex)
1779 {
1780         BMLoop *l;
1781         BMFace *f = l3[0]->f;
1782         MTFace *texface;
1783         MTexPoly *texpoly;
1784         MCol *mcol;
1785         MLoopCol *mloopcol;
1786         MLoopUV *mloopuv;
1787         int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
1788
1789         for(i=0; i < numTex; i++){
1790                 texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
1791                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
1792                 
1793                 texface->tpage = texpoly->tpage;
1794                 texface->flag = texpoly->flag;
1795                 texface->transp = texpoly->transp;
1796                 texface->mode = texpoly->mode;
1797                 texface->tile = texpoly->tile;
1798                 texface->unwrap = texpoly->unwrap;
1799         
1800                 for (j=0; j<3; j++) {
1801                         l = l3[j];
1802                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
1803                         texface->uv[j][0] = mloopuv->uv[0];
1804                         texface->uv[j][1] = mloopuv->uv[1];
1805                 }
1806         }
1807
1808         for(i=0; i < numCol; i++){
1809                 mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
1810                 
1811                 for (j=0; j<3; j++) {
1812                         l = l3[j];
1813                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
1814                         mcol[j].r = mloopcol->r;
1815                         mcol[j].g = mloopcol->g;
1816                         mcol[j].b = mloopcol->b;
1817                         mcol[j].a = mloopcol->a;
1818                 }
1819         }
1820
1821         if (hasWCol) {
1822                 mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
1823
1824                 for (j=0; j<3; j++) {
1825                         l = l3[j];
1826                         mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
1827                         mcol[j].r = mloopcol->r;
1828                         mcol[j].g = mloopcol->g;
1829                         mcol[j].b = mloopcol->b;
1830                         mcol[j].a = mloopcol->a;
1831                 }
1832         }
1833 }
1834
1835 DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *me)
1836 {
1837         DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, 
1838                                em->tottri, em->bm->totloop, em->bm->totface);
1839         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1840         BMesh *bm = em->bm;
1841         BMIter iter, liter;
1842         BMVert *eve;
1843         BMEdge *eed;
1844         BMFace *efa;
1845         MVert *mvert = cddm->mvert;
1846         MEdge *medge = cddm->medge;
1847         MFace *mface = cddm->mface;
1848         MLoop *mloop = cddm->mloop;
1849         MPoly *mpoly = cddm->mpoly;
1850         int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
1851         int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
1852         int i, j, *index, add_orig;
1853
1854         dm->deformedOnly = 1;
1855         
1856         /*don't add origindex layer if one already exists*/
1857         add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
1858
1859         CustomData_merge(&em->bm->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1860                          CD_CALLOC, dm->numVertData);
1861         CustomData_merge(&em->bm->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1862                          CD_CALLOC, dm->numEdgeData);
1863         CustomData_merge(&em->bm->ldata, &dm->loopData, CD_MASK_DERIVEDMESH,
1864                          CD_CALLOC, dm->numLoopData);
1865         CustomData_merge(&em->bm->pdata, &dm->polyData, CD_MASK_DERIVEDMESH,
1866                          CD_CALLOC, dm->numPolyData);
1867         
1868         /*add tesselation mface layers*/
1869         CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
1870
1871         /* set vert index */
1872         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1873         for (i=0; eve; eve=BMIter_Step(&iter), i++)
1874                 BMINDEX_SET(eve, i);
1875
1876         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1877
1878         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1879         for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
1880                 MVert *mv = &mvert[i];
1881
1882                 VECCOPY(mv->co, eve->co);
1883
1884                 BMINDEX_SET(eve, i);
1885
1886                 mv->no[0] = eve->no[0] * 32767.0;
1887                 mv->no[1] = eve->no[1] * 32767.0;
1888                 mv->no[2] = eve->no[2] * 32767.0;
1889
1890                 mv->flag = BMFlags_To_MEFlags(eve);
1891
1892                 if (add_orig) *index = i;
1893
1894                 CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
1895         }
1896
1897         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1898         eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1899         for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
1900                 MEdge *med = &medge[i];
1901
1902                 BMINDEX_SET(eed, i);
1903
1904                 med->v1 = BMINDEX_GET(eed->v1);
1905                 med->v2 = BMINDEX_GET(eed->v2);
1906                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1907                 
1908                 med->flag = BMFlags_To_MEFlags(eed);
1909
1910                 CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
1911                 if (add_orig) *index = i;
1912         }
1913
1914         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1915         for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
1916                 BMINDEX_SET(efa, i);
1917         }
1918
1919         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1920         for(i = 0; i < dm->numFaceData; i++, index++) {
1921                 MFace *mf = &mface[i];
1922                 BMLoop **l = em->looptris[i];
1923                 efa = l[0]->f;
1924
1925                 mf->v1 = BMINDEX_GET(l[0]->v);
1926                 mf->v2 = BMINDEX_GET(l[1]->v);
1927                 mf->v3 = BMINDEX_GET(l[2]->v);
1928                 mf->v4 = 0;
1929                 mf->mat_nr = efa->mat_nr;
1930                 mf->flag = BMFlags_To_MEFlags(efa);
1931                 
1932                 *index = add_orig ? BMINDEX_GET(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
1933
1934                 loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
1935                 test_index_face(mf, &dm->faceData, i, 3);
1936         }
1937         
1938         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1939         j = 0;
1940         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1941         for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
1942                 BMLoop *l;
1943                 MPoly *mp = &mpoly[i];
1944
1945                 mp->totloop = efa->len;
1946                 mp->flag = BMFlags_To_MEFlags(efa);
1947                 mp->loopstart = j;
1948                 mp->mat_nr = efa->mat_nr;
1949                 
1950                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
1951                         mloop->v = BMINDEX_GET(l->v);
1952                         mloop->e = BMINDEX_GET(l->e);
1953                         CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
1954
1955                         j++;
1956                         mloop++;
1957                 }
1958
1959                 CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
1960
1961                 if (add_orig) *index = i;
1962         }
1963
1964         return dm;
1965 }
1966
1967 typedef struct CDDM_LoopIter {
1968         DMLoopIter head;
1969         CDDerivedMesh *cddm;
1970         int len, i;
1971 } CDDM_LoopIter;
1972
1973 typedef struct CDDM_FaceIter {
1974         DMFaceIter head;
1975         CDDerivedMesh *cddm;
1976         CDDM_LoopIter liter;
1977 } CDDM_FaceIter;
1978
1979 void cddm_freeiter(void *self)
1980 {
1981         MEM_freeN(self);
1982 }
1983
1984 void cddm_stepiter(void *self)
1985 {
1986         CDDM_FaceIter *iter = self;
1987         MPoly *mp;
1988         
1989         mp = iter->cddm->mpoly + iter->head.index;
1990         mp->flag = iter->head.flags;
1991         mp->mat_nr = iter->head.mat_nr;
1992
1993         iter->head.index++;
1994         if (iter->head.index >= iter->cddm->dm.numPolyData) {
1995                 iter->head.done = 1;
1996                 return;
1997         }
1998
1999         mp = iter->cddm->mpoly + iter->head.index;
2000
2001         iter->head.flags = mp->flag;
2002         iter->head.mat_nr = mp->mat_nr;
2003         iter->head.len = mp->totloop;
2004 }
2005
2006 void *cddm_faceiter_getcddata(void *self, int type, int layer)
2007 {
2008         CDDM_FaceIter *iter = self;
2009
2010         if (layer == -1) return CustomData_get(&iter->cddm->dm.polyData, 
2011                                                iter->head.index, type);
2012         else return CustomData_get_n(&iter->cddm->dm.polyData, type, 
2013                                     iter->head.index, layer);
2014 }
2015
2016 void *cddm_loopiter_getcddata(void *self, int type, int layer)
2017 {
2018         CDDM_LoopIter *iter = self;
2019
2020         if (layer == -1) return CustomData_get(&iter->cddm->dm.loopData, 
2021                                                iter->head.index, type);
2022         else return CustomData_get_n(&iter->cddm->dm.loopData, type, 
2023                                      iter->head.index, layer);
2024 }
2025
2026 void *cddm_loopiter_getvertcddata(void *self, int type, int layer)
2027 {
2028         CDDM_LoopIter *iter = self;
2029
2030         if (layer == -1) return CustomData_get(&iter->cddm->dm.vertData, 
2031                                                iter->cddm->mloop[iter->head.index].v,
2032                                                type);
2033         else return CustomData_get_n(&iter->cddm->dm.vertData, type, 
2034                                      iter->cddm->mloop[iter->head.index].v, layer);
2035 }
2036
2037 DMLoopIter *cddmiter_get_loopiter(void *self)
2038 {
2039         CDDM_FaceIter *iter = self;
2040         CDDM_LoopIter *liter = &iter->liter;
2041         MPoly *mp = iter->cddm->mpoly + iter->head.index;
2042
2043         liter->i = -1;
2044         liter->len = iter->head.len;
2045         liter->head.index = mp->loopstart-1;
2046         liter->head.done = 0;
2047
2048         liter->head.step(liter);
2049
2050         return (DMLoopIter*) liter;
2051 }
2052
2053 void cddm_loopiter_step(void *self)
2054 {
2055         CDDM_LoopIter *liter = self;
2056         MLoop *ml;
2057
2058         liter->i++;
2059         liter->head.index++;
2060
2061         if (liter->i == liter->len) {
2062                 liter->head.done = 1;
2063                 return;
2064         }
2065
2066         ml = liter->cddm->mloop + liter->head.index;
2067
2068         liter->head.eindex = ml->e;
2069         liter->head.v = liter->cddm->mvert[ml->v];
2070         liter->head.vindex = ml->v;
2071 }
2072
2073 DMFaceIter *cdDM_newFaceIter(DerivedMesh *source)
2074 {
2075         CDDerivedMesh *cddm = (CDDerivedMesh*) source;
2076         CDDM_FaceIter *iter = MEM_callocN(sizeof(CDDM_FaceIter), "DMFaceIter from cddm");
2077
2078         iter->head.free = cddm_freeiter;
2079         iter->head.step = cddm_stepiter;
2080         iter->head.getCDData = cddm_faceiter_getcddata;
2081         iter->head.getLoopsIter = cddmiter_get_loopiter;
2082
2083         iter->liter.head.step = cddm_loopiter_step;
2084         iter->liter.head.getLoopCDData = cddm_loopiter_getcddata;
2085         iter->liter.head.getVertCDData = cddm_loopiter_getvertcddata;
2086         iter->liter.cddm = cddm;
2087
2088         iter->cddm = cddm;
2089
2090         if (source->numFaceData) {
2091                 iter->head.index = -1;
2092                 iter->head.step(iter);
2093         } else {
2094                 iter->head.done = 1;
2095         }
2096
2097         return (DMFaceIter*) iter;
2098 }
2099
2100 DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
2101 {
2102         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
2103         DerivedMesh *dm = &cddm->dm;
2104         int numVerts = source->numVertData;
2105         int numEdges = source->numEdgeData;
2106         int numFaces = source->numFaceData;
2107         int numLoops = source->numLoopData;
2108         int numPolys = source->numPolyData;
2109
2110         /* ensure these are created if they are made on demand */
2111         source->getVertDataArray(source, CD_ORIGINDEX);
2112         source->getEdgeDataArray(source, CD_ORIGINDEX);
2113         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2114
2115         /* this initializes dm, and copies all non mvert/medge/mface layers */
2116         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
2117                 numLoops, numPolys);
2118         dm->deformedOnly = source->deformedOnly;
2119
2120         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
2121         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
2122         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
2123
2124         /* now add mvert/medge/mface layers */
2125         cddm->mvert = source->dupVertArray(source);
2126         cddm->medge = source->dupEdgeArray(source);
2127         cddm->mface = source->dupTessFaceArray(source);
2128
2129         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
2130         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
2131         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
2132         
2133         if (!faces_from_tessfaces)
2134                 DM_DupPolys(source, dm);
2135         else
2136                 CDDM_tessfaces_to_faces(dm);
2137
2138         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2139         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2140
2141         return dm;
2142 }
2143
2144 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
2145  * relationship betwen mesh data this needs to be set by the caller. */
2146 DerivedMesh *CDDM_from_template(DerivedMesh *source,
2147                                 int numVerts, int numEdges, int numFaces,
2148                                                                 int numLoops, int numPolys)
2149 {
2150         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
2151         DerivedMesh *dm = &cddm->dm;
2152
2153         /* ensure these are created if they are made on demand */
2154         source->getVertDataArray(source, CD_ORIGINDEX);
2155         source->getEdgeDataArray(source, CD_ORIGINDEX);
2156         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2157
2158         /* this does a copy of all non mvert/medge/mface layers */
2159         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
2160
2161         /* now add mvert/medge/mface layers */
2162         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
2163         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2164         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
2165         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
2166         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
2167
2168         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
2169                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
2170         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
2171                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2172         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
2173                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
2174
2175         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
2176         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2177         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
2178         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2179         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2180
2181         return dm;
2182 }
2183
2184 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
2185 {
2186         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2187         MVert *vert;
2188         int i;
2189
2190         /* this will just return the pointer if it wasn't a referenced layer */
2191         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2192         cddm->mvert = vert;
2193
2194         for(i = 0; i < dm->numVertData; ++i, ++vert)
2195                 VECCOPY(vert->co, vertCoords[i]);
2196 }
2197
2198 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
2199 {
2200         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2201         MVert *vert;
2202         int i;
2203
2204         /* this will just return the pointer if it wasn't a referenced layer */
2205         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2206         cddm->mvert = vert;
2207
2208         for(i = 0; i < dm->numVertData; ++i, ++vert)
2209                 VECCOPY(vert->no, vertNormals[i]);
2210 }
2211
2212 void CDDM_calc_normals(DerivedMesh *dm)
2213 {
2214         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2215         float (*temp_nors)[3];
2216         float (*face_nors)[3];
2217         float (*vert_nors)[3];
2218         int i, j, *origIndex;
2219         int numVerts = dm->numVertData;
2220         int numFaces = dm->numFaceData;
2221         MFace *mf;
2222         MPoly *mp;
2223         MVert *mv;
2224         MLoop *ml;
2225
2226         if(numVerts == 0) return;
2227
2228         if (CustomData_has_layer(&dm->faceData, CD_NORMAL))
2229                 CustomData_free_layer(&dm->faceData, CD_NORMAL, dm->numFaceData, 0);
2230
2231         /*recalc tesselation to ensure we have valid origindex values
2232           for mface->mpoly lookups.*/
2233         cdDM_recalcTesselation2(dm);
2234
2235         numFaces = dm->numFaceData;
2236
2237         /*first go through and calculate normals for all the polys*/
2238         temp_nors = MEM_callocN(sizeof(float)*3*dm->numPolyData, "temp_nors cdderivedmesh.c");
2239         vert_nors = MEM_callocN(sizeof(float)*3*dm->numVertData, "vert_nors cdderivedmesh.c");
2240         
2241         mp = cddm->mpoly;
2242         for (i=0; i<dm->numPolyData; i++, mp++) {
2243                 mesh_calc_poly_normal(mp, cddm->mloop+mp->loopstart, cddm->mvert, temp_nors[i]);
2244
2245                 ml = cddm->mloop + mp->loopstart;
2246                 for (j=0; j<mp->totloop; j++, ml++) {
2247                         VECADD(vert_nors[ml->v], vert_nors[ml->v], temp_nors[i]);
2248                 }
2249         }
2250
2251         face_nors = MEM_callocN(sizeof(float)*3*dm->numFaceData, "face_nors cdderivedmesh.c");
2252         origIndex = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
2253
2254         mf = cddm->mface;
2255         for (i=0; i<dm->numFaceData; i++, mf++, origIndex++) {
2256                 VECCOPY(face_nors[i], temp_nors[*origIndex]);
2257         }
2258
2259         mv = cddm->mvert;
2260         for (i=0; i<dm->numVertData; i++, mv++) {
2261                 float *no = vert_nors[i];
2262                 
2263                 if (normalize_v3(no) == 0.0) {
2264                         VECCOPY(no, mv->co);
2265                         if (normalize_v3(no) == 0.0) {
2266                                 no[0] = 0.0f;
2267                                 no[1] = 0.0f;
2268                                 no[2] = 1.0f;
2269                         }
2270                 }
2271
2272                 normal_float_to_short_v3(mv->no, no);
2273         }
2274
2275         MEM_freeN(temp_nors);
2276         MEM_freeN(vert_nors);
2277
2278         /*this restores original poly origindex -> tessface origindex mapping,
2279           instead of the poly index -> tessface origindex one we generated
2280           with cdDM_recalcTesselation2*/
2281         cdDM_recalcTesselation(dm);
2282         CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, 
2283                 face_nors, dm->numFaceData);
2284 }
2285
2286 #if 1
2287 /*merge verts
2288  
2289   vtargetmap is a table that maps vertices to target vertices.  a value of -1
2290   indicates a vertex is a target, and is to be kept.
2291   
2292   this frees dm, and returns a new one.
2293   
2294   this is a really horribly written function.  ger. - joeedh
2295
2296  */
2297 DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap)
2298 {
2299         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2300         CDDerivedMesh *cddm2 = NULL;
2301         MVert *mv, *mvert = NULL;
2302         BLI_array_declare(mvert);
2303         MEdge *me, *medge = NULL;
2304         BLI_array_declare(medge);
2305         MPoly *mp, *mpoly = NULL;
2306         BLI_array_declare(mpoly);
2307         MLoop *ml, *mloop = NULL;
2308         BLI_array_declare(mloop);
2309         EdgeHash *ehash = BLI_edgehash_new();
2310         int *newv = NULL, *newe = NULL, *newl = NULL;
2311         int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
2312         BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
2313         int i, j, c, totloop, totpoly;
2314         
2315         totloop = dm->numLoopData;
2316         totpoly = dm->numPolyData;
2317         
2318         newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts");
2319         newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts");
2320         newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts");
2321         
2322         /*fill newl with destination vertex indices*/
2323         mv = cddm->mvert;
2324         c = 0;
2325         for (i=0; i<dm->numVertData; i++, mv++) {
2326                 if (vtargetmap[i] == -1) {
2327                         BLI_array_append(oldv, i);
2328                         newv[i] = c++;
2329                         BLI_array_append(mvert, *mv);
2330                 }
2331         }
2332         
2333         /*now link target vertices to destination indices*/
2334         for (i=0; i<dm->numVertData; i++) {
2335                 if (vtargetmap[i] != -1) {
2336                         newv[i] = newv[vtargetmap[i]];
2337                 }
2338         }
2339         
2340         /*find-replace merged vertices with target vertices*/   
2341         ml = cddm->mloop;
2342         c = 0;
2343         for (i=0; i<totloop; i++, ml++) {
2344                 if (ml->v == -1)
2345                         continue;
2346                 
2347                 if (vtargetmap[ml->v] != -1) {
2348                         me = &cddm->medge[ml->e];
2349                         if (me->v1 == ml->v)
2350                                 me->v1 = vtargetmap[ml->v];
2351                         else
2352                                 me->v2 = vtargetmap[ml->v];
2353                         
2354                         ml->v = vtargetmap[ml->v];
2355                 }
2356         }
2357         
2358         /*now go through and fix edges and faces*/
2359         me = cddm->medge;
2360         c = 0;
2361         for (i=0; i<dm->numEdgeData; i++, me++) {
2362                 int v1, v2;
2363                 
2364                 if (me->v1 == me->v2) {
2365                         newe[i] = -1;
2366                         continue;
2367                 }
2368                 
2369                 if (vtargetmap[me->v1] != -1)
2370                         v1 = vtargetmap[me->v1];
2371                 else
2372                         v1 = me->v1;
2373                 
2374                 if (vtargetmap[me->v2] != -1)
2375                         v2 = vtargetmap[me->v2];
2376                 else
2377                         v2 = me->v2;
2378                 
2379                 if (BLI_edgehash_haskey(ehash, v1, v2)) {
2380                         newe[i] = GET_INT_FROM_POINTER(BLI_edgehash_lookup(ehash, v1, v2));
2381                 } else {
2382                         BLI_array_append(olde, i);
2383                         newe[i] = c;
2384                         BLI_array_append(medge, *me);
2385                         BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c));
2386                         c++;
2387                 }
2388         }
2389         
2390         mp = cddm->mpoly;
2391         for (i=0; i<totpoly; i++, mp++) {
2392                 MPoly *mp2;
2393                 
2394                 ml = cddm->mloop + mp->loopstart;
2395                 
2396                 c = 0;
2397                 for (j=0; j<mp->totloop; j++, ml++) {
2398                         if (ml->v == -1)
2399                                 continue;
2400                         
2401                         me = cddm->medge + ml->e;
2402                         if (me->v1 != me->v2) {
2403                                 BLI_array_append(oldl, j+mp->loopstart);
2404                                 BLI_array_append(mloop, *ml);
2405                                 newl[j+mp->loopstart] = BLI_array_count(mloop)-1;
2406                                 c++;
2407                         }
2408                 }
2409                 
2410                 if (!c)
2411                         continue;
2412                 
2413                 mp2 = BLI_array_append(mpoly, *mp);
2414                 mp2->totloop = c;
2415                 mp2->loopstart = BLI_array_count(mloop) - c;
2416                 
2417                 BLI_array_append(oldp, i);
2418         }
2419         
2420         /*create new cddm*/     
2421         cddm2 = (CDDerivedMesh*) CDDM_from_template(cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
2422         
2423         /*update edge indices and copy customdata*/
2424         me = medge;
2425         for (i=0; i<cddm2->dm.numEdgeData; i++, me++) {
2426                 if (newv[me->v1] != -1)
2427                         me->v1 = newv[me->v1];
2428                 if (newv[me->v2] != -1)
2429                         me->v2 = newv[me->v2];
2430                 
2431                 CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1);
2432         }
2433         
2434         /*update loop indices and copy customdata*/
2435         ml = mloop;
2436         for (i=0; i<cddm2->dm.numLoopData; i++, ml++) {
2437                 if (newe[ml->e] != -1)
2438                         ml->e = newe[ml->e];
2439                 if (newv[ml->v] != -1)
2440                         ml->v = newv[ml->v];
2441                         
2442                 CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
2443         }
2444         
2445         /*copy vertex customdata*/      
2446         mv = mvert;
2447         for (i=0; i<cddm2->dm.numVertData; i++, mv++) {
2448                 CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1);
2449         }
2450         
2451         /*copy poly customdata*/
2452         mp = mpoly;
2453         for (i=0; i<cddm2->dm.numPolyData; i++, mp++) {
2454                 CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1);
2455         }
2456         
2457         /*copy over data.  CustomData_add_layer can do this, need to look it up.*/
2458         memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert));
2459         memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge));
2460         memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop));
2461         memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
2462         BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
2463
2464         CDDM_recalc_tesselation(cddm2, 1);
2465         
2466         if (newv) 
2467                 MEM_freeN(newv); 
2468         if (newe)
2469                 MEM_freeN(newe); 
2470         if (newl)
2471                 MEM_freeN(newl);
2472         if (oldv) 
2473                 MEM_freeN(oldv); 
2474         if (olde) 
2475                 MEM_freeN(olde); 
2476         if (oldl) 
2477                 MEM_freeN(oldl); 
2478         if (oldp) 
2479                 MEM_freeN(oldp);
2480         if (ehash)
2481                 BLI_edgehash_free(ehash, NULL);
2482
2483         /*free old derivedmesh*/
2484         dm->needsFree = 1;
2485         dm->release(dm);
2486         
2487         return (DerivedMesh*)cddm2;
2488 }
2489 #endif
2490
2491 void CDDM_calc_edges(DerivedMesh *dm)
2492 {
2493         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2494         CustomData edgeData;
2495         EdgeHashIterator *ehi;
2496         MFace *mf = cddm->mface;
2497         MEdge *med;
2498         EdgeHash *eh = BLI_edgehash_new();
2499         int i, *index, numEdges, maxFaces = dm->numFaceData;
2500
2501         for (i = 0; i < maxFaces; i++, mf++) {
2502                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
2503                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
2504                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
2505                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
2506                 
2507                 if (mf->v4) {
2508                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
2509                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
2510                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
2511                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
2512                 } else {
2513                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
2514                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
2515                 }
2516         }
2517
2518         numEdges = BLI_edgehash_size(eh);
2519
2520         /* write new edges into a temporary CustomData */
2521         memset(&edgeData, 0, sizeof(edgeData));
2522         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2523         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2524
2525         ehi = BLI_edgehashIterator_new(eh);
2526         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2527         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2528         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2529                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2530                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2531
2532                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2533                 *index = ORIGINDEX_NONE;
2534         }
2535         BLI_edgehashIterator_free(ehi);
2536
2537         /* free old CustomData and assign new one */
2538         CustomData_free(&dm->edgeData, dm->numEdgeData);
2539         dm->edgeData = edgeData;
2540         dm->numEdgeData = numEdges;
2541
2542         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2543
2544         BLI_edgehash_free(eh, NULL);
2545 }
2546
2547
2548 void CDDM_calc_edges_poly(DerivedMesh *dm)
2549 {
2550         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2551         CustomData edgeData;
2552         EdgeHashIterator *ehi;
2553         MPoly *mp = cddm->mpoly;
2554         MLoop *ml;
2555         MEdge *med;
2556         EdgeHash *eh = BLI_edgehash_new();
2557         int v1, v2;
2558         int *eindex;
2559         int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
2560
2561         eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
2562
2563         med = cddm->medge;
2564         if (med) {
2565                 for (i=0; i < numEdges; i++, med++) {
2566                         BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
2567                 }
2568         }
2569
2570         for (i=0; i < maxFaces; i++, mp++) {
2571                 ml = cddm->mloop + mp->loopstart;
2572                 for (j=0; j<mp->totloop; j++, ml++) {
2573                         v1 = ml->v;
2574                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2575                         if (!BLI_edgehash_haskey(eh, v1, v2)) {
2576                                 BLI_edgehash_insert(eh, v1, v2, NULL);
2577                         }
2578                 }
2579         }
2580
2581         k = numEdges;
2582         numEdges = BLI_edgehash_size(eh);
2583
2584         /* write new edges into a temporary CustomData */
2585         memset(&edgeData, 0, sizeof(edgeData));
2586         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2587         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2588
2589         ehi = BLI_edgehashIterator_new(eh);
2590         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2591         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2592         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2593             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2594                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2595                 j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
2596
2597                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2598                 *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
2599
2600                 BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
2601         }
2602         BLI_edgehashIterator_free(ehi);
2603
2604         /* free old CustomData and assign new one */
2605         CustomData_free(&dm->edgeData, dm->numEdgeData);
2606         dm->edgeData = edgeData;
2607         dm->numEdgeData = numEdges;
2608
2609         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2610
2611         mp = cddm->mpoly;
2612         for (i=0; i < maxFaces; i++, mp++) {
2613                 ml = cddm->mloop + mp->loopstart;
2614                 for (j=0; j<mp->totloop; j++, ml++) {
2615                         v1 = ml->v;
2616                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2617                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
2618                 }
2619         }
2620
2621         BLI_edgehash_free(eh, NULL);
2622 }
2623
2624 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
2625 {
2626         if (numVerts < dm->numVertData)
2627                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
2628
2629         dm->numVertData = numVerts;
2630 }
2631
2632 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
2633 {
2634         if (numEdges < dm->numEdgeData)
2635                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
2636
2637         dm->numEdgeData = numEdges;
2638 }
2639
2640 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
2641 {
2642         if (numFaces < dm->numFaceData)
2643                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
2644
2645         dm->numFaceData = numFaces;
2646 }
2647
2648 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
2649 {
2650         return &((CDDerivedMesh*)dm)->mvert[index];
2651 }
2652
2653 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
2654 {
2655         return &((CDDerivedMesh*)dm)->medge[index];
2656 }
2657
2658 MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
2659 {
2660         return &((CDDerivedMesh*)dm)->mface[index];
2661 }
2662
2663 MVert *CDDM_get_verts(DerivedMesh *dm)
2664 {
2665         return ((CDDerivedMesh*)dm)->mvert;
2666 }
2667
2668 MEdge *CDDM_get_edges(DerivedMesh *dm)
2669 {
2670         return ((CDDerivedMesh*)dm)->medge;
2671 }
2672
2673 MFace *CDDM_get_tessfaces(DerivedMesh *dm)
2674 {
2675         return ((CDDerivedMesh*)dm)->mface;
2676 }
2677
2678 MLoop *CDDM_get_loops(DerivedMesh *dm)
2679 {
2680         return ((CDDerivedMesh*)dm)->mloop;
2681 }
2682
2683 MPoly *CDDM_get_polys(DerivedMesh *dm)
2684 {
2685         return ((CDDerivedMesh*)dm)->mpoly;
2686 }
2687
2688 void CDDM_tessfaces_to_faces(DerivedMesh *dm)
2689 {
2690         /*converts mfaces to mpolys/mloops*/
2691         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2692         MFace *mf;
2693         MEdge *me;
2694         MLoop *ml;
2695         MPoly *mp;
2696         EdgeHash *eh = BLI_edgehash_new();
2697         int i, l, totloop, *index1, *index2;
2698         
2699         /*ensure we have all the edges we need*/
2700         CDDM_calc_edges(dm);
2701
2702         /*build edge hash*/
2703         me = cddm->medge;
2704         for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
2705                 BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
2706         }
2707
2708         mf = cddm->mface;
2709         totloop = 0;
2710         for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
2711                 totloop += mf->v4 ? 4 : 3;
2712         }
2713
2714         CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
2715         CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
2716         
2717         cddm->dm.numLoopData = totloop;
2718         cddm->dm.numPolyData = cddm->dm.numFaceData;
2719
2720         if (!totloop) return;
2721
2722         cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
2723         cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
2724         
2725         CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
2726         CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
2727         CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, 
2728                 CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData);
2729
2730         index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
2731         index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
2732
2733         mf = cddm->mface;
2734         mp = cddm->mpoly;
2735         ml = cddm->mloop;
2736         l = 0;
2737         for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
2738                 mp->flag = mf->flag;
2739                 mp->loopstart = l;
2740                 mp->mat_nr = mf->mat_nr;
2741                 mp->totloop = mf->v4 ? 4 : 3;
2742                 
2743                 ml->v = mf->v1;
2744                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
2745                 ml++, l++;
2746
2747                 ml->v = mf->v2;
2748                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
2749                 ml++, l++;
2750
2751                 ml->v = mf->v3;
2752                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
2753                 ml++, l++;
2754
2755                 if (mf->v4) {
2756                         ml->v = mf->v4;
2757                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
2758                         ml++, l++;
2759                 }
2760
2761         }
2762
2763         BLI_edgehash_free(eh, NULL);
2764 }
2765
2766 void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
2767 {
2768         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2769
2770         cddm->mvert = mvert;
2771 }
2772
2773 void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
2774 {
2775         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2776
2777         cddm->medge = medge;
2778 }
2779
2780 void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
2781 {
2782         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2783
2784         cddm->mface = mface;
2785 }