pre-merge commit
[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->pdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1798                          CD_CALLOC, dm->numFaceData);
1799         CustomData_merge(&em->bm->ldata, &dm->loopData, CD_MASK_DERIVEDMESH,
1800                          CD_CALLOC, dm->numLoopData);
1801         CustomData_merge(&em->bm->pdata, &dm->polyData, CD_MASK_DERIVEDMESH,
1802                          CD_CALLOC, dm->numPolyData);
1803         
1804         /*add tesselation mface layers*/
1805         CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
1806
1807         /* set vert index */
1808         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1809         for (i=0; eve; eve=BMIter_Step(&iter), i++)
1810                 BMINDEX_SET(eve, i);
1811
1812         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1813
1814         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1815         for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
1816                 MVert *mv = &mvert[i];
1817
1818                 VECCOPY(mv->co, eve->co);
1819
1820                 BMINDEX_SET(eve, i);
1821
1822                 mv->no[0] = eve->no[0] * 32767.0;
1823                 mv->no[1] = eve->no[1] * 32767.0;
1824                 mv->no[2] = eve->no[2] * 32767.0;
1825
1826                 mv->mat_nr = 0;
1827                 mv->flag = BMFlags_To_MEFlags(eve);
1828
1829                 if (add_orig) *index = i;
1830
1831                 CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
1832         }
1833
1834         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1835         eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1836         for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
1837                 MEdge *med = &medge[i];
1838
1839                 BMINDEX_SET(eed, i);
1840
1841                 med->v1 = BMINDEX_GET(eed->v1);
1842                 med->v2 = BMINDEX_GET(eed->v2);
1843                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1844                 
1845                 med->flag = BMFlags_To_MEFlags(eed);
1846
1847                 CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
1848                 if (add_orig) *index = i;
1849         }
1850
1851         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1852         for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
1853                 BMINDEX_SET(efa, i);
1854         }
1855
1856         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1857         for(i = 0; i < dm->numFaceData; i++, index++) {
1858                 MFace *mf = &mface[i];
1859                 BMLoop **l = em->looptris[i];
1860                 efa = l[0]->f;
1861
1862                 mf->v1 = BMINDEX_GET(l[0]->v);
1863                 mf->v2 = BMINDEX_GET(l[1]->v);
1864                 mf->v3 = BMINDEX_GET(l[2]->v);
1865                 mf->v4 = 0;
1866                 mf->mat_nr = efa->mat_nr;
1867                 mf->flag = BMFlags_To_MEFlags(efa);
1868                 
1869                 *index = add_orig ? BMINDEX_GET(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
1870
1871                 loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
1872                 test_index_face(mf, &dm->faceData, i, 3);
1873         }
1874         
1875         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1876         j = 0;
1877         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1878         for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
1879                 BMLoop *l;
1880                 MPoly *mp = &mpoly[i];
1881
1882                 mp->totloop = efa->len;
1883                 mp->flag = BMFlags_To_MEFlags(efa);
1884                 mp->loopstart = j;
1885                 mp->mat_nr = efa->mat_nr;
1886                 
1887                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
1888                         mloop->v = BMINDEX_GET(l->v);
1889                         mloop->e = BMINDEX_GET(l->e);
1890                         CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
1891
1892                         j++;
1893                         mloop++;
1894                 }
1895
1896                 CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
1897
1898                 if (add_orig) *index = i;
1899         }
1900
1901         return dm;
1902 }
1903
1904 typedef struct CDDM_LoopIter {
1905         DMLoopIter head;
1906         CDDerivedMesh *cddm;
1907         int len, i;
1908 } CDDM_LoopIter;
1909
1910 typedef struct CDDM_FaceIter {
1911         DMFaceIter head;
1912         CDDerivedMesh *cddm;
1913         CDDM_LoopIter liter;
1914 } CDDM_FaceIter;
1915
1916 void cddm_freeiter(void *self)
1917 {
1918         MEM_freeN(self);
1919 }
1920
1921 void cddm_stepiter(void *self)
1922 {
1923         CDDM_FaceIter *iter = self;
1924         MPoly *mp;
1925         
1926         mp = iter->cddm->mpoly + iter->head.index;
1927         mp->flag = iter->head.flags;
1928         mp->mat_nr = iter->head.mat_nr;
1929
1930         iter->head.index++;
1931         if (iter->head.index >= iter->cddm->dm.numPolyData) {
1932                 iter->head.done = 1;
1933                 return;
1934         }
1935
1936         mp = iter->cddm->mpoly + iter->head.index;
1937
1938         iter->head.flags = mp->flag;
1939         iter->head.mat_nr = mp->mat_nr;
1940         iter->head.len = mp->totloop;
1941 }
1942
1943 void *cddm_faceiter_getcddata(void *self, int type, int layer)
1944 {
1945         CDDM_FaceIter *iter = self;
1946
1947         if (layer == -1) return CustomData_get(&iter->cddm->dm.polyData, 
1948                                                iter->head.index, type);
1949         else return CustomData_get_n(&iter->cddm->dm.polyData, type, 
1950                                     iter->head.index, layer);
1951 }
1952
1953 void *cddm_loopiter_getcddata(void *self, int type, int layer)
1954 {
1955         CDDM_LoopIter *iter = self;
1956
1957         if (layer == -1) return CustomData_get(&iter->cddm->dm.loopData, 
1958                                                iter->head.index, type);
1959         else return CustomData_get_n(&iter->cddm->dm.loopData, type, 
1960                                      iter->head.index, layer);
1961 }
1962
1963 void *cddm_loopiter_getvertcddata(void *self, int type, int layer)
1964 {
1965         CDDM_LoopIter *iter = self;
1966
1967         if (layer == -1) return CustomData_get(&iter->cddm->dm.vertData, 
1968                                                iter->cddm->mloop[iter->head.vindex].v,
1969                                                type);
1970         else return CustomData_get_n(&iter->cddm->dm.vertData, type, 
1971                                      iter->cddm->mloop[iter->head.vindex].v, layer);
1972 }
1973
1974 DMLoopIter *cddmiter_get_loopiter(void *self)
1975 {
1976         CDDM_FaceIter *iter = self;
1977         CDDM_LoopIter *liter = &iter->liter;
1978         MPoly *mp = iter->cddm->mpoly + iter->head.index;
1979
1980         liter->i = -1;
1981         liter->len = iter->head.len;
1982         liter->head.index = mp->loopstart-1;
1983         liter->head.done = 0;
1984
1985         liter->head.step(liter);
1986
1987         return (DMLoopIter*) liter;
1988 }
1989
1990 void cddm_loopiter_step(void *self)
1991 {
1992         CDDM_LoopIter *liter = self;
1993         MLoop *ml;
1994
1995         liter->i++;
1996         liter->head.index++;
1997
1998         if (liter->i == liter->len) {
1999                 liter->head.done = 1;
2000                 return;
2001         }
2002
2003         ml = liter->cddm->mloop + liter->head.index;
2004
2005         liter->head.eindex = ml->e;
2006         liter->head.v = liter->cddm->mvert[ml->v];
2007         liter->head.vindex = ml->v;
2008 }
2009
2010 DMFaceIter *cdDM_newFaceIter(DerivedMesh *source)
2011 {
2012         CDDerivedMesh *cddm = (CDDerivedMesh*) source;
2013         CDDM_FaceIter *iter = MEM_callocN(sizeof(CDDM_FaceIter), "DMFaceIter from cddm");
2014
2015         iter->head.free = cddm_freeiter;
2016         iter->head.step = cddm_stepiter;
2017         iter->head.getCDData = cddm_faceiter_getcddata;
2018         iter->head.getLoopsIter = cddmiter_get_loopiter;
2019
2020         iter->liter.head.step = cddm_loopiter_step;
2021         iter->liter.head.getLoopCDData = cddm_loopiter_getcddata;
2022         iter->liter.head.getVertCDData = cddm_loopiter_getvertcddata;
2023         iter->liter.cddm = cddm;
2024
2025         iter->cddm = cddm;
2026
2027         if (source->numFaceData) {
2028                 iter->head.index = -1;
2029                 iter->head.step(iter);
2030         } else {
2031                 iter->head.done = 1;
2032         }
2033
2034         return (DMFaceIter*) iter;
2035 }
2036
2037 DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
2038 {
2039         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
2040         DerivedMesh *dm = &cddm->dm;
2041         int numVerts = source->numVertData;
2042         int numEdges = source->numEdgeData;
2043         int numFaces = source->numFaceData;
2044         int numLoops = source->numLoopData;
2045         int numPolys = source->numPolyData;
2046
2047         /* ensure these are created if they are made on demand */
2048         source->getVertDataArray(source, CD_ORIGINDEX);
2049         source->getEdgeDataArray(source, CD_ORIGINDEX);
2050         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2051
2052         /* this initializes dm, and copies all non mvert/medge/mface layers */
2053         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
2054                 numLoops, numPolys);
2055         dm->deformedOnly = source->deformedOnly;
2056
2057         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
2058         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
2059         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
2060
2061         /* now add mvert/medge/mface layers */
2062         cddm->mvert = source->dupVertArray(source);
2063         cddm->medge = source->dupEdgeArray(source);
2064         cddm->mface = source->dupTessFaceArray(source);
2065
2066         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
2067         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
2068         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
2069         
2070         if (!faces_from_tessfaces)
2071                 DM_DupPolys(source, dm);
2072         else
2073                 CDDM_tessfaces_to_faces(dm);
2074
2075         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2076         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2077
2078         return dm;
2079 }
2080
2081 DerivedMesh *CDDM_from_template(DerivedMesh *source,
2082                                 int numVerts, int numEdges, int numFaces,
2083                                                                 int numLoops, int numPolys)
2084 {
2085         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
2086         DerivedMesh *dm = &cddm->dm;
2087
2088         /* ensure these are created if they are made on demand */
2089         source->getVertDataArray(source, CD_ORIGINDEX);
2090         source->getEdgeDataArray(source, CD_ORIGINDEX);
2091         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2092
2093         /* this does a copy of all non mvert/medge/mface layers */
2094         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
2095
2096         /* now add mvert/medge/mface layers */
2097         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
2098         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2099         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
2100         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
2101         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
2102
2103         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
2104                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
2105         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
2106                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2107         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
2108                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
2109
2110         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
2111         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2112         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
2113         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2114         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2115
2116         return dm;
2117 }
2118
2119 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
2120 {
2121         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2122         MVert *vert;
2123         int i;
2124
2125         /* this will just return the pointer if it wasn't a referenced layer */
2126         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2127         cddm->mvert = vert;
2128
2129         for(i = 0; i < dm->numVertData; ++i, ++vert)
2130                 VECCOPY(vert->co, vertCoords[i]);
2131 }
2132
2133 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
2134 {
2135         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2136         MVert *vert;
2137         int i;
2138
2139         /* this will just return the pointer if it wasn't a referenced layer */
2140         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2141         cddm->mvert = vert;
2142
2143         for(i = 0; i < dm->numVertData; ++i, ++vert)
2144                 VECCOPY(vert->no, vertNormals[i]);
2145 }
2146
2147 void CDDM_calc_normals(DerivedMesh *dm)
2148 {
2149         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2150         float (*temp_nors)[3];
2151         float (*face_nors)[3];
2152         float (*vert_nors)[3];
2153         int i, j, *origIndex;
2154         int numVerts = dm->numVertData;
2155         int numFaces = dm->numFaceData;
2156         MFace *mf;
2157         MPoly *mp;
2158         MVert *mv;
2159         MLoop *ml;
2160
2161         if(numVerts == 0) return;
2162
2163         if (CustomData_has_layer(&dm->faceData, CD_NORMAL))
2164                 CustomData_free_layer(&dm->faceData, CD_NORMAL, dm->numFaceData, 0);
2165
2166         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
2167                                                         "CDDM_calc_normals temp_nors");
2168
2169         /*recalc tesselation to ensure we have valid origindex values
2170           for mface->mpoly lookups.*/
2171         cdDM_recalcTesselation2(dm);
2172
2173         numFaces = dm->numFaceData;
2174
2175         /*first go through and calculate normals for all the polys*/
2176         temp_nors = MEM_callocN(sizeof(float)*3*dm->numPolyData, "temp_nors cdderivedmesh.c");
2177         vert_nors = MEM_callocN(sizeof(float)*3*dm->numVertData, "vert_nors cdderivedmesh.c");
2178         
2179         mp = cddm->mpoly;
2180         for (i=0; i<dm->numPolyData; i++, mp++) {
2181                 mesh_calc_poly_normal(mp, cddm->mloop+mp->loopstart, cddm->mvert, temp_nors[i]);
2182
2183                 ml = cddm->mloop + mp->loopstart;
2184                 for (j=0; j<mp->totloop; j++, ml++) {
2185                         VECADD(vert_nors[ml->v], vert_nors[ml->v], temp_nors[i]);
2186                 }
2187         }
2188
2189         face_nors = MEM_callocN(sizeof(float)*3*dm->numFaceData, "face_nors cdderivedmesh.c");
2190         origIndex = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
2191
2192         mf = cddm->mface;
2193         for (i=0; i<dm->numFaceData; i++, mf++, origIndex++) {
2194                 VECCOPY(face_nors[i], temp_nors[*origIndex]);
2195         }
2196
2197         mv = cddm->mvert;
2198         for (i=0; i<dm->numVertData; i++, mv++) {
2199                 float *no = vert_nors[i];
2200                 
2201                 if (normalize_v3(no) == 0.0) {
2202                         VECCOPY(no, mv->co);
2203                         if (normalize_v3(no) == 0.0) {
2204                                 no[0] = 0.0f;
2205                                 no[1] = 0.0f;
2206                                 no[2] = 1.0f;
2207                         }
2208                 }
2209
2210                 normal_float_to_short_v3(mv->no, no);
2211         }
2212
2213         MEM_freeN(temp_nors);
2214         MEM_freeN(vert_nors);
2215
2216         /*this restores original poly origindex -> tessface origindex mapping,
2217           instead of the poly index -> tessface origindex one we generated
2218           with cdDM_recalcTesselation2*/
2219         cdDM_recalcTesselation(dm);
2220         CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, 
2221                 face_nors, dm->numFaceData);
2222 }
2223
2224 #if 0
2225 /*merge verts
2226  
2227   vtargetmap is a table that maps vertices to target vertices.  a value of -1
2228   indicates a vertex is a target, and is to be kept.
2229   
2230   this is a really horribly written function.  ger. - joeedh
2231
2232  */
2233 DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap)
2234 {
2235         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2236         CDDerivedMesh *cddm2 = NULL;
2237         MVert *mv, *mvert = NULL;
2238         BLI_array_declare(mvert);
2239         MEdge *me, *medge = NULL;
2240         BLI_array_declare(medge);
2241         MPoly *mp, *mpoly = NULL;
2242         BLI_array_declare(mpoly);
2243         MLoop *ml, *mloop = NULL;
2244         BLI_array_declare(mloop);
2245         SmallHash _hash, *hash=&_hash;
2246         SmallHash _hash2, *hash2=&_hash2;
2247         int *newv = NULL, *newe = NULL, *newl = NULL;
2248         int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
2249         BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
2250         int i, j, c, totloop, totpoly;
2251         
2252         BLI_smallhash_init(hash);
2253         BLI_smallhash_init(hash2);
2254
2255 #if 0
2256         /*split off ngon faces with merges in them*/
2257         mp = cddm->mpoly;
2258         for (i=0; i<dm->numPolyData; i++, mp++) {
2259                 ml = cddm->mloop + mp->loopstart;
2260                 for (j=0; j<mp->totloop; j++, ml++) {
2261                         MLoop *ml2 = NULL;
2262                         int k, k1, a;
2263                         
2264                         if (ml->v == -1)
2265                                 continue;
2266                         
2267                         for (k1=0; k1<mp->totloop; k1++) {
2268                                 k = (j + k1) % mp->totloop;
2269                                 ml2 = cddm->mloop + mp->loopstart + k;
2270                                 
2271                                 if (ml == ml2 || ml2->v == -1)
2272                                         continue;
2273                                 
2274                                 if (vtargetmap[ml->v] == ml2->v || vtargetmap[ml2->v] == ml->v) {
2275                                         MLoop *ml3;
2276                                         MPoly *mp2;
2277                                         int s, e, l, tot;
2278                                         
2279                                         if (k < j) 
2280                                                 SWAP(int, k, j);
2281                                         
2282                                         s = j; e = k; tot = 0;
2283                                         l = BLI_array_count(mloop);
2284                                         ml3 = cddm->mloop + mp->loopstart + s;
2285                                         for (a=s; a<e; a++, ml3++) {
2286                                                 if (ml3->v == -1)
2287                                                         continue;
2288                                                 
2289                                                 BLI_smallhash_insert(hash, dm->numLoopData + BLI_array_count(mloop), SET_INT_IN_POINTER(mp->loopstart + a - s));
2290                                                 BLI_array_append(mloop, *ml3);
2291                                                 
2292                                                 ml3->v = -1;
2293                                                 ml3->e = -1;
2294                                                 tot++;
2295                                         }
2296                                         
2297                                         if (!tot)
2298                                                 continue;
2299                                         
2300                                         BLI_smallhash_insert(hash2, dm->numPolyData + BLI_array_count(mpoly), SET_INT_IN_POINTER(i));
2301         
2302                                         mp2 = BLI_array_append(mpoly, *mp);
2303                                         mp2->loopstart = l + dm->numLoopData;
2304                                         mp2->totloop = tot;
2305                                 }
2306                         }
2307                 }
2308         }
2309
2310         ml = MEM_callocN(sizeof(MLoop)*(dm->numLoopData + BLI_array_count(mloop)), "merge mloop");
2311         mp = MEM_callocN(sizeof(MPoly)*(dm->numPolyData + BLI_array_count(mloop)), "merge mpoly");
2312         
2313         memcpy(ml, cddm->mloop, sizeof(MLoop)*dm->numLoopData);
2314         memcpy(mp, cddm->mpoly, sizeof(MPoly)*dm->numPolyData);
2315         
2316         cddm->mloop = ml; cddm->mpoly = mp;
2317         
2318         memcpy(cddm->mloop+dm->numLoopData, mloop, sizeof(MLoop)*BLI_array_count(mloop));
2319         memcpy(cddm->mpoly+dm->numPolyData, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
2320         
2321         totloop = dm->numLoopData + BLI_array_count(mloop);
2322         totpoly = dm->numPolyData + BLI_array_count(mpoly);
2323         
2324         BLI_array_empty(mloop);
2325         BLI_array_empty(mpoly);
2326 #else
2327         totloop = dm->numLoopData;
2328         totpoly = dm->numPolyData;
2329 #endif
2330         
2331         newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts");
2332         newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts");
2333         newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts");
2334                 
2335         mv = cddm->mvert;
2336         c = 0;
2337         for (i=0; i<dm->numVertData; i++, mv++) {
2338                 if (vtargetmap[i] == -1) {
2339                         BLI_array_append(oldv, i);
2340                         newv[i] = c++;
2341                         BLI_array_append(mvert, *mv);
2342                 }
2343         }
2344         
2345         /*find-replace merged vertices with target vertices*/   
2346         ml = cddm->mloop;
2347         c = 0;
2348         for (i=0; i<totloop; i++, ml++) {
2349                 if (ml->v == -1)
2350                         continue;
2351                 
2352                 if (vtargetmap[ml->v] != -1) {
2353                         me = &cddm->medge[ml->e];
2354                         if (me->v1 == ml->v)
2355                                 me->v1 = vtargetmap[ml->v];
2356                         else
2357                                 me->v2 = vtargetmap[ml->v];
2358                         
2359                         ml->v = vtargetmap[ml->v];
2360                 }
2361         }
2362         
2363         /*now go through and fix edges and faces*/
2364         me = cddm->medge;
2365         c = 0;
2366         for (i=0; i<dm->numEdgeData; i++, me++) {
2367                 if (me->v1 == me->v2)
2368                         continue;
2369                 
2370                 BLI_array_append(olde, i);
2371                 newe[i] = c++;
2372                 BLI_array_append(medge, *me);
2373         }
2374         
2375         mp = cddm->mpoly;
2376         for (i=0; i<totpoly; i++, mp++) {
2377                 MPoly *mp2;
2378                 
2379                 ml = cddm->mloop + mp->loopstart;
2380                 
2381                 c = 0;
2382                 for (j=0; j<mp->totloop; j++, ml++) {
2383                         if (ml->v == -1)
2384                                 continue;
2385                         
2386                         me = cddm->medge + ml->e;
2387                         if (me->v1 != me->v2) {
2388                                 BLI_array_append(oldl, j);
2389                                 BLI_array_append(mloop, *ml);
2390                                 newl[c] = BLI_array_count(mloop)-1;
2391                                 c++;
2392                         }
2393                 }
2394                 
2395                 if (!c)
2396                         continue;
2397                 
2398                 mp2 = BLI_array_append(mpoly, *mp);
2399                 mp2->totloop = c;
2400                 mp2->loopstart = BLI_array_count(mloop) - c;
2401                 
2402                 BLI_array_append(oldp, i);
2403         }
2404         
2405         /*create new cddm*/     
2406         cddm2 = (CDDerivedMesh*) CDDM_new(BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
2407         
2408         /*copy over data.  CustomData_add_layer can do this, need to look it up.*/
2409         memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert));
2410         memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge));
2411         memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop));
2412         memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
2413         
2414         BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
2415         mvert = cddm2->mvert; medge = cddm2->medge; mloop = cddm2->mloop; mpoly = cddm2->mpoly;
2416         
2417         /*update edge indices and copy customdata*/
2418         me = cddm2->medge;
2419         for (i=0; i<cddm2->dm.numEdgeData; i++, me++) {
2420                 MEdge cpy;
2421                 
2422                 me->v1 = newv[me->v1];
2423                 me->v2 = newv[me->v2];
2424                 
2425                 cpy = *me;
2426                 CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1);
2427                 *me = cpy;
2428         }
2429         
2430         /*update loop indices and copy customdata*/
2431         ml = cddm2->mloop;
2432         for (i=0; i<cddm2->dm.numLoopData; i++, ml++) {
2433                 MLoop cpy;
2434                 
2435                 ml->e = newe[ml->e];
2436                 ml->v = newv[ml->v];
2437                         
2438                 cpy = *ml;
2439                 
2440                 if (oldl[i] >= dm->numLoopData)
2441                         oldl[i] = GET_INT_FROM_POINTER(BLI_smallhash_lookup(hash, (intptr_t)oldl[i]));
2442
2443                 CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
2444                 *ml = cpy;
2445         }
2446         
2447         /*copy vertex customdata*/      
2448         mv = cddm2->mvert;
2449         for (i=0; i<cddm2->dm.numVertData; i++, mv++) {
2450                 MVert cpy = *mv;
2451                 
2452                 CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1);
2453                 *mv = cpy;
2454         }
2455         
2456         /*copy poly customdata*/
2457         mp = cddm2->mpoly;
2458         for (i=0; i<cddm2->dm.numPolyData; i++, mp++) {
2459                 MPoly cpy = *mp;
2460                 
2461                 if (oldl[i] >= dm->numPolyData)
2462                         oldl[i] = GET_INT_FROM_POINTER(BLI_smallhash_lookup(hash, (intptr_t)oldl[i]));
2463
2464                 CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1);
2465                 *mp = cpy;
2466         }
2467         
2468         /*eek! not sure what to do with ORIGINDEX stuff here!!*/        
2469         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);
2470         cddm2->mface = CustomData_get_layer(&cddm->dm.faceData, CD_MFACE);
2471         
2472         if (newv) 
2473                 MEM_freeN(newv); 
2474         if (newe)
2475                 MEM_freeN(newe); 
2476         if (newl)
2477                 MEM_freeN(newl);
2478         if (oldv) 
2479                 MEM_freeN(oldv); 
2480         if (olde) 
2481                 MEM_freeN(olde); 
2482         if (oldl) 
2483                 MEM_freeN(oldl); 
2484         if (oldp) 
2485                 MEM_freeN(oldp);
2486         
2487         BLI_smallhash_release(hash);
2488         BLI_smallhash_release(hash2);
2489         
2490         dm->needsFree = 1;
2491         dm->release(dm);
2492         
2493         return (DerivedMesh*)cddm2;
2494 }
2495 #endif
2496
2497 void CDDM_calc_edges(DerivedMesh *dm)
2498 {
2499         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2500         CustomData edgeData;
2501         EdgeHashIterator *ehi;
2502         MFace *mf = cddm->mface;
2503         MEdge *med;
2504         EdgeHash *eh = BLI_edgehash_new();
2505         int i, *index, numEdges, maxFaces = dm->numFaceData;
2506
2507         for (i = 0; i < maxFaces; i++, mf++) {
2508                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
2509                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
2510                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
2511                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
2512                 
2513                 if (mf->v4) {
2514                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
2515                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
2516                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
2517                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
2518                 } else {
2519                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
2520                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
2521                 }
2522         }
2523
2524         numEdges = BLI_edgehash_size(eh);
2525
2526         /* write new edges into a temporary CustomData */
2527         memset(&edgeData, 0, sizeof(edgeData));
2528         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2529         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2530
2531         ehi = BLI_edgehashIterator_new(eh);
2532         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2533         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2534         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2535                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2536                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2537
2538                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2539                 *index = ORIGINDEX_NONE;
2540         }
2541         BLI_edgehashIterator_free(ehi);
2542
2543         /* free old CustomData and assign new one */
2544         CustomData_free(&dm->edgeData, dm->numEdgeData);
2545         dm->edgeData = edgeData;
2546         dm->numEdgeData = numEdges;
2547
2548         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2549
2550         BLI_edgehash_free(eh, NULL);
2551 }
2552
2553
2554 void CDDM_calc_edges_poly(DerivedMesh *dm)
2555 {
2556         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2557         CustomData edgeData;
2558         EdgeHashIterator *ehi;
2559         MPoly *mp = cddm->mpoly;
2560         MLoop *ml;
2561         MEdge *med;
2562         EdgeHash *eh = BLI_edgehash_new();
2563         int v1, v2;
2564         int *eindex;
2565         int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
2566
2567         eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
2568
2569         med = cddm->medge;
2570         if (med) {
2571                 for (i=0; i < numEdges; i++, med++) {
2572                         BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
2573                 }
2574         }
2575
2576         for (i=0; i < maxFaces; i++, mp++) {
2577                 ml = cddm->mloop + mp->loopstart;
2578                 for (j=0; j<mp->totloop; j++, ml++) {
2579                         v1 = ml->v;
2580                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2581                         if (!BLI_edgehash_haskey(eh, v1, v2)) {
2582                                 BLI_edgehash_insert(eh, v1, v2, NULL);
2583                         }
2584                 }
2585         }
2586
2587         k = numEdges;
2588         numEdges = BLI_edgehash_size(eh);
2589
2590         /* write new edges into a temporary CustomData */
2591         memset(&edgeData, 0, sizeof(edgeData));
2592         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2593         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2594
2595         ehi = BLI_edgehashIterator_new(eh);
2596         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2597         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2598         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2599             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2600                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2601                 j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
2602
2603                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2604                 *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
2605
2606                 BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
2607         }
2608         BLI_edgehashIterator_free(ehi);
2609
2610         /* free old CustomData and assign new one */
2611         CustomData_free(&dm->edgeData, dm->numEdgeData);
2612         dm->edgeData = edgeData;
2613         dm->numEdgeData = numEdges;
2614
2615         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2616
2617         mp = cddm->mpoly;
2618         for (i=0; i < maxFaces; i++, mp++) {
2619                 ml = cddm->mloop + mp->loopstart;
2620                 for (j=0; j<mp->totloop; j++, ml++) {
2621                         v1 = ml->v;
2622                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2623                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
2624                 }
2625         }
2626
2627         BLI_edgehash_free(eh, NULL);
2628 }
2629
2630 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
2631 {
2632         if (numVerts < dm->numVertData)
2633                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
2634
2635         dm->numVertData = numVerts;
2636 }
2637
2638 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
2639 {
2640         if (numEdges < dm->numEdgeData)
2641                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
2642
2643         dm->numEdgeData = numEdges;
2644 }
2645
2646 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
2647 {
2648         if (numFaces < dm->numFaceData)
2649                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
2650
2651         dm->numFaceData = numFaces;
2652 }
2653
2654 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
2655 {
2656         return &((CDDerivedMesh*)dm)->mvert[index];
2657 }
2658
2659 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
2660 {
2661         return &((CDDerivedMesh*)dm)->medge[index];
2662 }
2663
2664 MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
2665 {
2666         return &((CDDerivedMesh*)dm)->mface[index];
2667 }
2668
2669 MVert *CDDM_get_verts(DerivedMesh *dm)
2670 {
2671         return ((CDDerivedMesh*)dm)->mvert;
2672 }
2673
2674 MEdge *CDDM_get_edges(DerivedMesh *dm)
2675 {
2676         return ((CDDerivedMesh*)dm)->medge;
2677 }
2678
2679 MFace *CDDM_get_tessfaces(DerivedMesh *dm)
2680 {
2681         return ((CDDerivedMesh*)dm)->mface;
2682 }
2683
2684 void CDDM_tessfaces_to_faces(DerivedMesh *dm)
2685 {
2686         /*converts mfaces to mpolys/mloops*/
2687         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2688         MFace *mf;
2689         MEdge *me;
2690         MLoop *ml;
2691         MPoly *mp;
2692         EdgeHash *eh = BLI_edgehash_new();
2693         int i, l, totloop, *index1, *index2;
2694         
2695         /*ensure we have all the edges we need*/
2696         CDDM_calc_edges(dm);
2697
2698         /*build edge hash*/
2699         me = cddm->medge;
2700         for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
2701                 BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
2702         }
2703
2704         mf = cddm->mface;
2705         totloop = 0;
2706         for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
2707                 totloop += mf->v4 ? 4 : 3;
2708         }
2709
2710         CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
2711         CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
2712         
2713         cddm->dm.numLoopData = totloop;
2714         cddm->dm.numPolyData = cddm->dm.numFaceData;
2715
2716         if (!totloop) return;
2717
2718         cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
2719         cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
2720         
2721         CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
2722         CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
2723         CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, 
2724                 CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData);
2725
2726         index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
2727         index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
2728
2729         mf = cddm->mface;
2730         mp = cddm->mpoly;
2731         ml = cddm->mloop;
2732         l = 0;
2733         for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
2734                 mp->flag = mf->flag;
2735                 mp->loopstart = l;
2736                 mp->mat_nr = mf->mat_nr;
2737                 mp->totloop = mf->v4 ? 4 : 3;
2738                 
2739                 ml->v = mf->v1;
2740                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
2741                 ml++, l++;
2742
2743                 ml->v = mf->v2;
2744                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
2745                 ml++, l++;
2746
2747                 ml->v = mf->v3;
2748                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
2749                 ml++, l++;
2750
2751                 if (mf->v4) {
2752                         ml->v = mf->v4;
2753                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
2754                         ml++, l++;
2755                 }
2756
2757         }
2758
2759         BLI_edgehash_free(eh, NULL);
2760 }
2761
2762 void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
2763 {
2764         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2765
2766         cddm->mvert = mvert;
2767 }
2768
2769 void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
2770 {
2771         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2772
2773         cddm->medge = medge;
2774 }
2775
2776 void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
2777 {
2778         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2779
2780         cddm->mface = mface;
2781 }