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