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