add function for getting a polygon map: dm->getPolyMap(ob, dm).
[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->totface, 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_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
288                                     me->totface, me->totvert);
289
290                 if(ss->modifiers_active && ob->derivedDeform) {
291                         DerivedMesh *deformdm= ob->derivedDeform;
292                         float (*vertCos)[3];
293                         int totvert;
294
295                         totvert= deformdm->getNumVerts(deformdm);
296                         vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
297                         deformdm->getVertCos(deformdm, vertCos);
298                         BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
299                         MEM_freeN(vertCos);
300                 }
301         }
302
303         return cddm->pbvh;
304 }
305
306 /* update vertex normals so that drawing smooth faces works during sculpt
307    TODO: proper fix is to support the pbvh in all drawing modes */
308 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
309 {
310         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
311         float (*face_nors)[3];
312
313         if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numTessFaceData)
314                 return;
315
316         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
317
318         BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
319 }
320
321 static void cdDM_drawVerts(DerivedMesh *dm)
322 {
323         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
324         MVert *mv = cddm->mvert;
325         int i;
326
327         if( GPU_buffer_legacy(dm) ) {
328                 glBegin(GL_POINTS);
329                 for(i = 0; i < dm->numVertData; i++, mv++)
330                         glVertex3fv(mv->co);
331                 glEnd();
332         }
333         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
334                 GPU_vertex_setup(dm);
335                 if( !GPU_buffer_legacy(dm) ) {
336                         if(dm->drawObject->tot_triangle_point)
337                                 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
338                         else
339                                 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
340                 }
341                 GPU_buffer_unbind();
342         }
343 }
344
345 static void cdDM_drawUVEdges(DerivedMesh *dm)
346 {
347         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
348         MFace *mf = cddm->mface;
349         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
350         int i;
351
352         if(mf) {
353                 if( GPU_buffer_legacy(dm) ) {
354                         glBegin(GL_LINES);
355                         for(i = 0; i < dm->numTessFaceData; i++, mf++, tf++) {
356                                 if(!(mf->flag&ME_HIDE)) {
357                                         glVertex2fv(tf->uv[0]);
358                                         glVertex2fv(tf->uv[1]);
359
360                                         glVertex2fv(tf->uv[1]);
361                                         glVertex2fv(tf->uv[2]);
362
363                                         if(!mf->v4) {
364                                                 glVertex2fv(tf->uv[2]);
365                                                 glVertex2fv(tf->uv[0]);
366                                         } else {
367                                                 glVertex2fv(tf->uv[2]);
368                                                 glVertex2fv(tf->uv[3]);
369
370                                                 glVertex2fv(tf->uv[3]);
371                                                 glVertex2fv(tf->uv[0]);
372                                         }
373                                 }
374                         }
375                         glEnd();
376                 }
377                 else {
378                         int prevstart = 0;
379                         int prevdraw = 1;
380                         int draw = 1;
381                         int curpos = 0;
382
383                         GPU_uvedge_setup(dm);
384                         if( !GPU_buffer_legacy(dm) ) {
385                                 for(i = 0; i < dm->numTessFaceData; i++, mf++) {
386                                         if(!(mf->flag&ME_HIDE)) {
387                                                 draw = 1;
388                                         } 
389                                         else {
390                                                 draw = 0;
391                                         }
392                                         if( prevdraw != draw ) {
393                                                 if( prevdraw > 0 && (curpos-prevstart) > 0) {
394                                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
395                                                 }
396                                                 prevstart = curpos;
397                                         }
398                                         if( mf->v4 ) {
399                                                 curpos += 8;
400                                         }
401                                         else {
402                                                 curpos += 6;
403                                         }
404                                         prevdraw = draw;
405                                 }
406                                 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
407                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
408                                 }
409                         }
410                         GPU_buffer_unbind();
411                 }
412         }
413 }
414
415 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges)
416 {
417         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
418         MVert *mvert = cddm->mvert;
419         MEdge *medge = cddm->medge;
420         int i;
421         
422         if( GPU_buffer_legacy(dm) ) {
423                 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
424                 glBegin(GL_LINES);
425                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
426                         if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
427                            && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
428                                 glVertex3fv(mvert[medge->v1].co);
429                                 glVertex3fv(mvert[medge->v2].co);
430                         }
431                 }
432                 glEnd();
433         }
434         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
435                 int prevstart = 0;
436                 int prevdraw = 1;
437                 int draw = 1;
438
439                 GPU_edge_setup(dm);
440                 if( !GPU_buffer_legacy(dm) ) {
441                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
442                                 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
443                                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
444                                         draw = 1;
445                                 } 
446                                 else {
447                                         draw = 0;
448                                 }
449                                 if( prevdraw != draw ) {
450                                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
451                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
452                                         }
453                                         prevstart = i;
454                                 }
455                                 prevdraw = draw;
456                         }
457                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
458                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
459                         }
460                 }
461                 GPU_buffer_unbind();
462         }
463 }
464
465 static void cdDM_drawLooseEdges(DerivedMesh *dm)
466 {
467         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
468         MVert *mvert = cddm->mvert;
469         MEdge *medge = cddm->medge;
470         int i;
471
472         if( GPU_buffer_legacy(dm) ) {
473                 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
474                 glBegin(GL_LINES);
475                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
476                         if(medge->flag&ME_LOOSEEDGE) {
477                                 glVertex3fv(mvert[medge->v1].co);
478                                 glVertex3fv(mvert[medge->v2].co);
479                         }
480                 }
481                 glEnd();
482         }
483         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
484                 int prevstart = 0;
485                 int prevdraw = 1;
486                 int draw = 1;
487
488                 GPU_edge_setup(dm);
489                 if( !GPU_buffer_legacy(dm) ) {
490                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
491                                 if(medge->flag&ME_LOOSEEDGE) {
492                                         draw = 1;
493                                 } 
494                                 else {
495                                         draw = 0;
496                                 }
497                                 if( prevdraw != draw ) {
498                                         if( prevdraw > 0 && (i-prevstart) > 0) {
499                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
500                                         }
501                                         prevstart = i;
502                                 }
503                                 prevdraw = draw;
504                         }
505                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
506                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
507                         }
508                 }
509                 GPU_buffer_unbind();
510         }
511 }
512
513 static void cdDM_drawFacesSolid(DerivedMesh *dm,
514                                 float (*partial_redraw_planes)[4],
515                                 int UNUSED(fast), int (*setMaterial)(int, void *attribs))
516 {
517         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
518         MVert *mvert = cddm->mvert;
519         MFace *mface = cddm->mface;
520         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
521         int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
522
523 #define PASSVERT(index) {                                               \
524         if(shademodel == GL_SMOOTH) {                           \
525                 short *no = mvert[index].no;                    \
526                 glNormal3sv(no);                                                \
527         }                                                                                       \
528         glVertex3fv(mvert[index].co);   \
529 }
530
531         if(cddm->pbvh && cddm->pbvh_draw) {
532                 if(dm->numTessFaceData) {
533                         float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
534
535                         /* should be per face */
536                         if(!setMaterial(mface->mat_nr+1, NULL))
537                                 return;
538
539                         glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
540                         BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH));
541                         glShadeModel(GL_FLAT);
542                 }
543
544                 return;
545         }
546
547         if( GPU_buffer_legacy(dm) ) {
548                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
549                 glBegin(glmode = GL_QUADS);
550                 for(a = 0; a < dm->numTessFaceData; a++, mface++) {
551                         int new_glmode, new_matnr, new_shademodel;
552
553                         new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
554                         new_matnr = mface->mat_nr + 1;
555                         new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
556                         
557                         if(new_glmode != glmode || new_matnr != matnr
558                            || new_shademodel != shademodel) {
559                                 glEnd();
560
561                                 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
562
563                                 glShadeModel(shademodel = new_shademodel);
564                                 glBegin(glmode = new_glmode);
565                         } 
566                         
567                         if(drawCurrentMat) {
568                                 if(shademodel == GL_FLAT) {
569                                         if (nors) {
570                                                 glNormal3fv(nors);
571                                         }
572                                         else {
573                                                 /* TODO make this better (cache facenormals as layer?) */
574                                                 float nor[3];
575                                                 if(mface->v4) {
576                                                         normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
577                                                 } else {
578                                                         normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
579                                                 }
580                                                 glNormal3fv(nor);
581                                         }
582                                 }
583
584                                 PASSVERT(mface->v1);
585                                 PASSVERT(mface->v2);
586                                 PASSVERT(mface->v3);
587                                 if(mface->v4) {
588                                         PASSVERT(mface->v4);
589                                 }
590                         }
591
592                         if(nors) nors += 3;
593                 }
594                 glEnd();
595         }
596         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
597                 GPU_vertex_setup( dm );
598                 GPU_normal_setup( dm );
599                 if( !GPU_buffer_legacy(dm) ) {
600                         glShadeModel(GL_SMOOTH);
601                         for( a = 0; a < dm->drawObject->totmaterial; a++ ) {
602                                 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
603                                         glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
604                                                      dm->drawObject->materials[a].totpoint);
605                         }
606                 }
607                 GPU_buffer_unbind( );
608         }
609
610 #undef PASSVERT
611         glShadeModel(GL_FLAT);
612 }
613
614 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
615 {
616         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
617         int a, glmode;
618         unsigned char *cp1, *cp2;
619         MVert *mvert = cddm->mvert;
620         MFace *mface = cddm->mface;
621
622         cp1 = col1;
623         if(col2) {
624                 cp2 = col2;
625         } else {
626                 cp2 = NULL;
627                 useTwoSided = 0;
628         }
629
630         /* there's a conflict here... twosided colors versus culling...? */
631         /* defined by history, only texture faces have culling option */
632         /* we need that as mesh option builtin, next to double sided lighting */
633         if(col2) {
634                 glEnable(GL_CULL_FACE);
635         }
636
637         cdDM_update_normals_from_pbvh(dm);
638
639         if( GPU_buffer_legacy(dm) ) {
640                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
641                 glShadeModel(GL_SMOOTH);
642                 glBegin(glmode = GL_QUADS);
643                 for(a = 0; a < dm->numTessFaceData; a++, mface++, cp1 += 16) {
644                         int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
645
646                         if(new_glmode != glmode) {
647                                 glEnd();
648                                 glBegin(glmode = new_glmode);
649                         }
650                                 
651                         glColor3ubv(cp1+0);
652                         glVertex3fv(mvert[mface->v1].co);
653                         glColor3ubv(cp1+4);
654                         glVertex3fv(mvert[mface->v2].co);
655                         glColor3ubv(cp1+8);
656                         glVertex3fv(mvert[mface->v3].co);
657                         if(mface->v4) {
658                                 glColor3ubv(cp1+12);
659                                 glVertex3fv(mvert[mface->v4].co);
660                         }
661                                 
662                         if(useTwoSided) {
663                                 glColor3ubv(cp2+8);
664                                 glVertex3fv(mvert[mface->v3].co );
665                                 glColor3ubv(cp2+4);
666                                 glVertex3fv(mvert[mface->v2].co );
667                                 glColor3ubv(cp2+0);
668                                 glVertex3fv(mvert[mface->v1].co );
669                                 if(mface->v4) {
670                                         glColor3ubv(cp2+12);
671                                         glVertex3fv(mvert[mface->v4].co );
672                                 }
673                         }
674                         if(col2) cp2 += 16;
675                 }
676                 glEnd();
677         }
678         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
679                 GPU_color4_upload(dm,cp1);
680                 GPU_vertex_setup(dm);
681                 GPU_color_setup(dm);
682                 if( !GPU_buffer_legacy(dm) ) {
683                         glShadeModel(GL_SMOOTH);
684                         glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
685
686                         if( useTwoSided ) {
687                                 GPU_color4_upload(dm,cp2);
688                                 GPU_color_setup(dm);
689                                 glCullFace(GL_FRONT);
690                                 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
691                                 glCullFace(GL_BACK);
692                         }
693                 }
694                 GPU_buffer_unbind();
695         }
696
697         glShadeModel(GL_FLAT);
698         glDisable(GL_CULL_FACE);
699 }
700
701 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
702                            int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
703                            int (*drawParamsMapped)(void *userData, int index),
704                            int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
705                            void *userData) 
706 {
707         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
708         MVert *mv = cddm->mvert;
709         MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
710         MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
711         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
712         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
713         int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
714         int startFace = 0 /*, lastFlag = 0xdeadbeef */ /* UNUSED */;
715         MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
716         if(!mcol)
717                 mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
718
719         cdDM_update_normals_from_pbvh(dm);
720
721         if( GPU_buffer_legacy(dm) ) {
722                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
723                 for(i = 0; i < dm->numTessFaceData; i++, mf++) {
724                         MVert *mvert;
725                         int flag;
726                         unsigned char *cp = NULL;
727
728                         if(drawParams) {
729                                 flag = drawParams(tf? &tf[i]: NULL, (mcol != NULL), mf->mat_nr);
730                         }
731                         else {
732                                 if(index) {
733                                         orig = *index++;
734                                         if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
735                                         if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
736                                         else    { if(nors) nors += 3; continue; }
737                                 }
738                                 else
739                                         if(drawParamsMapped) flag = drawParamsMapped(userData, i);
740                                         else    { if(nors) nors += 3; continue; }
741                         }
742                         
743                         if(flag != 0) {
744                                 if (flag==1 && mcol)
745                                         cp= (unsigned char*) &mcol[i*4];
746
747                                 if(!(mf->flag&ME_SMOOTH)) {
748                                         if (nors) {
749                                                 glNormal3fv(nors);
750                                         }
751                                         else {
752                                                 float nor[3];
753                                                 if(mf->v4) {
754                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
755                                                 } else {
756                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
757                                                 }
758                                                 glNormal3fv(nor);
759                                         }
760                                 }
761
762                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
763                                 if(tf) glTexCoord2fv(tf[i].uv[0]);
764                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
765                                 mvert = &mv[mf->v1];
766                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
767                                 glVertex3fv(mvert->co);
768                                         
769                                 if(tf) glTexCoord2fv(tf[i].uv[1]);
770                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
771                                 mvert = &mv[mf->v2];
772                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
773                                 glVertex3fv(mvert->co);
774
775                                 if(tf) glTexCoord2fv(tf[i].uv[2]);
776                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
777                                 mvert = &mv[mf->v3];
778                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
779                                 glVertex3fv(mvert->co);
780
781                                 if(mf->v4) {
782                                         if(tf) glTexCoord2fv(tf[i].uv[3]);
783                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
784                                         mvert = &mv[mf->v4];
785                                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
786                                         glVertex3fv(mvert->co);
787                                 }
788                                 glEnd();
789                         }
790                         
791                         if(nors) nors += 3;
792                 }
793         } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
794                 MCol *col = realcol;
795                 if(!col)
796                         col = mcol;
797
798                 GPU_vertex_setup( dm );
799                 GPU_normal_setup( dm );
800                 GPU_uv_setup( dm );
801                 if( col != NULL ) {
802                         /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL )  {
803                                 col = 0;
804                         } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
805                                 col = 0;
806                         }
807                         
808                         if( col != 0 ) {*/
809                                 unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
810                                 for( i=0; i < dm->getNumTessFaces(dm); i++ ) {
811                                         for( j=0; j < 4; j++ ) {
812                                                 /* bgr -> rgb is intentional (and stupid), but how its stored internally */
813                                                 colors[i*12+j*3] = col[i*4+j].b;
814                                                 colors[i*12+j*3+1] = col[i*4+j].g;
815                                                 colors[i*12+j*3+2] = col[i*4+j].r;
816                                         }
817                                 }
818                                 GPU_color3_upload(dm,colors);
819                                 MEM_freeN(colors);
820                                 if(realcol)
821                                         dm->drawObject->colType = CD_TEXTURE_MCOL;
822                                 else if(mcol)
823                                         dm->drawObject->colType = CD_MCOL;
824                         //}
825                         GPU_color_setup( dm );
826                 }
827
828                 if( !GPU_buffer_legacy(dm) ) {
829                         int tottri = dm->drawObject->tot_triangle_point/3;
830                         int next_actualFace= dm->drawObject->triangle_to_mface[0];
831
832                         glShadeModel( GL_SMOOTH );
833                         /* lastFlag = 0; */ /* UNUSED */
834                         for(i = 0; i < tottri; i++) {
835                                 int actualFace = next_actualFace;
836                                 int flag = 1;
837                                 int flush = 0;
838
839                                 if(i != tottri-1)
840                                         next_actualFace= dm->drawObject->triangle_to_mface[i+1];
841
842                                 if(drawParams) {
843                                         flag = drawParams(tf? &tf[actualFace]: NULL, (mcol != NULL), mf[actualFace].mat_nr);
844                                 }
845                                 else {
846                                         if(index) {
847                                                 orig = index[actualFace];
848                                                 if(orig == ORIGINDEX_NONE) continue;
849                                                 if(drawParamsMapped)
850                                                         flag = drawParamsMapped(userData, orig);
851                                         }
852                                         else
853                                                 if(drawParamsMapped)
854                                                         flag = drawParamsMapped(userData, actualFace);
855                                 }
856
857                                 /* flush buffer if current triangle isn't drawable or it's last triangle */
858                                 flush= !flag || i == tottri - 1;
859
860                                 if(!flush && compareDrawOptions) {
861                                         /* also compare draw options and flush buffer if they're different
862                                            need for face selection highlight in edit mode */
863                                         flush|= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
864                                 }
865
866                                 if(flush) {
867                                         int first= startFace*3;
868                                         int count= (i-startFace+(flag ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
869
870                                         if(count) {
871                                                 if (col)
872                                                         GPU_color_switch(1);
873                                                 else
874                                                         GPU_color_switch(0);
875
876                                                 glDrawArrays(GL_TRIANGLES, first, count);
877                                         }
878
879                                         startFace = i + 1;
880                                 }
881                         }
882                 }
883
884                 GPU_buffer_unbind();
885                 glShadeModel( GL_FLAT );
886         }
887 }
888
889 static void cdDM_drawFacesTex(DerivedMesh *dm,
890                            int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr),
891                            int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
892                            void *userData)
893 {
894         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
895 }
896
897 static void cdDM_drawMappedFaces(DerivedMesh *dm,
898                         int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
899                         int (*setMaterial)(int, void *attribs),
900                         int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
901                         void *userData, int useColors)
902 {
903         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
904         MVert *mv = cddm->mvert;
905         MFace *mf = cddm->mface;
906         MCol *mc;
907         float *nors= DM_get_tessface_data_layer(dm, CD_NORMAL);
908         int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
909
910         mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL);
911         if(!mc)
912                 mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL);
913         if(!mc)
914                 mc = DM_get_tessface_data_layer(dm, CD_MCOL);
915
916         cdDM_update_normals_from_pbvh(dm);
917
918         /* back-buffer always uses legacy since VBO's would need the
919          * color array temporarily overwritten for drawing, then reset. */
920         if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
921                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
922                 for(i = 0; i < dm->numTessFaceData; i++, mf++) {
923                         int drawSmooth = (mf->flag & ME_SMOOTH);
924                         int draw= 1;
925
926                         orig= (index==NULL) ? i : *index++;
927                         
928                         if(orig == ORIGINDEX_NONE)
929                                 draw= setMaterial(mf->mat_nr + 1, NULL);
930                         else if (setDrawOptions != NULL)
931                                 draw= setDrawOptions(userData, orig, &drawSmooth);
932
933                         if(draw) {
934                                 unsigned char *cp = NULL;
935
936                                 if(useColors && mc)
937                                         cp = (unsigned char *)&mc[i * 4];
938
939                                 /* no need to set shading mode to flat because
940                                 *  normals are already used to change shading */
941                                 glShadeModel(GL_SMOOTH);
942                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
943
944                                 if (!drawSmooth) {
945                                         if (nors) {
946                                                 glNormal3fv(nors);
947                                         }
948                                         else {
949                                                 float nor[3];
950                                                 if(mf->v4) {
951                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
952                                                 } else {
953                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
954                                                 }
955                                                 glNormal3fv(nor);
956                                         }
957
958                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
959                                         glVertex3fv(mv[mf->v1].co);
960                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
961                                         glVertex3fv(mv[mf->v2].co);
962                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
963                                         glVertex3fv(mv[mf->v3].co);
964                                         if(mf->v4) {
965                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
966                                                 glVertex3fv(mv[mf->v4].co);
967                                         }
968                                 } else {
969                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
970                                         glNormal3sv(mv[mf->v1].no);
971                                         glVertex3fv(mv[mf->v1].co);
972                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
973                                         glNormal3sv(mv[mf->v2].no);
974                                         glVertex3fv(mv[mf->v2].co);
975                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
976                                         glNormal3sv(mv[mf->v3].no);
977                                         glVertex3fv(mv[mf->v3].co);
978                                         if(mf->v4) {
979                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
980                                                 glNormal3sv(mv[mf->v4].no);
981                                                 glVertex3fv(mv[mf->v4].co);
982                                         }
983                                 }
984
985                                 glEnd();
986                         }
987                         
988                         if (nors) nors += 3;
989                 }
990         }
991         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
992                 int prevstart = 0;
993                 GPU_vertex_setup(dm);
994                 GPU_normal_setup(dm);
995                 if( useColors && mc )
996                         GPU_color_setup(dm);
997                 if( !GPU_buffer_legacy(dm) ) {
998                         int tottri = dm->drawObject->tot_triangle_point/3;
999                         glShadeModel(GL_SMOOTH);
1000                         
1001                         if(tottri == 0) {
1002                                 /* avoid buffer problems in following code */
1003                         }
1004                         if(setDrawOptions == NULL) {
1005                                 /* just draw the entire face array */
1006                                 glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
1007                         }
1008                         else {
1009                                 /* we need to check if the next material changes */
1010                                 int next_actualFace= dm->drawObject->triangle_to_mface[0];
1011                                 
1012                                 for( i = 0; i < tottri; i++ ) {
1013                                         //int actualFace = dm->drawObject->triangle_to_mface[i];
1014                                         int actualFace = next_actualFace;
1015                                         MFace *mface= mf + actualFace;
1016                                         int drawSmooth= (mface->flag & ME_SMOOTH);
1017                                         int draw = 1;
1018                                         int flush = 0;
1019
1020                                         if(i != tottri-1)
1021                                                 next_actualFace= dm->drawObject->triangle_to_mface[i+1];
1022
1023                                         orig= (index==NULL) ? actualFace : index[actualFace];
1024
1025                                         if(orig == ORIGINDEX_NONE)
1026                                                 draw= setMaterial(mface->mat_nr + 1, NULL);
1027                                         else if (setDrawOptions != NULL)
1028                                                 draw= setDrawOptions(userData, orig, &drawSmooth);
1029         
1030                                         /* Goal is to draw as long of a contiguous triangle
1031                                            array as possible, so draw when we hit either an
1032                                            invisible triangle or at the end of the array */
1033
1034                                         /* flush buffer if current triangle isn't drawable or it's last triangle... */
1035                                         flush= !draw || i == tottri - 1;
1036
1037                                         /* ... or when material setting is dissferent  */
1038                                         flush|= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
1039
1040                                         if(!flush && compareDrawOptions) {
1041                                                 flush|= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
1042                                         }
1043
1044                                         if(flush) {
1045                                                 int first= prevstart*3;
1046                                                 int count= (i-prevstart+(draw ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
1047
1048                                                 if(count)
1049                                                         glDrawArrays(GL_TRIANGLES, first, count);
1050
1051                                                 prevstart = i + 1;
1052                                         }
1053                                 }
1054                         }
1055
1056                         glShadeModel(GL_FLAT);
1057                 }
1058                 GPU_buffer_unbind();
1059         }
1060 }
1061
1062 static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
1063                            int (*setDrawOptions)(void *userData, int index),
1064                            int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1065                            void *userData)
1066 {
1067         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
1068 }
1069
1070 static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, int smoothnormal)
1071 {
1072         int b;
1073
1074         /* orco texture coordinates */
1075         if(attribs->totorco) {
1076                 if(attribs->orco.glTexco)
1077                         glTexCoord3fv(attribs->orco.array[index]);
1078                 else
1079                         glVertexAttrib3fvARB(attribs->orco.glIndex, attribs->orco.array[index]);
1080         }
1081
1082         /* uv texture coordinates */
1083         for(b = 0; b < attribs->tottface; b++) {
1084                 MTFace *tf = &attribs->tface[b].array[a];
1085
1086                 if(attribs->tface[b].glTexco)
1087                         glTexCoord2fv(tf->uv[vert]);
1088                 else
1089                         glVertexAttrib2fvARB(attribs->tface[b].glIndex, tf->uv[vert]);
1090         }
1091
1092         /* vertex colors */
1093         for(b = 0; b < attribs->totmcol; b++) {
1094                 MCol *cp = &attribs->mcol[b].array[a*4 + vert];
1095                 GLubyte col[4];
1096                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1097                 glVertexAttrib4ubvARB(attribs->mcol[b].glIndex, col);
1098         }
1099
1100         /* tangent for normal mapping */
1101         if(attribs->tottang) {
1102                 float *tang = attribs->tang.array[a*4 + vert];
1103                 glVertexAttrib4fvARB(attribs->tang.glIndex, tang);
1104         }
1105
1106         /* vertex normal */
1107         if(smoothnormal)
1108                 glNormal3sv(mvert[index].no);
1109         
1110         /* vertex coordinate */
1111         glVertex3fv(mvert[index].co);
1112 }
1113
1114 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
1115                            int (*setMaterial)(int, void *attribs),
1116                            int (*setDrawOptions)(void *userData, int index),
1117                            void *userData)
1118 {
1119         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1120         GPUVertexAttribs gattribs;
1121         DMVertexAttribs attribs;
1122         MVert *mvert = cddm->mvert;
1123         MFace *mface = cddm->mface;
1124         /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
1125         float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
1126         int a, b, dodraw, matnr, new_matnr;
1127         int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1128
1129         cdDM_update_normals_from_pbvh(dm);
1130
1131         matnr = -1;
1132         dodraw = 0;
1133
1134         glShadeModel(GL_SMOOTH);
1135
1136         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1137                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1138                 memset(&attribs, 0, sizeof(attribs));
1139
1140                 glBegin(GL_QUADS);
1141
1142                 for(a = 0; a < dm->numTessFaceData; a++, mface++) {
1143                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1144                         new_matnr = mface->mat_nr + 1;
1145
1146                         if(new_matnr != matnr) {
1147                                 glEnd();
1148
1149                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1150                                 if(dodraw)
1151                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1152
1153                                 glBegin(GL_QUADS);
1154                         }
1155
1156                         if(!dodraw) {
1157                                 continue;
1158                         }
1159                         else if(setDrawOptions) {
1160                                 orig = (index)? index[a]: a;
1161
1162                                 if(orig == ORIGINDEX_NONE) {
1163                                         /* since the material is set by setMaterial(), faces with no
1164                                          * origin can be assumed to be generated by a modifier */ 
1165                                         
1166                                         /* continue */
1167                                 }
1168                                 else if(!setDrawOptions(userData, orig))
1169                                         continue;
1170                         }
1171
1172                         if(!smoothnormal) {
1173                                 if(nors) {
1174                                         glNormal3fv(nors[a]);
1175                                 }
1176                                 else {
1177                                         /* TODO ideally a normal layer should always be available */
1178                                         float nor[3];
1179                                         if(mface->v4) {
1180                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1181                                         } else {
1182                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1183                                         }
1184                                         glNormal3fv(nor);
1185                                 }
1186                         }
1187
1188                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal);
1189                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal);
1190                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1191
1192                         if(mface->v4)
1193                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal);
1194                         else
1195                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1196                 }
1197                 glEnd();
1198         }
1199         else {
1200                 GPUBuffer *buffer = NULL;
1201                 char *varray = NULL;
1202                 int numdata = 0, elementsize = 0, offset;
1203                 int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0;
1204                 int i;
1205
1206                 MFace *mf = mface;
1207                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1208                 memset(&attribs, 0, sizeof(attribs));
1209
1210                 GPU_vertex_setup(dm);
1211                 GPU_normal_setup(dm);
1212
1213                 if( !GPU_buffer_legacy(dm) ) {
1214                         for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
1215
1216                                 a = dm->drawObject->triangle_to_mface[i];
1217
1218                                 mface = mf + a;
1219                                 new_matnr = mface->mat_nr + 1;
1220
1221                                 if(new_matnr != matnr ) {
1222                                         numfaces = curface - start;
1223                                         if( numfaces > 0 ) {
1224
1225                                                 if( dodraw ) {
1226
1227                                                         if( numdata != 0 ) {
1228
1229                                                                 GPU_buffer_unlock(buffer);
1230
1231                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1232                                                         }
1233
1234                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1235
1236                                                         if( numdata != 0 ) {
1237
1238                                                                 GPU_buffer_free(buffer);
1239
1240                                                                 buffer = NULL;
1241                                                         }
1242
1243                                                 }
1244                                         }
1245                                         numdata = 0;
1246                                         start = curface;
1247                                         /* prevdraw = dodraw; */ /* UNUSED */
1248                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1249                                         if(dodraw) {
1250                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1251
1252                                                 if(attribs.totorco) {
1253                                                         datatypes[numdata].index = attribs.orco.glIndex;
1254                                                         datatypes[numdata].size = 3;
1255                                                         datatypes[numdata].type = GL_FLOAT;
1256                                                         numdata++;
1257                                                 }
1258                                                 for(b = 0; b < attribs.tottface; b++) {
1259                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1260                                                         datatypes[numdata].size = 2;
1261                                                         datatypes[numdata].type = GL_FLOAT;
1262                                                         numdata++;
1263                                                 }       
1264                                                 for(b = 0; b < attribs.totmcol; b++) {
1265                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1266                                                         datatypes[numdata].size = 4;
1267                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1268                                                         numdata++;
1269                                                 }       
1270                                                 if(attribs.tottang) {
1271                                                         datatypes[numdata].index = attribs.tang.glIndex;
1272                                                         datatypes[numdata].size = 4;
1273                                                         datatypes[numdata].type = GL_FLOAT;
1274                                                         numdata++;
1275                                                 }
1276                                                 if( numdata != 0 ) {
1277                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1278                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
1279                                                         if( buffer == NULL ) {
1280                                                                 GPU_buffer_unbind();
1281                                                                 dm->drawObject->legacy = 1;
1282                                                                 return;
1283                                                         }
1284                                                         varray = GPU_buffer_lock_stream(buffer);
1285                                                         if( varray == NULL ) {
1286                                                                 GPU_buffer_unbind();
1287                                                                 GPU_buffer_free(buffer);
1288                                                                 dm->drawObject->legacy = 1;
1289                                                                 return;
1290                                                         }
1291                                                 }
1292                                                 else {
1293                                                         /* if the buffer was set, dont use it again.
1294                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1295                                                         /* prevdraw= 0; */ /* UNUSED */
1296                                                         buffer= NULL;
1297                                                 }
1298                                         }
1299                                 }
1300
1301                                 if(dodraw && numdata != 0 ) {
1302                                         offset = 0;
1303                                         if(attribs.totorco) {
1304                                                 copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1305                                                 copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1306                                                 copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1307                                                 offset += sizeof(float)*3;
1308                                         }
1309                                         for(b = 0; b < attribs.tottface; b++) {
1310                                                 MTFace *tf = &attribs.tface[b].array[a];
1311                                                 copy_v2_v2((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1312                                                 copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1313
1314                                                 copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1315                                                 offset += sizeof(float)*2;
1316                                         }
1317                                         for(b = 0; b < attribs.totmcol; b++) {
1318                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1319                                                 GLubyte col[4];
1320                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1321                                                 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset], (char *)col);
1322                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1323                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1324                                                 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize], (char *)col);
1325                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1326                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1327                                                 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize*2], (char *)col);
1328                                                 offset += sizeof(unsigned char)*4;
1329                                         }       
1330                                         if(attribs.tottang) {
1331                                                 float *tang = attribs.tang.array[a*4 + 0];
1332                                                 copy_v4_v4((float *)&varray[elementsize*curface*3+offset], tang);
1333                                                 tang = attribs.tang.array[a*4 + 1];
1334                                                 copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1335                                                 tang = attribs.tang.array[a*4 + 2];
1336                                                 copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1337                                                 offset += sizeof(float)*4;
1338                                         }
1339                                         (void)offset;
1340                                 }
1341                                 curface++;
1342                                 if(mface->v4) {
1343                                         if(dodraw && numdata != 0 ) {
1344                                                 offset = 0;
1345                                                 if(attribs.totorco) {
1346                                                         copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1347                                                         copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1348                                                         copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1349                                                         offset += sizeof(float)*3;
1350                                                 }
1351                                                 for(b = 0; b < attribs.tottface; b++) {
1352                                                         MTFace *tf = &attribs.tface[b].array[a];
1353                                                         copy_v2_v2((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1354                                                         copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1355                                                         copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1356                                                         offset += sizeof(float)*2;
1357                                                 }
1358                                                 for(b = 0; b < attribs.totmcol; b++) {
1359                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1360                                                         GLubyte col[4];
1361                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1362                                                         copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset], (char *)col);
1363                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1364                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1365                                                         copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize], (char *)col);
1366                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1367                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1368                                                         copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize*2], (char *)col);
1369                                                         offset += sizeof(unsigned char)*4;
1370                                                 }       
1371                                                 if(attribs.tottang) {
1372                                                         float *tang = attribs.tang.array[a*4 + 2];
1373                                                         copy_v4_v4((float *)&varray[elementsize*curface*3+offset], tang);
1374                                                         tang = attribs.tang.array[a*4 + 3];
1375                                                         copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1376                                                         tang = attribs.tang.array[a*4 + 0];
1377                                                         copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1378                                                         offset += sizeof(float)*4;
1379                                                 }
1380                                                 (void)offset;
1381                                         }
1382                                         curface++;
1383                                         i++;
1384                                 }
1385                         }
1386                         numfaces = curface - start;
1387                         if( numfaces > 0 ) {
1388                                 if( dodraw ) {
1389                                         if( numdata != 0 ) {
1390                                                 GPU_buffer_unlock(buffer);
1391                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1392                                         }
1393                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1394                                 }
1395                         }
1396                         GPU_buffer_unbind();
1397                 }
1398                 GPU_buffer_free(buffer);
1399         }
1400
1401         glShadeModel(GL_FLAT);
1402 }
1403
1404 static void cdDM_drawFacesGLSL(DerivedMesh *dm,int (*setMaterial)(int, void *attribs))
1405 {
1406         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1407 }
1408
1409 static void cdDM_drawMappedFacesMat(DerivedMesh *dm,
1410         void (*setMaterial)(void *userData, int, void *attribs),
1411         int (*setFace)(void *userData, int index), void *userData)
1412 {
1413         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1414         GPUVertexAttribs gattribs;
1415         DMVertexAttribs attribs;
1416         MVert *mvert = cddm->mvert;
1417         MFace *mf = cddm->mface;
1418         float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
1419         int a, matnr, new_matnr;
1420         int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1421
1422         cdDM_update_normals_from_pbvh(dm);
1423
1424         matnr = -1;
1425
1426         glShadeModel(GL_SMOOTH);
1427
1428         memset(&attribs, 0, sizeof(attribs));
1429
1430         glBegin(GL_QUADS);
1431
1432         for(a = 0; a < dm->numTessFaceData; a++, mf++) {
1433                 const int smoothnormal = (mf->flag & ME_SMOOTH);
1434
1435                 /* material */
1436                 new_matnr = mf->mat_nr + 1;
1437
1438                 if(new_matnr != matnr) {
1439                         glEnd();
1440
1441                         setMaterial(userData, matnr = new_matnr, &gattribs);
1442                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1443
1444                         glBegin(GL_QUADS);
1445                 }
1446
1447                 /* skipping faces */
1448                 if(setFace) {
1449                         orig = (index)? index[a]: a;
1450
1451                         if(orig != ORIGINDEX_NONE && !setFace(userData, orig))
1452                                 continue;
1453                 }
1454
1455                 /* smooth normal */
1456                 if(!smoothnormal) {
1457                         if(nors) {
1458                                 glNormal3fv(nors[a]);
1459                         }
1460                         else {
1461                                 /* TODO ideally a normal layer should always be available */
1462                                 float nor[3];
1463
1464                                 if(mf->v4)
1465                                         normal_quad_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
1466                                 else
1467                                         normal_tri_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
1468
1469                                 glNormal3fv(nor);
1470                         }
1471                 }
1472
1473                 /* vertices */
1474                 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v1, 0, smoothnormal);
1475                 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v2, 1, smoothnormal);
1476                 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal);
1477
1478                 if(mf->v4)
1479                         cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v4, 3, smoothnormal);
1480                 else
1481                         cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal);
1482         }
1483         glEnd();
1484
1485         glShadeModel(GL_FLAT);
1486 }
1487
1488 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1489 {
1490         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1491         MVert *vert = cddm->mvert;
1492         MEdge *edge = cddm->medge;
1493         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1494
1495         glBegin(GL_LINES);
1496         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1497                 if(index) {
1498                         orig = *index++;
1499                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1500                 }
1501                 else
1502                         orig = i;
1503
1504                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1505                         glVertex3fv(vert[edge->v1].co);
1506                         glVertex3fv(vert[edge->v2].co);
1507                 }
1508         }
1509         glEnd();
1510 }
1511
1512 static void cdDM_foreachMappedVert(
1513                                                    DerivedMesh *dm,
1514                                                    void (*func)(void *userData, int index, float *co,
1515                                                                                 float *no_f, short *no_s),
1516                                                    void *userData)
1517 {
1518         MVert *mv = CDDM_get_verts(dm);
1519         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1520
1521         for(i = 0; i < dm->numVertData; i++, mv++) {
1522                 if(index) {
1523                         orig = *index++;
1524                         if(orig == ORIGINDEX_NONE) continue;
1525                         func(userData, orig, mv->co, NULL, mv->no);
1526                 }
1527                 else
1528                         func(userData, i, mv->co, NULL, mv->no);
1529         }
1530 }
1531
1532 static void cdDM_foreachMappedEdge(
1533                                                    DerivedMesh *dm,
1534                                                    void (*func)(void *userData, int index,
1535                                                                                 float *v0co, float *v1co),
1536                                                    void *userData)
1537 {
1538         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1539         MVert *mv = cddm->mvert;
1540         MEdge *med = cddm->medge;
1541         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1542
1543         for(i = 0; i < dm->numEdgeData; i++, med++) {
1544                 if (index) {
1545                         orig = *index++;
1546                         if(orig == ORIGINDEX_NONE) continue;
1547                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1548                 }
1549                 else
1550                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1551         }
1552 }
1553
1554 static void cdDM_foreachMappedFaceCenter(
1555                                                    DerivedMesh *dm,
1556                                                    void (*func)(void *userData, int index,
1557                                                                                 float *cent, float *no),
1558                                                    void *userData)
1559 {
1560         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1561         MVert *mv = cddm->mvert;
1562         MPoly *mf = cddm->mpoly;
1563         MLoop *ml = cddm->mloop;
1564         int i, j, orig, *index;
1565
1566         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1567         mf = cddm->mpoly;
1568         for(i = 0; i < dm->numPolyData; i++, mf++) {
1569                 float cent[3];
1570                 float no[3];
1571
1572                 if (index) {
1573                         orig = *index++;
1574                         if(orig == ORIGINDEX_NONE) continue;
1575                 }
1576                 else
1577                         orig = i;
1578                 
1579                 ml = &cddm->mloop[mf->loopstart];
1580                 cent[0] = cent[1] = cent[2] = 0.0f;
1581                 for (j=0; j<mf->totloop; j++, ml++) {
1582                         add_v3_v3v3(cent, cent, mv[ml->v].co);
1583                 }
1584                 mul_v3_fl(cent, 1.0f / (float)j);
1585
1586                 ml = &cddm->mloop[mf->loopstart];
1587                 if (j > 3) {
1588                         normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1589                                        mv[(ml+2)->v].co, mv[(ml+3)->v].co);
1590                 } else {
1591                         normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co, mv[(ml+2)->v].co);
1592                 }
1593
1594                 func(userData, orig, cent, no);
1595         }
1596
1597 }
1598
1599 void CDDM_recalc_tesselation_ex(DerivedMesh *dm, const int do_face_nor_cpy)
1600 {
1601         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1602
1603         dm->numTessFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, &dm->polyData,
1604                                                      cddm->mvert,
1605                                                      dm->numTessFaceData, dm->numLoopData, dm->numPolyData,
1606                                                      do_face_nor_cpy);
1607
1608         if (!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) {
1609                 int *polyIndex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX);
1610                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyIndex, dm->numTessFaceData);
1611         }
1612
1613         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1614
1615         /* Tesselation recreated faceData, and the active layer indices need to get re-propagated
1616            from loops and polys to faces */
1617         CustomData_bmesh_update_active_layers(&dm->faceData, &dm->polyData, &dm->loopData);
1618 }
1619
1620 void CDDM_recalc_tesselation(DerivedMesh *dm)
1621 {
1622         CDDM_recalc_tesselation_ex(dm, TRUE);
1623 }
1624
1625 static void cdDM_free_internal(CDDerivedMesh *cddm)
1626 {
1627         if(cddm->fmap) MEM_freeN(cddm->fmap);
1628         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1629
1630         if(cddm->pmap) MEM_freeN(cddm->pmap);
1631         if(cddm->pmap_mem) MEM_freeN(cddm->pmap_mem);
1632 }
1633
1634 static void cdDM_release(DerivedMesh *dm)
1635 {
1636         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1637
1638         if (DM_release(dm)) {
1639                 cdDM_free_internal(cddm);
1640                 MEM_freeN(cddm);
1641         }
1642 }
1643
1644 int CDDM_Check(DerivedMesh *dm)
1645 {
1646         return dm && dm->getMinMax == cdDM_getMinMax;
1647 }
1648
1649 /**************** CDDM interface functions ****************/
1650 static CDDerivedMesh *cdDM_create(const char *desc)
1651 {
1652         CDDerivedMesh *cddm;
1653         DerivedMesh *dm;
1654
1655         cddm = MEM_callocN(sizeof(*cddm), desc);
1656         dm = &cddm->dm;
1657
1658         dm->getMinMax = cdDM_getMinMax;
1659
1660         dm->getNumVerts = cdDM_getNumVerts;
1661         dm->getNumEdges = cdDM_getNumEdges;
1662         dm->getNumTessFaces = cdDM_getNumTessFaces;
1663         dm->getNumLoops = cdDM_getNumLoops;
1664         dm->getNumPolys = cdDM_getNumPolys;
1665
1666         dm->getVert = cdDM_getVert;
1667         dm->getEdge = cdDM_getEdge;
1668         dm->getTessFace = cdDM_getTessFace;
1669
1670         dm->copyVertArray = cdDM_copyVertArray;
1671         dm->copyEdgeArray = cdDM_copyEdgeArray;
1672         dm->copyTessFaceArray = cdDM_copyTessFaceArray;
1673         dm->copyLoopArray = cdDM_copyLoopArray;
1674         dm->copyPolyArray = cdDM_copyPolyArray;
1675
1676         dm->getVertData = DM_get_vert_data;
1677         dm->getEdgeData = DM_get_edge_data;
1678         dm->getTessFaceData = DM_get_tessface_data;
1679         dm->getVertDataArray = DM_get_vert_data_layer;
1680         dm->getEdgeDataArray = DM_get_edge_data_layer;
1681         dm->getTessFaceDataArray = DM_get_tessface_data_layer;
1682
1683         dm->calcNormals = CDDM_calc_normals;
1684         dm->recalcTesselation = CDDM_recalc_tesselation;
1685
1686         dm->getVertCos = cdDM_getVertCos;
1687         dm->getVertCo = cdDM_getVertCo;
1688         dm->getVertNo = cdDM_getVertNo;
1689
1690         dm->getPBVH = cdDM_getPBVH;
1691         dm->getPolyMap = cdDM_getPolyMap;
1692         dm->getFaceMap = cdDM_getFaceMap;
1693
1694         dm->drawVerts = cdDM_drawVerts;
1695
1696         dm->drawUVEdges = cdDM_drawUVEdges;
1697         dm->drawEdges = cdDM_drawEdges;
1698         dm->drawLooseEdges = cdDM_drawLooseEdges;
1699         dm->drawMappedEdges = cdDM_drawMappedEdges;
1700
1701         dm->drawFacesSolid = cdDM_drawFacesSolid;
1702         dm->drawFacesColored = cdDM_drawFacesColored;
1703         dm->drawFacesTex = cdDM_drawFacesTex;
1704         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1705         dm->drawMappedFaces = cdDM_drawMappedFaces;
1706         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1707         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1708         dm->drawMappedFacesMat = cdDM_drawMappedFacesMat;
1709
1710         dm->foreachMappedVert = cdDM_foreachMappedVert;
1711         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1712         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1713
1714         dm->release = cdDM_release;
1715
1716         return cddm;
1717 }
1718
1719 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
1720 {
1721         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1722         DerivedMesh *dm = &cddm->dm;
1723
1724         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
1725
1726         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1727         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1728         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces);
1729         CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numTessFaces);
1730         CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
1731
1732         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1733         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1734         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces);
1735         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
1736         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
1737
1738         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1739         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1740         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1741         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1742         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1743
1744         return dm;
1745 }
1746
1747 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1748 {
1749         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1750         DerivedMesh *dm = &cddm->dm;
1751         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1752         int alloctype;
1753         int *polyindex = NULL;
1754
1755         /* this does a referenced copy, with an exception for fluidsim */
1756
1757         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
1758                     mesh->totloop, mesh->totpoly);
1759
1760         dm->deformedOnly = 1;
1761
1762         alloctype= CD_REFERENCE;
1763
1764         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1765                                          mesh->totvert);
1766         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1767                                          mesh->totedge);
1768         CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_POLYINDEX, alloctype,
1769                                          mesh->totface);
1770         CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
1771                          mesh->totloop);
1772         CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
1773                          mesh->totpoly);
1774
1775         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1776         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1777         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1778         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1779         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1780
1781         /* commented since even when CD_POLYINDEX was first added this line fails
1782          * on the default cube, (after editmode toggle too) - campbell */
1783 #if 0
1784         BLI_assert(CustomData_has_layer(&cddm->dm.faceData, CD_POLYINDEX));
1785 #endif
1786
1787         polyindex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX);
1788         if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX)) {
1789                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyindex, mesh->totface);
1790         }
1791
1792         return dm;
1793 }
1794
1795 static DerivedMesh *UNUSED_FUNCTION(CDDM_from_editmesh)(EditMesh *em, Mesh *UNUSED(me))
1796 {
1797         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1798                                    BLI_countlist(&em->edges),
1799                                    BLI_countlist(&em->faces), 0, 0);
1800         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1801         EditVert *eve;
1802         EditEdge *eed;
1803         EditFace *efa;
1804         MVert *mvert = cddm->mvert;
1805         MEdge *medge = cddm->medge;
1806         MFace *mface = cddm->mface;
1807         int i, *index;
1808
1809         dm->deformedOnly = 1;
1810
1811         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1812                                          CD_CALLOC, dm->numVertData);
1813         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1814                                          CD_CALLOC, dm->numEdgeData); */
1815         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1816                                          CD_CALLOC, dm->numTessFaceData);
1817         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1818                          CD_CALLOC, dm->numTessFaceData);
1819
1820         /* set eve->hash to vert index */
1821         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1822                 eve->tmp.l = i;
1823
1824         /* Need to be able to mark loose edges */
1825         for(eed = em->edges.first; eed; eed = eed->next) {
1826                 eed->f2 = 0;
1827         }
1828         for(efa = em->faces.first; efa; efa = efa->next) {
1829                 efa->e1->f2 = 1;
1830                 efa->e2->f2 = 1;
1831                 efa->e3->f2 = 1;
1832                 if(efa->e4) efa->e4->f2 = 1;
1833         }
1834
1835         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1836         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1837                 i++, eve = eve->next, index++) {
1838                 MVert *mv = &mvert[i];
1839
1840                 copy_v3_v3(mv->co, eve->co);
1841
1842                 normal_float_to_short_v3(mv->no, eve->no);
1843                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1844
1845                 mv->flag = 0;
1846
1847                 *index = i;
1848
1849                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1850         }
1851
1852         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1853         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1854                 i++, eed = eed->next, index++) {
1855                 MEdge *med = &medge[i];
1856
1857                 med->v1 = eed->v1->tmp.l;
1858                 med->v2 = eed->v2->tmp.l;
1859                 med->crease = (unsigned char) (eed->crease * 255.0f);
1860                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1861                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1862                 
1863                 if(eed->seam) med->flag |= ME_SEAM;
1864                 if(eed->sharp) med->flag |= ME_SHARP;
1865                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1866
1867                 *index = i;
1868
1869                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1870         }
1871
1872         index = dm->getTessFaceDataArray(dm, CD_POLYINDEX);
1873         for(i = 0, efa = em->faces.first; i < dm->numTessFaceData;
1874                 i++, efa = efa->next, index++) {
1875                 MFace *mf = &mface[i];
1876
1877                 mf->v1 = efa->v1->tmp.l;
1878                 mf->v2 = efa->v2->tmp.l;
1879                 mf->v3 = efa->v3->tmp.l;
1880                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1881                 mf->mat_nr = efa->mat_nr;
1882                 mf->flag = efa->flag;
1883
1884                 *index = i;
1885
1886                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1887                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1888         }
1889
1890         return dm;
1891 }
1892
1893 DerivedMesh *CDDM_from_curve(Object *ob)
1894 {
1895         return CDDM_from_curve_customDB(ob, &ob->disp);
1896 }
1897
1898 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1899 {
1900         DerivedMesh *dm;
1901         CDDerivedMesh *cddm;
1902         MVert *allvert;
1903         MEdge *alledge;
1904         MLoop *allloop;
1905         MPoly *allpoly;
1906         int totvert, totedge, totloop, totpoly;
1907
1908         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1909                 &totedge, &allloop, &allpoly, &totloop, &totpoly) != 0) {
1910                 /* Error initializing mdata. This often happens when curve is empty */
1911                 return CDDM_new(0, 0, 0, 0, 0);
1912         }
1913
1914         dm = CDDM_new(totvert, totedge, 0, totloop, totpoly);
1915         dm->deformedOnly = 1;
1916
1917         cddm = (CDDerivedMesh*)dm;
1918
1919         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1920         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1921         memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop));
1922         memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly));
1923
1924         MEM_freeN(allvert);
1925         MEM_freeN(alledge);
1926         MEM_freeN(allloop);
1927         MEM_freeN(allpoly);
1928
1929         CDDM_calc_edges(dm);
1930
1931         return dm;
1932 }
1933
1934 static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
1935                                           int cdindex, BMLoop *l3[3],
1936                                           int numCol, int numTex)
1937 {
1938         BMLoop *l;
1939         BMFace *f = l3[0]->f;
1940         MTFace *texface;
1941         MTexPoly *texpoly;
1942         MCol *mcol;
1943         MLoopCol *mloopcol;
1944         MLoopUV *mloopuv;
1945         int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
1946
1947         for(i=0; i < numTex; i++){
1948                 texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
1949                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
1950                 
1951                 texface->tpage = texpoly->tpage;
1952                 texface->flag = texpoly->flag;
1953                 texface->transp = texpoly->transp;
1954                 texface->mode = texpoly->mode;
1955                 texface->tile = texpoly->tile;
1956                 texface->unwrap = texpoly->unwrap;
1957         
1958                 for (j=0; j<3; j++) {
1959                         l = l3[j];
1960                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
1961                         texface->uv[j][0] = mloopuv->uv[0];
1962                         texface->uv[j][1] = mloopuv->uv[1];
1963                 }
1964         }
1965
1966         for(i=0; i < numCol; i++){
1967                 mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
1968                 
1969                 for (j=0; j<3; j++) {
1970                         l = l3[j];
1971                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
1972                         mcol[j].r = mloopcol->r;
1973                         mcol[j].g = mloopcol->g;
1974                         mcol[j].b = mloopcol->b;
1975                         mcol[j].a = mloopcol->a;
1976                 }
1977         }
1978
1979         if (hasWCol) {
1980                 mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
1981
1982                 for (j=0; j<3; j++) {
1983                         l = l3[j];
1984                         mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
1985                         mcol[j].r = mloopcol->r;
1986                         mcol[j].g = mloopcol->g;
1987                         mcol[j].b = mloopcol->b;
1988                         mcol[j].a = mloopcol->a;
1989                 }
1990         }
1991 }
1992
1993 DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps, int use_tessface)
1994 {
1995         DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, 
1996                                em->tottri, em->bm->totloop, em->bm->totface);
1997         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1998         BMesh *bm = em->bm;
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 = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
2046         for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
2047                 MVert *mv = &mvert[i];
2048
2049                 copy_v3_v3(mv->co, eve->co);
2050
2051                 BM_SetIndex(eve, i); /* set_inline */
2052
2053                 normal_float_to_short_v3(mv->no, eve->no);
2054
2055                 mv->flag = BM_Vert_Flag_To_MEFlag(eve);
2056
2057                 if (has_vert_bweight)
2058                         mv->bweight = (unsigned char)(BM_GetCDf(&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 = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
2068         for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
2069                 MEdge *med = &medge[i];
2070
2071                 BM_SetIndex(eed, i); /* set_inline */
2072
2073                 med->v1 = BM_GetIndex(eed->v1);
2074                 med->v2 = BM_GetIndex(eed->v2);
2075
2076                 if (has_crease)
2077                         med->crease = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_CREASE)*255.0f);
2078                 if (has_edge_bweight)
2079                         med->bweight = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_BWEIGHT)*255.0f);
2080                 
2081                 med->flag = BM_Edge_Flag_To_MEFlag(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_ElemIndex_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_GetIndex(l[0]->v);
2102                         mf->v2 = BM_GetIndex(l[1]->v);
2103                         mf->v3 = BM_GetIndex(l[2]->v);
2104                         mf->v4 = 0;
2105                         mf->mat_nr = efa->mat_nr;
2106                         mf->flag = BM_Face_Flag_To_MEFlag(efa);
2107
2108                         *index = add_orig ? BM_GetIndex(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
2109                         *polyindex = BM_GetIndex(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 = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
2119         for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
2120                 BMLoop *l;
2121                 MPoly *mp = &mpoly[i];
2122
2123                 BM_SetIndex(efa, i); /* set_inline */
2124
2125                 mp->totloop = efa->len;
2126                 mp->flag = BM_Face_Flag_To_MEFlag(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_GetIndex(l->v);
2132                         mloop->e = BM_GetIndex(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 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
2721 {
2722         return &((CDDerivedMesh*)dm)->mvert[index];
2723 }
2724
2725 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
2726 {
2727         return &((CDDerivedMesh*)dm)->medge[index];
2728 }
2729
2730 MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
2731 {
2732         return &((CDDerivedMesh*)dm)->mface[index];
2733 }
2734
2735 MVert *CDDM_get_verts(DerivedMesh *dm)
2736 {
2737         return ((CDDerivedMesh*)dm)->mvert;
2738 }
2739
2740 MEdge *CDDM_get_edges(DerivedMesh *dm)
2741 {
2742         return ((CDDerivedMesh*)dm)->medge;
2743 }
2744
2745 MFace *CDDM_get_tessfaces(DerivedMesh *dm)
2746 {
2747         return ((CDDerivedMesh*)dm)->mface;
2748 }
2749
2750 MLoop *CDDM_get_loops(DerivedMesh *dm)
2751 {
2752         return ((CDDerivedMesh*)dm)->mloop;
2753 }
2754
2755 MPoly *CDDM_get_polys(DerivedMesh *dm)
2756 {
2757         return ((CDDerivedMesh*)dm)->mpoly;
2758 }
2759
2760 void CDDM_tessfaces_to_faces(DerivedMesh *dm)
2761 {
2762         /*converts mfaces to mpolys/mloops*/
2763         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2764         MFace *mf;
2765         MEdge *me;
2766         EdgeHash *eh = BLI_edgehash_new();
2767         int i, totloop;
2768         
2769         /*ensure we have all the edges we need*/
2770         CDDM_calc_edges_tessface(dm);
2771
2772         /*build edge hash*/
2773         me = cddm->medge;
2774         for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
2775                 BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
2776         }
2777
2778         mf = cddm->mface;
2779         totloop = 0;
2780         for (i=0; i<cddm->dm.numTessFaceData; i++, mf++) {
2781                 totloop += mf->v4 ? 4 : 3;
2782         }
2783
2784         CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
2785         CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
2786         
2787         cddm->dm.numLoopData = totloop;
2788         cddm->dm.numPolyData = cddm->dm.numTessFaceData;
2789
2790         if (totloop) {
2791                 MLoop *ml;
2792                 MPoly *mp;
2793                 int l, *polyindex;
2794
2795                 cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
2796                 cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numTessFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
2797
2798                 CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
2799                 CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
2800                 CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData,
2801                         CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numTessFaceData);
2802
2803                 polyindex = CustomData_get_layer(&cddm->dm.faceData, CD_POLYINDEX);
2804
2805                 mf = cddm->mface;
2806                 mp = cddm->mpoly;
2807                 ml = cddm->mloop;
2808                 l = 0;
2809                 for (i=0; i<cddm->dm.numTessFaceData; i++, mf++, mp++) {
2810                         mp->flag = mf->flag;
2811                         mp->loopstart = l;
2812                         mp->mat_nr = mf->mat_nr;
2813                         mp->totloop = mf->v4 ? 4 : 3;
2814
2815                         ml->v = mf->v1;
2816                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
2817                         ml++, l++;
2818
2819                         ml->v = mf->v2;
2820                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
2821                         ml++, l++;
2822
2823                         ml->v = mf->v3;
2824                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
2825                         ml++, l++;
2826
2827                         if (mf->v4) {
2828                                 ml->v = mf->v4;
2829                                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
2830                                 ml++, l++;
2831                         }
2832
2833                         *polyindex = i;
2834                 }
2835         }
2836
2837         BLI_edgehash_free(eh, NULL);
2838 }
2839
2840 void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
2841 {
2842         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2843         
2844         if (!CustomData_has_layer(&dm->vertData, CD_MVERT))
2845                 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData);
2846                                 
2847         cddm->mvert = mvert;
2848 }
2849
2850 void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
2851 {
2852         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2853
2854         if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE))
2855                 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData);
2856
2857         cddm->medge = medge;
2858 }
2859
2860 void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
2861 {
2862         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2863
2864         if (!CustomData_has_layer(&dm->faceData, CD_MFACE))
2865                 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numTessFaceData);
2866
2867         cddm->mface = mface;
2868 }