Another rip fix for rip grabbing the wrong side of the split edges
[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_vcol, 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_vcol, 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
1050 static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, int smoothnormal)
1051 {
1052         int b;
1053
1054         /* orco texture coordinates */
1055         if(attribs->totorco) {
1056                 if(attribs->orco.glTexco)
1057                         glTexCoord3fv(attribs->orco.array[index]);
1058                 else
1059                         glVertexAttrib3fvARB(attribs->orco.glIndex, attribs->orco.array[index]);
1060         }
1061
1062         /* uv texture coordinates */
1063         for(b = 0; b < attribs->tottface; b++) {
1064                 MTFace *tf = &attribs->tface[b].array[a];
1065
1066                 if(attribs->tface[b].glTexco)
1067                         glTexCoord2fv(tf->uv[vert]);
1068                 else
1069                         glVertexAttrib2fvARB(attribs->tface[b].glIndex, tf->uv[vert]);
1070         }
1071
1072         /* vertex colors */
1073         for(b = 0; b < attribs->totmcol; b++) {
1074                 MCol *cp = &attribs->mcol[b].array[a*4 + vert];
1075                 GLubyte col[4];
1076                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1077                 glVertexAttrib4ubvARB(attribs->mcol[b].glIndex, col);
1078         }
1079
1080         /* tangent for normal mapping */
1081         if(attribs->tottang) {
1082                 float *tang = attribs->tang.array[a*4 + vert];
1083                 glVertexAttrib4fvARB(attribs->tang.glIndex, tang);
1084         }
1085
1086         /* vertex normal */
1087         if(smoothnormal)
1088                 glNormal3sv(mvert[index].no);
1089
1090         /* vertex coordinate */
1091         glVertex3fv(mvert[index].co);
1092 }
1093
1094
1095 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
1096 {
1097         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1098         GPUVertexAttribs gattribs;
1099         DMVertexAttribs attribs;
1100         MVert *mvert = cddm->mvert;
1101         MFace *mface = cddm->mface;
1102         /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
1103         float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
1104         int a, b, dodraw, matnr, new_matnr;
1105         int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1106
1107         cdDM_update_normals_from_pbvh(dm);
1108
1109         matnr = -1;
1110         dodraw = 0;
1111
1112         glShadeModel(GL_SMOOTH);
1113
1114         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1115                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1116                 memset(&attribs, 0, sizeof(attribs));
1117
1118                 glBegin(GL_QUADS);
1119
1120                 for(a = 0; a < dm->numFaceData; a++, mface++) {
1121                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1122                         new_matnr = mface->mat_nr + 1;
1123
1124                         if(new_matnr != matnr) {
1125                                 glEnd();
1126
1127                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1128                                 if(dodraw)
1129                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1130
1131                                 glBegin(GL_QUADS);
1132                         }
1133
1134                         if(!dodraw) {
1135                                 continue;
1136                         }
1137                         else if(setDrawOptions) {
1138                                 orig = (index)? index[a]: a;
1139
1140                                 if(orig == ORIGINDEX_NONE) {
1141                                         /* since the material is set by setMaterial(), faces with no
1142                                          * origin can be assumed to be generated by a modifier */ 
1143                                         
1144                                         /* continue */
1145                                 }
1146                                 else if(!setDrawOptions(userData, orig))
1147                                         continue;
1148                         }
1149
1150                         if(!smoothnormal) {
1151                                 if(nors) {
1152                                         glNormal3fv(nors[a]);
1153                                 }
1154                                 else {
1155                                         /* TODO ideally a normal layer should always be available */
1156                                         float nor[3];
1157                                         if(mface->v4) {
1158                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1159                                         } else {
1160                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1161                                         }
1162                                         glNormal3fv(nor);
1163                                 }
1164                         }
1165
1166                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal);
1167                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal);
1168                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1169                         if(mface->v4)
1170                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal);
1171                         else
1172                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1173
1174                 }
1175                 glEnd();
1176         }
1177         else {
1178                 GPUBuffer *buffer = NULL;
1179                 char *varray = NULL;
1180                 int numdata = 0, elementsize = 0, offset;
1181                 int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0;
1182                 int i;
1183
1184                 MFace *mf = mface;
1185                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1186                 memset(&attribs, 0, sizeof(attribs));
1187
1188                 GPU_vertex_setup(dm);
1189                 GPU_normal_setup(dm);
1190
1191                 if( !GPU_buffer_legacy(dm) ) {
1192                         for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
1193
1194                                 a = dm->drawObject->triangle_to_mface[i];
1195
1196                                 mface = mf + a;
1197                                 new_matnr = mface->mat_nr + 1;
1198
1199                                 if(new_matnr != matnr ) {
1200                                         numfaces = curface - start;
1201                                         if( numfaces > 0 ) {
1202
1203                                                 if( dodraw ) {
1204
1205                                                         if( numdata != 0 ) {
1206
1207                                                                 GPU_buffer_unlock(buffer);
1208
1209                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1210                                                         }
1211
1212                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1213
1214                                                         if( numdata != 0 ) {
1215
1216                                                                 GPU_buffer_free(buffer);
1217
1218                                                                 buffer = NULL;
1219                                                         }
1220
1221                                                 }
1222                                         }
1223                                         numdata = 0;
1224                                         start = curface;
1225                                         /* prevdraw = dodraw; */ /* UNUSED */
1226                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1227                                         if(dodraw) {
1228                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1229
1230                                                 if(attribs.totorco) {
1231                                                         datatypes[numdata].index = attribs.orco.glIndex;
1232                                                         datatypes[numdata].size = 3;
1233                                                         datatypes[numdata].type = GL_FLOAT;
1234                                                         numdata++;
1235                                                 }
1236                                                 for(b = 0; b < attribs.tottface; b++) {
1237                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1238                                                         datatypes[numdata].size = 2;
1239                                                         datatypes[numdata].type = GL_FLOAT;
1240                                                         numdata++;
1241                                                 }       
1242                                                 for(b = 0; b < attribs.totmcol; b++) {
1243                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1244                                                         datatypes[numdata].size = 4;
1245                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1246                                                         numdata++;
1247                                                 }       
1248                                                 if(attribs.tottang) {
1249                                                         datatypes[numdata].index = attribs.tang.glIndex;
1250                                                         datatypes[numdata].size = 4;
1251                                                         datatypes[numdata].type = GL_FLOAT;
1252                                                         numdata++;
1253                                                 }
1254                                                 if( numdata != 0 ) {
1255                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1256                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
1257                                                         if( buffer == NULL ) {
1258                                                                 GPU_buffer_unbind();
1259                                                                 dm->drawObject->legacy = 1;
1260                                                                 return;
1261                                                         }
1262                                                         varray = GPU_buffer_lock_stream(buffer);
1263                                                         if( varray == NULL ) {
1264                                                                 GPU_buffer_unbind();
1265                                                                 GPU_buffer_free(buffer);
1266                                                                 dm->drawObject->legacy = 1;
1267                                                                 return;
1268                                                         }
1269                                                 }
1270                                                 else {
1271                                                         /* if the buffer was set, dont use it again.
1272                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1273                                                         /* prevdraw= 0; */ /* UNUSED */
1274                                                         buffer= NULL;
1275                                                 }
1276                                         }
1277                                 }
1278                                 if(!dodraw) {
1279                                         continue;
1280                                 }
1281
1282                                 if( numdata != 0 ) {
1283                                         offset = 0;
1284                                         if(attribs.totorco) {
1285                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1286                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1287                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1288                                                 offset += sizeof(float)*3;
1289                                         }
1290                                         for(b = 0; b < attribs.tottface; b++) {
1291                                                 MTFace *tf = &attribs.tface[b].array[a];
1292                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1293                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1294
1295                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1296                                                 offset += sizeof(float)*2;
1297                                         }
1298                                         for(b = 0; b < attribs.totmcol; b++) {
1299                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1300                                                 GLubyte col[4];
1301                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1302                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1303                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1304                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1305                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1306                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1307                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1308                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1309                                                 offset += sizeof(unsigned char)*4;
1310                                         }       
1311                                         if(attribs.tottang) {
1312                                                 float *tang = attribs.tang.array[a*4 + 0];
1313                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1314                                                 tang = attribs.tang.array[a*4 + 1];
1315                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1316                                                 tang = attribs.tang.array[a*4 + 2];
1317                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1318                                                 offset += sizeof(float)*4;
1319                                         }
1320                                         (void)offset;
1321                                 }
1322                                 curface++;
1323                                 if(mface->v4) {
1324                                         if( numdata != 0 ) {
1325                                                 offset = 0;
1326                                                 if(attribs.totorco) {
1327                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1328                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1329                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1330                                                         offset += sizeof(float)*3;
1331                                                 }
1332                                                 for(b = 0; b < attribs.tottface; b++) {
1333                                                         MTFace *tf = &attribs.tface[b].array[a];
1334                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1335                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1336                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1337                                                         offset += sizeof(float)*2;
1338                                                 }
1339                                                 for(b = 0; b < attribs.totmcol; b++) {
1340                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1341                                                         GLubyte col[4];
1342                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1343                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1344                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1345                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1346                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1347                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1348                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1349                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1350                                                         offset += sizeof(unsigned char)*4;
1351                                                 }       
1352                                                 if(attribs.tottang) {
1353                                                         float *tang = attribs.tang.array[a*4 + 2];
1354                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1355                                                         tang = attribs.tang.array[a*4 + 3];
1356                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1357                                                         tang = attribs.tang.array[a*4 + 0];
1358                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1359                                                         offset += sizeof(float)*4;
1360                                                 }
1361                                                 (void)offset;
1362                                         }
1363                                         curface++;
1364                                         i++;
1365                                 }
1366                         }
1367                         numfaces = curface - start;
1368                         if( numfaces > 0 ) {
1369                                 if( dodraw ) {
1370                                         if( numdata != 0 ) {
1371                                                 GPU_buffer_unlock(buffer);
1372                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1373                                         }
1374                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1375                                 }
1376                         }
1377                         GPU_buffer_unbind();
1378                 }
1379                 GPU_buffer_free(buffer);
1380         }
1381
1382         glShadeModel(GL_FLAT);
1383 }
1384
1385 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1386 {
1387         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1388 }
1389
1390 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1391 {
1392         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1393         MVert *vert = cddm->mvert;
1394         MEdge *edge = cddm->medge;
1395         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1396
1397         glBegin(GL_LINES);
1398         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1399                 if(index) {
1400                         orig = *index++;
1401                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1402                 }
1403                 else
1404                         orig = i;
1405
1406                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1407                         glVertex3fv(vert[edge->v1].co);
1408                         glVertex3fv(vert[edge->v2].co);
1409                 }
1410         }
1411         glEnd();
1412 }
1413
1414 static void cdDM_foreachMappedVert(
1415                                                    DerivedMesh *dm,
1416                                                    void (*func)(void *userData, int index, float *co,
1417                                                                                 float *no_f, short *no_s),
1418                                                    void *userData)
1419 {
1420         MVert *mv = CDDM_get_verts(dm);
1421         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1422
1423         for(i = 0; i < dm->numVertData; i++, mv++) {
1424                 if(index) {
1425                         orig = *index++;
1426                         if(orig == ORIGINDEX_NONE) continue;
1427                         func(userData, orig, mv->co, NULL, mv->no);
1428                 }
1429                 else
1430                         func(userData, i, mv->co, NULL, mv->no);
1431         }
1432 }
1433
1434 static void cdDM_foreachMappedEdge(
1435                                                    DerivedMesh *dm,
1436                                                    void (*func)(void *userData, int index,
1437                                                                                 float *v0co, float *v1co),
1438                                                    void *userData)
1439 {
1440         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1441         MVert *mv = cddm->mvert;
1442         MEdge *med = cddm->medge;
1443         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1444
1445         for(i = 0; i < dm->numEdgeData; i++, med++) {
1446                 if (index) {
1447                         orig = *index++;
1448                         if(orig == ORIGINDEX_NONE) continue;
1449                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1450                 }
1451                 else
1452                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1453         }
1454 }
1455
1456 static void cdDM_foreachMappedFaceCenter(
1457                                                    DerivedMesh *dm,
1458                                                    void (*func)(void *userData, int index,
1459                                                                                 float *cent, float *no),
1460                                                    void *userData)
1461 {
1462         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1463         MVert *mv = cddm->mvert;
1464         MPoly *mf = cddm->mpoly;
1465         MLoop *ml = cddm->mloop;
1466         int i, j, orig, *index;
1467
1468         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1469         mf = cddm->mpoly;
1470         for(i = 0; i < dm->numPolyData; i++, mf++) {
1471                 float cent[3];
1472                 float no[3];
1473
1474                 if (index) {
1475                         orig = *index++;
1476                         if(orig == ORIGINDEX_NONE) continue;
1477                 } else
1478                         orig = i;
1479                 
1480                 ml = &cddm->mloop[mf->loopstart];
1481                 cent[0] = cent[1] = cent[2] = 0.0f;
1482                 for (j=0; j<mf->totloop; j++, ml++) {
1483                         add_v3_v3v3(cent, cent, mv[ml->v].co);
1484                 }
1485                 mul_v3_fl(cent, 1.0f / (float)j);
1486
1487                 ml = &cddm->mloop[mf->loopstart];
1488                 if (j > 3) {
1489                         normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1490                                        mv[(ml+2)->v].co, mv[(ml+3)->v].co);
1491                 } else {
1492                         normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1493                                        mv[(ml+2)->v].co);
1494                 }
1495
1496                 func(userData, orig, cent, no);
1497         }
1498
1499 }
1500
1501 static void cdDM_recalcTesselation(DerivedMesh *dm)
1502 {
1503         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1504
1505         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1506                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1507                 dm->numPolyData, 1, 0);
1508         
1509         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1510 }
1511
1512 /*ignores original poly origindex layer*/
1513 static void cdDM_recalcTesselation2(DerivedMesh *dm)
1514 {
1515         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1516
1517         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1518                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1519                 dm->numPolyData, 0, 0);
1520         
1521         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1522 }
1523
1524 void CDDM_recalc_tesselation(DerivedMesh *dm, int orig_use_polyorig)
1525 {
1526         if (orig_use_polyorig)
1527                 cdDM_recalcTesselation(dm);
1528         else
1529                 cdDM_recalcTesselation2(dm);
1530 }
1531
1532 static void cdDM_free_internal(CDDerivedMesh *cddm)
1533 {
1534         if(cddm->fmap) MEM_freeN(cddm->fmap);
1535         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1536 }
1537
1538 static void cdDM_release(DerivedMesh *dm)
1539 {
1540         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1541
1542         if (DM_release(dm)) {
1543                 cdDM_free_internal(cddm);
1544                 MEM_freeN(cddm);
1545         }
1546 }
1547
1548 int CDDM_Check(DerivedMesh *dm)
1549 {
1550         return dm && dm->getMinMax == cdDM_getMinMax;
1551 }
1552
1553 /**************** CDDM interface functions ****************/
1554 static CDDerivedMesh *cdDM_create(const char *desc)
1555 {
1556         CDDerivedMesh *cddm;
1557         DerivedMesh *dm;
1558
1559         cddm = MEM_callocN(sizeof(*cddm), desc);
1560         dm = &cddm->dm;
1561
1562         dm->getMinMax = cdDM_getMinMax;
1563
1564         dm->getNumVerts = cdDM_getNumVerts;
1565         dm->getNumEdges = cdDM_getNumEdges;
1566         dm->getNumTessFaces = cdDM_getNumTessFaces;
1567         dm->getNumFaces = cdDM_getNumFaces;
1568
1569         dm->getVert = cdDM_getVert;
1570         dm->getEdge = cdDM_getEdge;
1571         dm->getTessFace = cdDM_getFace;
1572         dm->copyVertArray = cdDM_copyVertArray;
1573         dm->copyEdgeArray = cdDM_copyEdgeArray;
1574         dm->copyTessFaceArray = cdDM_copyFaceArray;
1575         dm->copyLoopArray = cdDM_copyLoopArray;
1576         dm->copyPolyArray = cdDM_copyPolyArray;
1577         dm->getVertData = DM_get_vert_data;
1578         dm->getEdgeData = DM_get_edge_data;
1579         dm->getTessFaceData = DM_get_face_data;
1580         dm->getVertDataArray = DM_get_vert_data_layer;
1581         dm->getEdgeDataArray = DM_get_edge_data_layer;
1582         dm->getTessFaceDataArray = DM_get_tessface_data_layer;
1583         
1584         //doesn't work yet for all cases
1585         //dm->recalcTesselation = cdDM_recalcTesselation;
1586
1587         dm->getVertCos = cdDM_getVertCos;
1588         dm->getVertCo = cdDM_getVertCo;
1589         dm->getVertNo = cdDM_getVertNo;
1590
1591         dm->getPBVH = cdDM_getPBVH;
1592         dm->getFaceMap = cdDM_getFaceMap;
1593
1594         dm->drawVerts = cdDM_drawVerts;
1595
1596         dm->drawUVEdges = cdDM_drawUVEdges;
1597         dm->drawEdges = cdDM_drawEdges;
1598         dm->drawLooseEdges = cdDM_drawLooseEdges;
1599         dm->drawMappedEdges = cdDM_drawMappedEdges;
1600
1601         dm->drawFacesSolid = cdDM_drawFacesSolid;
1602         dm->drawFacesColored = cdDM_drawFacesColored;
1603         dm->drawFacesTex = cdDM_drawFacesTex;
1604         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1605         dm->drawMappedFaces = cdDM_drawMappedFaces;
1606         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1607         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1608
1609         dm->foreachMappedVert = cdDM_foreachMappedVert;
1610         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1611         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1612
1613         dm->release = cdDM_release;
1614
1615         return cddm;
1616 }
1617
1618 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
1619 {
1620         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1621         DerivedMesh *dm = &cddm->dm;
1622
1623         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
1624
1625         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1626         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1627         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1628         CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
1629
1630         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1631         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1632         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1633         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
1634         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
1635
1636         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1637         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1638         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1639         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1640         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1641
1642         return dm;
1643 }
1644
1645 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1646 {
1647         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1648         DerivedMesh *dm = &cddm->dm;
1649         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1650         int alloctype;
1651
1652         /* this does a referenced copy, with an exception for fluidsim */
1653
1654         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
1655                     mesh->totloop, mesh->totpoly);
1656
1657         dm->deformedOnly = 1;
1658
1659         alloctype= CD_REFERENCE;
1660
1661         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1662                                          mesh->totvert);
1663         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1664                                          mesh->totedge);
1665         CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype,
1666                                          mesh->totface);
1667         CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
1668                          mesh->totloop);
1669         CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
1670                          mesh->totpoly);
1671
1672         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1673         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1674         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1675         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1676         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1677
1678         if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
1679                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
1680
1681         return dm;
1682 }
1683
1684 static DerivedMesh *disabled__CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1685 {
1686         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1687                                    BLI_countlist(&em->edges),
1688                                    BLI_countlist(&em->faces), 0, 0);
1689         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1690         EditVert *eve;
1691         EditEdge *eed;
1692         EditFace *efa;
1693         MVert *mvert = cddm->mvert;
1694         MEdge *medge = cddm->medge;
1695         MFace *mface = cddm->mface;
1696         int i, *index;
1697
1698         dm->deformedOnly = 1;
1699
1700         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1701                                          CD_CALLOC, dm->numVertData);
1702         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1703                                          CD_CALLOC, dm->numEdgeData); */
1704         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1705                                          CD_CALLOC, dm->numFaceData);
1706         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1707                          CD_CALLOC, dm->numFaceData);
1708
1709         /* set eve->hash to vert index */
1710         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1711                 eve->tmp.l = i;
1712
1713         /* Need to be able to mark loose edges */
1714         for(eed = em->edges.first; eed; eed = eed->next) {
1715                 eed->f2 = 0;
1716         }
1717         for(efa = em->faces.first; efa; efa = efa->next) {
1718                 efa->e1->f2 = 1;
1719                 efa->e2->f2 = 1;
1720                 efa->e3->f2 = 1;
1721                 if(efa->e4) efa->e4->f2 = 1;
1722         }
1723
1724         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1725         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1726                 i++, eve = eve->next, index++) {
1727                 MVert *mv = &mvert[i];
1728
1729                 VECCOPY(mv->co, eve->co);
1730
1731                 normal_float_to_short_v3(mv->no, eve->no);
1732                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1733
1734                 mv->flag = 0;
1735
1736                 *index = i;
1737
1738                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1739         }
1740
1741         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1742         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1743                 i++, eed = eed->next, index++) {
1744                 MEdge *med = &medge[i];
1745
1746                 med->v1 = eed->v1->tmp.l;
1747                 med->v2 = eed->v2->tmp.l;
1748                 med->crease = (unsigned char) (eed->crease * 255.0f);
1749                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1750                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1751                 
1752                 if(eed->seam) med->flag |= ME_SEAM;
1753                 if(eed->sharp) med->flag |= ME_SHARP;
1754                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1755
1756                 *index = i;
1757
1758                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1759         }
1760
1761         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1762         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1763                 i++, efa = efa->next, index++) {
1764                 MFace *mf = &mface[i];
1765
1766                 mf->v1 = efa->v1->tmp.l;
1767                 mf->v2 = efa->v2->tmp.l;
1768                 mf->v3 = efa->v3->tmp.l;
1769                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1770                 mf->mat_nr = efa->mat_nr;
1771                 mf->flag = efa->flag;
1772
1773                 *index = i;
1774
1775                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1776                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1777         }
1778
1779         return dm;
1780 }
1781
1782 DerivedMesh *CDDM_from_curve(Object *ob)
1783 {
1784         return CDDM_from_curve_customDB(ob, &ob->disp);
1785 }
1786
1787 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1788 {
1789         DerivedMesh *dm;
1790         CDDerivedMesh *cddm;
1791         MVert *allvert;
1792         MEdge *alledge;
1793         MFace *allface;
1794         MLoop *allloop;
1795         MPoly *allpoly;
1796         int totvert, totedge, totface, totloop, totpoly;
1797
1798         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1799                 &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) {
1800                 /* Error initializing mdata. This often happens when curve is empty */
1801                 return CDDM_new(0, 0, 0, 0, 0);
1802         }
1803
1804         dm = CDDM_new(totvert, totedge, totface, totloop, totpoly);
1805         dm->deformedOnly = 1;
1806
1807         cddm = (CDDerivedMesh*)dm;
1808
1809         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1810         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1811         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1812         memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop));
1813         memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly));
1814
1815         MEM_freeN(allvert);
1816         MEM_freeN(alledge);
1817         MEM_freeN(allface);
1818         MEM_freeN(allloop);
1819         MEM_freeN(allpoly);
1820
1821         return dm;
1822 }
1823
1824 static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
1825                                           int cdindex, BMLoop *l3[3],
1826                                           int numCol, int numTex)
1827 {
1828         BMLoop *l;
1829         BMFace *f = l3[0]->f;
1830         MTFace *texface;
1831         MTexPoly *texpoly;
1832         MCol *mcol;
1833         MLoopCol *mloopcol;
1834         MLoopUV *mloopuv;
1835         int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
1836
1837         for(i=0; i < numTex; i++){
1838                 texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
1839                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
1840                 
1841                 texface->tpage = texpoly->tpage;
1842                 texface->flag = texpoly->flag;
1843                 texface->transp = texpoly->transp;
1844                 texface->mode = texpoly->mode;
1845                 texface->tile = texpoly->tile;
1846                 texface->unwrap = texpoly->unwrap;
1847         
1848                 for (j=0; j<3; j++) {
1849                         l = l3[j];
1850                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
1851                         texface->uv[j][0] = mloopuv->uv[0];
1852                         texface->uv[j][1] = mloopuv->uv[1];
1853                 }
1854         }
1855
1856         for(i=0; i < numCol; i++){
1857                 mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
1858                 
1859                 for (j=0; j<3; j++) {
1860                         l = l3[j];
1861                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
1862                         mcol[j].r = mloopcol->r;
1863                         mcol[j].g = mloopcol->g;
1864                         mcol[j].b = mloopcol->b;
1865                         mcol[j].a = mloopcol->a;
1866                 }
1867         }
1868
1869         if (hasWCol) {
1870                 mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
1871
1872                 for (j=0; j<3; j++) {
1873                         l = l3[j];
1874                         mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
1875                         mcol[j].r = mloopcol->r;
1876                         mcol[j].g = mloopcol->g;
1877                         mcol[j].b = mloopcol->b;
1878                         mcol[j].a = mloopcol->a;
1879                 }
1880         }
1881 }
1882
1883 DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps)
1884 {
1885         DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, 
1886                                em->tottri, em->bm->totloop, em->bm->totface);
1887         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1888         BMesh *bm = em->bm;
1889         BMIter iter, liter;
1890         BMVert *eve;
1891         BMEdge *eed;
1892         BMFace *efa;
1893         MVert *mvert = cddm->mvert;
1894         MEdge *medge = cddm->medge;
1895         MFace *mface = cddm->mface;
1896         MLoop *mloop = cddm->mloop;
1897         MPoly *mpoly = cddm->mpoly;
1898         int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
1899         int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
1900         int i, j, *index, add_orig;
1901         int has_crease, has_edge_bweight, has_vert_bweight;
1902         int flag;
1903         
1904         has_edge_bweight = CustomData_has_layer(&em->bm->edata, CD_BWEIGHT);
1905         has_vert_bweight = CustomData_has_layer(&em->bm->vdata, CD_BWEIGHT);
1906         has_crease = CustomData_has_layer(&em->bm->edata, CD_CREASE);
1907         
1908         dm->deformedOnly = 1;
1909         
1910         /*don't add origindex layer if one already exists*/
1911         add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
1912
1913         flag = use_mdisps ? CD_MASK_DERIVEDMESH|CD_MASK_MDISPS : CD_MASK_DERIVEDMESH;
1914         
1915         /*don't process shapekeys, we only feed them through the modifier stack as needed,
1916       e.g. for applying modifiers or the like*/
1917         flag &= ~CD_SHAPEKEY;
1918         CustomData_merge(&em->bm->vdata, &dm->vertData, flag,
1919                          CD_CALLOC, dm->numVertData);
1920         CustomData_merge(&em->bm->edata, &dm->edgeData, flag,
1921                          CD_CALLOC, dm->numEdgeData);
1922         CustomData_merge(&em->bm->ldata, &dm->loopData, flag,
1923                          CD_CALLOC, dm->numLoopData);
1924         CustomData_merge(&em->bm->pdata, &dm->polyData, flag,
1925                          CD_CALLOC, dm->numPolyData);
1926         
1927         /*add tesselation mface layers*/
1928         CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
1929
1930         /* set vert index */
1931         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1932         for (i=0; eve; eve=BMIter_Step(&iter), i++)
1933                 BM_SetIndex(eve, i);
1934
1935         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1936
1937         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1938         for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
1939                 MVert *mv = &mvert[i];
1940
1941                 VECCOPY(mv->co, eve->co);
1942
1943                 BM_SetIndex(eve, i);
1944
1945                 mv->no[0] = eve->no[0] * 32767.0;
1946                 mv->no[1] = eve->no[1] * 32767.0;
1947                 mv->no[2] = eve->no[2] * 32767.0;
1948
1949                 mv->flag = BMFlags_To_MEFlags(eve);
1950
1951                 if (has_vert_bweight)
1952                         mv->bweight = (unsigned char)(BM_GetCDf(&bm->vdata, eve, CD_BWEIGHT)*255.0f);
1953
1954                 if (add_orig) *index = i;
1955
1956                 CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
1957         }
1958
1959         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1960         eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1961         for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
1962                 MEdge *med = &medge[i];
1963
1964                 BM_SetIndex(eed, i);
1965
1966                 med->v1 = BM_GetIndex(eed->v1);
1967                 med->v2 = BM_GetIndex(eed->v2);
1968                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1969
1970                 if (has_crease)
1971                         med->crease = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_CREASE)*255.0f);
1972                 if (has_edge_bweight)
1973                         med->bweight = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_BWEIGHT)*255.0f);
1974                 
1975                 med->flag = BMFlags_To_MEFlags(eed);
1976
1977                 CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
1978                 if (add_orig) *index = i;
1979         }
1980
1981         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
1982         for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
1983                 BM_SetIndex(efa, i);
1984         }
1985
1986         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1987         for(i = 0; i < dm->numFaceData; i++, index++) {
1988                 MFace *mf = &mface[i];
1989                 BMLoop **l = em->looptris[i];
1990                 efa = l[0]->f;
1991
1992                 mf->v1 = BM_GetIndex(l[0]->v);
1993                 mf->v2 = BM_GetIndex(l[1]->v);
1994                 mf->v3 = BM_GetIndex(l[2]->v);
1995                 mf->v4 = 0;
1996                 mf->mat_nr = efa->mat_nr;
1997                 mf->flag = BMFlags_To_MEFlags(efa);
1998                 
1999                 *index = add_orig ? BM_GetIndex(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
2000
2001                 loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
2002                 test_index_face(mf, &dm->faceData, i, 3);
2003         }
2004         
2005         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
2006         j = 0;
2007         efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
2008         for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
2009                 BMLoop *l;
2010                 MPoly *mp = &mpoly[i];
2011
2012                 mp->totloop = efa->len;
2013                 mp->flag = BMFlags_To_MEFlags(efa);
2014                 mp->loopstart = j;
2015                 mp->mat_nr = efa->mat_nr;
2016                 
2017                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
2018                         mloop->v = BM_GetIndex(l->v);
2019                         mloop->e = BM_GetIndex(l->e);
2020                         CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
2021
2022                         j++;
2023                         mloop++;
2024                 }
2025
2026                 CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
2027
2028                 if (add_orig) *index = i;
2029         }
2030
2031         return dm;
2032 }
2033
2034 DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
2035 {
2036         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
2037         DerivedMesh *dm = &cddm->dm;
2038         int numVerts = source->numVertData;
2039         int numEdges = source->numEdgeData;
2040         int numFaces = source->numFaceData;
2041         int numLoops = source->numLoopData;
2042         int numPolys = source->numPolyData;
2043
2044         /* ensure these are created if they are made on demand */
2045         source->getVertDataArray(source, CD_ORIGINDEX);
2046         source->getEdgeDataArray(source, CD_ORIGINDEX);
2047         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2048
2049         /* this initializes dm, and copies all non mvert/medge/mface layers */
2050         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
2051                 numLoops, numPolys);
2052         dm->deformedOnly = source->deformedOnly;
2053
2054         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
2055         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
2056         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
2057
2058         /* now add mvert/medge/mface layers */
2059         cddm->mvert = source->dupVertArray(source);
2060         cddm->medge = source->dupEdgeArray(source);
2061         cddm->mface = source->dupTessFaceArray(source);
2062
2063         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
2064         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
2065         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
2066         
2067         if (!faces_from_tessfaces)
2068                 DM_DupPolys(source, dm);
2069         else
2070                 CDDM_tessfaces_to_faces(dm);
2071
2072         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2073         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2074         
2075         cdDM_recalcTesselation((DerivedMesh *)cddm);
2076         
2077         return dm;
2078 }
2079
2080 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
2081  * relationship betwen mesh data this needs to be set by the caller. */
2082 DerivedMesh *CDDM_from_template(DerivedMesh *source,
2083                                 int numVerts, int numEdges, int numFaces,
2084                                                                 int numLoops, int numPolys)
2085 {
2086         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
2087         DerivedMesh *dm = &cddm->dm;
2088
2089         /* ensure these are created if they are made on demand */
2090         source->getVertDataArray(source, CD_ORIGINDEX);
2091         source->getEdgeDataArray(source, CD_ORIGINDEX);
2092         source->getTessFaceDataArray(source, CD_ORIGINDEX);
2093
2094         /* this does a copy of all non mvert/medge/mface layers */
2095         DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
2096
2097         /* now add mvert/medge/mface layers */
2098         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
2099         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2100         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
2101         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
2102         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
2103
2104         if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
2105                 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
2106         if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
2107                 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2108         if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
2109                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
2110
2111         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
2112         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2113         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
2114         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
2115         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
2116
2117         return dm;
2118 }
2119
2120 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
2121 {
2122         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2123         MVert *vert;
2124         int i;
2125
2126         /* this will just return the pointer if it wasn't a referenced layer */
2127         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2128         cddm->mvert = vert;
2129
2130         for(i = 0; i < dm->numVertData; ++i, ++vert)
2131                 VECCOPY(vert->co, vertCoords[i]);
2132 }
2133
2134 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
2135 {
2136         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2137         MVert *vert;
2138         int i;
2139
2140         /* this will just return the pointer if it wasn't a referenced layer */
2141         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2142         cddm->mvert = vert;
2143
2144         for(i = 0; i < dm->numVertData; ++i, ++vert)
2145                 copy_v3_v3_short(vert->no, vertNormals[i]);
2146 }
2147
2148 void CDDM_calc_normals(DerivedMesh *dm)
2149 {
2150         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2151         float (*face_nors)[3] = NULL;
2152         
2153         if(dm->numVertData == 0) return;
2154
2155         /* we don't want to overwrite any referenced layers */
2156         cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
2157         
2158         /*set tesselation origindex values to map to poly indices, rather then poly
2159           poly origindex values*/
2160         cdDM_recalcTesselation2(dm);
2161         
2162         face_nors = MEM_mallocN(sizeof(float)*3*dm->numFaceData, "face_nors");
2163         
2164         /* calculate face normals */
2165         mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), 
2166                                           dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numFaceData, 
2167                                           CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors);
2168         
2169         /*restore tesselation origindex indices to poly origindex indices*/
2170         cdDM_recalcTesselation(dm);
2171
2172         CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, 
2173                 face_nors, dm->numFaceData);
2174 }
2175
2176 #if 1
2177 /*merge verts
2178  
2179   vtargetmap is a table that maps vertices to target vertices.  a value of -1
2180   indicates a vertex is a target, and is to be kept.
2181   
2182   this frees dm, and returns a new one.
2183   
2184   this is a really horribly written function.  ger. - joeedh
2185
2186  */
2187 DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap)
2188 {
2189         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2190         CDDerivedMesh *cddm2 = NULL;
2191         MVert *mv, *mvert = NULL;
2192         BLI_array_declare(mvert);
2193         MEdge *me, *medge = NULL;
2194         BLI_array_declare(medge);
2195         MPoly *mp, *mpoly = NULL;
2196         BLI_array_declare(mpoly);
2197         MLoop *ml, *mloop = NULL;
2198         BLI_array_declare(mloop);
2199         EdgeHash *ehash = BLI_edgehash_new();
2200         int *newv = NULL, *newe = NULL, *newl = NULL;
2201         int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
2202         BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
2203         int i, j, c, totloop, totpoly;
2204         
2205         totloop = dm->numLoopData;
2206         totpoly = dm->numPolyData;
2207         
2208         newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts");
2209         newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts");
2210         newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts");
2211         
2212         /*fill newl with destination vertex indices*/
2213         mv = cddm->mvert;
2214         c = 0;
2215         for (i=0; i<dm->numVertData; i++, mv++) {
2216                 if (vtargetmap[i] == -1) {
2217                         BLI_array_append(oldv, i);
2218                         newv[i] = c++;
2219                         BLI_array_append(mvert, *mv);
2220                 }
2221         }
2222         
2223         /*now link target vertices to destination indices*/
2224         for (i=0; i<dm->numVertData; i++) {
2225                 if (vtargetmap[i] != -1) {
2226                         newv[i] = newv[vtargetmap[i]];
2227                 }
2228         }
2229         
2230         /*find-replace merged vertices with target vertices*/   
2231         ml = cddm->mloop;
2232         c = 0;
2233         for (i=0; i<totloop; i++, ml++) {
2234                 if (ml->v == -1)
2235                         continue;
2236                 
2237                 if (vtargetmap[ml->v] != -1)
2238                         ml->v = vtargetmap[ml->v];
2239         }
2240         
2241         /*now go through and fix edges and faces*/
2242         me = cddm->medge;
2243         c = 0;
2244         for (i=0; i<dm->numEdgeData; i++, me++) {
2245                 int v1, v2;
2246                 
2247                 if (me->v1 == me->v2) {
2248                         newe[i] = -1;
2249                         continue;
2250                 }
2251                 
2252                 if (vtargetmap[me->v1] != -1)
2253                         v1 = vtargetmap[me->v1];
2254                 else
2255                         v1 = me->v1;
2256                 
2257                 if (vtargetmap[me->v2] != -1)
2258                         v2 = vtargetmap[me->v2];
2259                 else
2260                         v2 = me->v2;
2261                 
2262                 if (BLI_edgehash_haskey(ehash, v1, v2)) {
2263                         newe[i] = GET_INT_FROM_POINTER(BLI_edgehash_lookup(ehash, v1, v2));
2264                 } else {
2265                         BLI_array_append(olde, i);
2266                         newe[i] = c;
2267                         BLI_array_append(medge, *me);
2268                         BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c));
2269                         c++;
2270                 }
2271         }
2272         
2273         mp = cddm->mpoly;
2274         for (i=0; i<totpoly; i++, mp++) {
2275                 MPoly *mp2;
2276                 
2277                 ml = cddm->mloop + mp->loopstart;
2278                 
2279                 c = 0;
2280                 for (j=0; j<mp->totloop; j++, ml++) {
2281                         if (ml->v == -1)
2282                                 continue;
2283                         
2284                         me = cddm->medge + ml->e;
2285                         if (me->v1 != me->v2) {
2286                                 BLI_array_append(oldl, j+mp->loopstart);
2287                                 BLI_array_append(mloop, *ml);
2288                                 newl[j+mp->loopstart] = BLI_array_count(mloop)-1;
2289                                 c++;
2290                         }
2291                 }
2292                 
2293                 if (!c)
2294                         continue;
2295                 
2296                 mp2 = BLI_array_append(mpoly, *mp);
2297                 mp2->totloop = c;
2298                 mp2->loopstart = BLI_array_count(mloop) - c;
2299                 
2300                 BLI_array_append(oldp, i);
2301         }
2302         
2303         /*create new cddm*/     
2304         cddm2 = (CDDerivedMesh*) CDDM_from_template((DerivedMesh*)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
2305         
2306         /*update edge indices and copy customdata*/
2307         me = medge;
2308         for (i=0; i<cddm2->dm.numEdgeData; i++, me++) {
2309                 if (newv[me->v1] != -1)
2310                         me->v1 = newv[me->v1];
2311                 if (newv[me->v2] != -1)
2312                         me->v2 = newv[me->v2];
2313                 
2314                 CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1);
2315         }
2316         
2317         /*update loop indices and copy customdata*/
2318         ml = mloop;
2319         for (i=0; i<cddm2->dm.numLoopData; i++, ml++) {
2320                 if (newe[ml->e] != -1)
2321                         ml->e = newe[ml->e];
2322                 if (newv[ml->v] != -1)
2323                         ml->v = newv[ml->v];
2324                         
2325                 CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
2326         }
2327         
2328         /*copy vertex customdata*/      
2329         mv = mvert;
2330         for (i=0; i<cddm2->dm.numVertData; i++, mv++) {
2331                 CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1);
2332         }
2333         
2334         /*copy poly customdata*/
2335         mp = mpoly;
2336         for (i=0; i<cddm2->dm.numPolyData; i++, mp++) {
2337                 CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1);
2338         }
2339         
2340         /*copy over data.  CustomData_add_layer can do this, need to look it up.*/
2341         memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert));
2342         memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge));
2343         memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop));
2344         memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
2345         BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
2346
2347         CDDM_recalc_tesselation((DerivedMesh*)cddm2, 1);
2348         
2349         if (newv) 
2350                 MEM_freeN(newv); 
2351         if (newe)
2352                 MEM_freeN(newe); 
2353         if (newl)
2354                 MEM_freeN(newl);
2355         if (oldv) 
2356                 MEM_freeN(oldv); 
2357         if (olde) 
2358                 MEM_freeN(olde); 
2359         if (oldl) 
2360                 MEM_freeN(oldl); 
2361         if (oldp) 
2362                 MEM_freeN(oldp);
2363         if (ehash)
2364                 BLI_edgehash_free(ehash, NULL);
2365
2366         /*free old derivedmesh*/
2367         dm->needsFree = 1;
2368         dm->release(dm);
2369         
2370         return (DerivedMesh*)cddm2;
2371 }
2372 #endif
2373
2374 void CDDM_calc_edges(DerivedMesh *dm)
2375 {
2376         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2377         CustomData edgeData;
2378         EdgeHashIterator *ehi;
2379         MFace *mf = cddm->mface;
2380         MEdge *med;
2381         EdgeHash *eh = BLI_edgehash_new();
2382         int i, *index, numEdges, maxFaces = dm->numFaceData;
2383
2384         for (i = 0; i < maxFaces; i++, mf++) {
2385                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
2386                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
2387                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
2388                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
2389                 
2390                 if (mf->v4) {
2391                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
2392                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
2393                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
2394                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
2395                 } else {
2396                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
2397                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
2398                 }
2399         }
2400
2401         numEdges = BLI_edgehash_size(eh);
2402
2403         /* write new edges into a temporary CustomData */
2404         memset(&edgeData, 0, sizeof(edgeData));
2405         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2406         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2407
2408         ehi = BLI_edgehashIterator_new(eh);
2409         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2410         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2411         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2412                 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2413                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2414
2415                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2416                 *index = ORIGINDEX_NONE;
2417         }
2418         BLI_edgehashIterator_free(ehi);
2419
2420         /* free old CustomData and assign new one */
2421         CustomData_free(&dm->edgeData, dm->numEdgeData);
2422         dm->edgeData = edgeData;
2423         dm->numEdgeData = numEdges;
2424
2425         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2426
2427         BLI_edgehash_free(eh, NULL);
2428 }
2429
2430
2431 void CDDM_calc_edges_poly(DerivedMesh *dm)
2432 {
2433         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2434         CustomData edgeData;
2435         EdgeHashIterator *ehi;
2436         MPoly *mp = cddm->mpoly;
2437         MLoop *ml;
2438         MEdge *med;
2439         EdgeHash *eh = BLI_edgehash_new();
2440         int v1, v2;
2441         int *eindex;
2442         int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
2443
2444         eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
2445
2446         med = cddm->medge;
2447         if (med) {
2448                 for (i=0; i < numEdges; i++, med++) {
2449                         BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
2450                 }
2451         }
2452
2453         for (i=0; i < maxFaces; i++, mp++) {
2454                 ml = cddm->mloop + mp->loopstart;
2455                 for (j=0; j<mp->totloop; j++, ml++) {
2456                         v1 = ml->v;
2457                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2458                         if (!BLI_edgehash_haskey(eh, v1, v2)) {
2459                                 BLI_edgehash_insert(eh, v1, v2, NULL);
2460                         }
2461                 }
2462         }
2463
2464         k = numEdges;
2465         numEdges = BLI_edgehash_size(eh);
2466
2467         /* write new edges into a temporary CustomData */
2468         memset(&edgeData, 0, sizeof(edgeData));
2469         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
2470         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
2471
2472         ehi = BLI_edgehashIterator_new(eh);
2473         med = CustomData_get_layer(&edgeData, CD_MEDGE);
2474         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
2475         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
2476             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
2477                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
2478                 j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
2479
2480                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
2481                 *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
2482
2483                 BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
2484         }
2485         BLI_edgehashIterator_free(ehi);
2486
2487         /* free old CustomData and assign new one */
2488         CustomData_free(&dm->edgeData, dm->numEdgeData);
2489         dm->edgeData = edgeData;
2490         dm->numEdgeData = numEdges;
2491
2492         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
2493
2494         mp = cddm->mpoly;
2495         for (i=0; i < maxFaces; i++, mp++) {
2496                 ml = cddm->mloop + mp->loopstart;
2497                 for (j=0; j<mp->totloop; j++, ml++) {
2498                         v1 = ml->v;
2499                         v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
2500                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
2501                 }
2502         }
2503
2504         BLI_edgehash_free(eh, NULL);
2505 }
2506
2507 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
2508 {
2509         if (numVerts < dm->numVertData)
2510                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
2511
2512         dm->numVertData = numVerts;
2513 }
2514
2515 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
2516 {
2517         if (numEdges < dm->numEdgeData)
2518                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
2519
2520         dm->numEdgeData = numEdges;
2521 }
2522
2523 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
2524 {
2525         if (numFaces < dm->numFaceData)
2526                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
2527
2528         dm->numFaceData = numFaces;
2529 }
2530
2531 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
2532 {
2533         return &((CDDerivedMesh*)dm)->mvert[index];
2534 }
2535
2536 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
2537 {
2538         return &((CDDerivedMesh*)dm)->medge[index];
2539 }
2540
2541 MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
2542 {
2543         return &((CDDerivedMesh*)dm)->mface[index];
2544 }
2545
2546 MVert *CDDM_get_verts(DerivedMesh *dm)
2547 {
2548         return ((CDDerivedMesh*)dm)->mvert;
2549 }
2550
2551 MEdge *CDDM_get_edges(DerivedMesh *dm)
2552 {
2553         return ((CDDerivedMesh*)dm)->medge;
2554 }
2555
2556 MFace *CDDM_get_tessfaces(DerivedMesh *dm)
2557 {
2558         return ((CDDerivedMesh*)dm)->mface;
2559 }
2560
2561 MLoop *CDDM_get_loops(DerivedMesh *dm)
2562 {
2563         return ((CDDerivedMesh*)dm)->mloop;
2564 }
2565
2566 MPoly *CDDM_get_polys(DerivedMesh *dm)
2567 {
2568         return ((CDDerivedMesh*)dm)->mpoly;
2569 }
2570
2571 void CDDM_tessfaces_to_faces(DerivedMesh *dm)
2572 {
2573         /*converts mfaces to mpolys/mloops*/
2574         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2575         MFace *mf;
2576         MEdge *me;
2577         MLoop *ml;
2578         MPoly *mp;
2579         EdgeHash *eh = BLI_edgehash_new();
2580         int i, l, totloop, *index1, *index2;
2581         
2582         /*ensure we have all the edges we need*/
2583         CDDM_calc_edges(dm);
2584
2585         /*build edge hash*/
2586         me = cddm->medge;
2587         for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
2588                 BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
2589         }
2590
2591         mf = cddm->mface;
2592         totloop = 0;
2593         for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
2594                 totloop += mf->v4 ? 4 : 3;
2595         }
2596
2597         CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
2598         CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
2599         
2600         cddm->dm.numLoopData = totloop;
2601         cddm->dm.numPolyData = cddm->dm.numFaceData;
2602
2603         if (!totloop) return;
2604
2605         cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
2606         cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
2607         
2608         CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
2609         CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
2610         CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, 
2611                 CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData);
2612
2613         index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
2614         index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
2615
2616         mf = cddm->mface;
2617         mp = cddm->mpoly;
2618         ml = cddm->mloop;
2619         l = 0;
2620         for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
2621                 mp->flag = mf->flag;
2622                 mp->loopstart = l;
2623                 mp->mat_nr = mf->mat_nr;
2624                 mp->totloop = mf->v4 ? 4 : 3;
2625                 
2626                 ml->v = mf->v1;
2627                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
2628                 ml++, l++;
2629
2630                 ml->v = mf->v2;
2631                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
2632                 ml++, l++;
2633
2634                 ml->v = mf->v3;
2635                 ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
2636                 ml++, l++;
2637
2638                 if (mf->v4) {
2639                         ml->v = mf->v4;
2640                         ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
2641                         ml++, l++;
2642                 }
2643
2644         }
2645
2646         BLI_edgehash_free(eh, NULL);
2647 }
2648
2649 void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
2650 {
2651         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2652         
2653         if (!CustomData_has_layer(&dm->vertData, CD_MVERT))
2654                 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData);
2655                                 
2656         cddm->mvert = mvert;
2657 }
2658
2659 void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
2660 {
2661         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2662
2663         if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE))
2664                 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData);
2665
2666         cddm->medge = medge;
2667 }
2668
2669 void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
2670 {
2671         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
2672
2673         if (!CustomData_has_layer(&dm->faceData, CD_MFACE))
2674                 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numFaceData);
2675
2676         cddm->mface = mface;
2677 }