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