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