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