svn merge ^/trunk/blender -r40372:40379
[blender.git] / source / blender / blenkernel / intern / cdderivedmesh.c
1  /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2006 Blender Foundation.
21 * All rights reserved.
22 *
23 * The Original Code is: all of this file.
24 *
25 * Contributor(s): Ben Batt <benbatt@gmail.com>
26 *
27 * ***** END GPL LICENSE BLOCK *****
28 *
29 * Implementation of CDDerivedMesh.
30 *
31 * BKE_cdderivedmesh.h contains the function prototypes for this file.
32 *
33 */
34
35 /** \file blender/blenkernel/intern/cdderivedmesh.c
36  *  \ingroup bke
37  */
38  
39 #include "GL/glew.h"
40
41 #include "BKE_cdderivedmesh.h"
42 #include "BKE_global.h"
43 #include "BKE_mesh.h"
44 #include "BKE_paint.h"
45 #include "BKE_utildefines.h"
46 #include "BKE_tessmesh.h"
47
48 #include "BLI_editVert.h"
49 #include "BLI_scanfill.h"
50 #include "BLI_math.h"
51 #include "BLI_blenlib.h"
52 #include "BLI_edgehash.h"
53 #include "BLI_editVert.h"
54 #include "BLI_math.h"
55 #include "BLI_pbvh.h"
56 #include "BLI_array.h"
57 #include "BLI_smallhash.h"
58 #include "BLI_utildefines.h"
59
60 #include "BKE_cdderivedmesh.h"
61 #include "BKE_global.h"
62 #include "BKE_mesh.h"
63 #include "BKE_paint.h"
64
65
66 #include "DNA_meshdata_types.h"
67 #include "DNA_object_types.h"
68 #include "DNA_curve_types.h" /* for Curve */
69
70 #include "MEM_guardedalloc.h"
71
72 #include "GPU_buffers.h"
73 #include "GPU_draw.h"
74 #include "GPU_extensions.h"
75 #include "GPU_material.h"
76
77 #include <string.h>
78 #include <limits.h>
79 #include <math.h>
80
81 typedef struct {
82         DerivedMesh dm;
83
84         /* these point to data in the DerivedMesh custom data layers,
85            they are only here for efficiency and convenience **/
86         MVert *mvert;
87         MEdge *medge;
88         MFace *mface;
89         MLoop *mloop;
90         MPoly *mpoly;
91
92         /* Cached */
93         struct PBVH *pbvh;
94         int pbvh_draw;
95
96         /* Mesh connectivity */
97         struct ListBase *fmap;
98         struct IndexNode *fmap_mem;
99 } CDDerivedMesh;
100
101 /**************** DerivedMesh interface functions ****************/
102 static int cdDM_getNumVerts(DerivedMesh *dm)
103 {
104         return dm->numVertData;
105 }
106
107 static int cdDM_getNumEdges(DerivedMesh *dm)
108 {
109         return dm->numEdgeData;
110 }
111
112 static int cdDM_getNumTessFaces(DerivedMesh *dm)
113 {
114         return dm->numFaceData;
115 }
116
117 static int cdDM_getNumFaces(DerivedMesh *dm)
118 {
119         return dm->numPolyData;
120 }
121
122 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
123 {
124         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
125         *vert_r = cddm->mvert[index];
126 }
127
128 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
129 {
130         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
131         *edge_r = cddm->medge[index];
132 }
133
134 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
135 {
136         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
137         *face_r = cddm->mface[index];
138 }
139
140 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
141 {
142         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
143         memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
144 }
145
146 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
147 {
148         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
149         memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
150 }
151
152 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
153 {
154         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
155         memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
156 }
157
158 static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
159 {
160         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
161         memcpy(loop_r, cddm->mloop, sizeof(*loop_r) * dm->numLoopData);
162 }
163
164 static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
165 {
166         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
167         memcpy(poly_r, cddm->mpoly, sizeof(*poly_r) * dm->numPolyData);
168 }
169
170 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
171 {
172         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
173         int i;
174
175         if (dm->numVertData) {
176                 for (i=0; i<dm->numVertData; i++) {
177                         DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
178                 }
179         } else {
180                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
181         }
182 }
183
184 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
185 {
186         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
187
188         VECCOPY(co_r, cddm->mvert[index].co);
189 }
190
191 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
192 {
193         MVert *mv = CDDM_get_verts(dm);
194         int i;
195
196         for(i = 0; i < dm->numVertData; i++, mv++)
197                 VECCOPY(cos_r[i], mv->co);
198 }
199
200 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
201 {
202         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
203         normal_short_to_float_v3(no_r, cddm->mvert[index].no);
204 }
205
206 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
207 {
208         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
209
210         if(!cddm->fmap && ob->type == OB_MESH) {
211                 Mesh *me= ob->data;
212
213                 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
214                                          me->totvert, me->totface);
215         }
216
217         return cddm->fmap;
218 }
219
220 static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
221 {
222         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
223         Mesh *me= ob->data;
224         int deformed= 0;
225
226         /* active modifiers means extra deformation, which can't be handled correct
227            on bith of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
228            stuff and show final DerivedMesh so user would see actual object shape */
229         deformed|= ob->sculpt->modifiers_active;
230
231         /* as in case with modifiers, we can't synchronize deformation made against
232            PBVH and non-locked keyblock, so also use PBVH only for brushes and
233            final DM to give final result to user */
234         deformed|= ob->sculpt->kb && (ob->shapeflag&OB_SHAPE_LOCK) == 0;
235
236         if(deformed)
237                 return 0;
238
239         return cddm->mvert == me->mvert || ob->sculpt->kb;
240 }
241
242 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
243 {
244         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
245
246         if(!ob) {
247                 cddm->pbvh= NULL;
248                 return NULL;
249         }
250
251         if(!ob->sculpt)
252                 return NULL;
253         if(ob->sculpt->pbvh) {
254                 cddm->pbvh= ob->sculpt->pbvh;
255                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
256         }
257
258         /* always build pbvh from original mesh, and only use it for drawing if
259            this derivedmesh is just original mesh. it's the multires subsurf dm
260            that this is actually for, to support a pbvh on a modified mesh */
261         if(!cddm->pbvh && ob->type == OB_MESH) {
262                 SculptSession *ss= ob->sculpt;
263                 Mesh *me= ob->data;
264                 cddm->pbvh = BLI_pbvh_new();
265                 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
266                 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
267                                    me->totface, me->totvert);
268
269                 if(ss->modifiers_active && ob->derivedDeform) {
270                         DerivedMesh *deformdm= ob->derivedDeform;
271                         float (*vertCos)[3];
272                         int totvert;
273
274                         totvert= deformdm->getNumVerts(deformdm);
275                         vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
276                         deformdm->getVertCos(deformdm, vertCos);
277                         BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
278                         MEM_freeN(vertCos);
279                 }
280         }
281
282         return cddm->pbvh;
283 }
284
285 /* update vertex normals so that drawing smooth faces works during sculpt
286    TODO: proper fix is to support the pbvh in all drawing modes */
287 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
288 {
289         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
290         float (*face_nors)[3];
291
292         if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
293                 return;
294
295         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
296
297         BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
298 }
299
300 static void cdDM_drawVerts(DerivedMesh *dm)
301 {
302         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
303         MVert *mv = cddm->mvert;
304         int i;
305
306         if( GPU_buffer_legacy(dm) ) {
307                 glBegin(GL_POINTS);
308                 for(i = 0; i < dm->numVertData; i++, mv++)
309                         glVertex3fv(mv->co);
310                 glEnd();
311         }
312         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
313                 GPU_vertex_setup(dm);
314                 if( !GPU_buffer_legacy(dm) ) {
315                         if(dm->drawObject->tot_triangle_point)
316                                 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
317                         else
318                                 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
319                 }
320                 GPU_buffer_unbind();
321         }
322 }
323
324 static void cdDM_drawUVEdges(DerivedMesh *dm)
325 {
326         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
327         MFace *mf = cddm->mface;
328         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
329         int i;
330
331         if(mf) {
332                 if( GPU_buffer_legacy(dm) ) {
333                         glBegin(GL_LINES);
334                         for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
335                                 if(!(mf->flag&ME_HIDE)) {
336                                         glVertex2fv(tf->uv[0]);
337                                         glVertex2fv(tf->uv[1]);
338
339                                         glVertex2fv(tf->uv[1]);
340                                         glVertex2fv(tf->uv[2]);
341
342                                         if(!mf->v4) {
343                                                 glVertex2fv(tf->uv[2]);
344                                                 glVertex2fv(tf->uv[0]);
345                                         } else {
346                                                 glVertex2fv(tf->uv[2]);
347                                                 glVertex2fv(tf->uv[3]);
348
349                                                 glVertex2fv(tf->uv[3]);
350                                                 glVertex2fv(tf->uv[0]);
351                                         }
352                                 }
353                         }
354                         glEnd();
355                 }
356                 else {
357                         int prevstart = 0;
358                         int prevdraw = 1;
359                         int draw = 1;
360                         int curpos = 0;
361
362                         GPU_uvedge_setup(dm);
363                         if( !GPU_buffer_legacy(dm) ) {
364                                 for(i = 0; i < dm->numFaceData; i++, mf++) {
365                                         if(!(mf->flag&ME_HIDE)) {
366                                                 draw = 1;
367                                         } 
368                                         else {
369                                                 draw = 0;
370                                         }
371                                         if( prevdraw != draw ) {
372                                                 if( prevdraw > 0 && (curpos-prevstart) > 0) {
373                                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
374                                                 }
375                                                 prevstart = curpos;
376                                         }
377                                         if( mf->v4 ) {
378                                                 curpos += 8;
379                                         }
380                                         else {
381                                                 curpos += 6;
382                                         }
383                                         prevdraw = draw;
384                                 }
385                                 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
386                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
387                                 }
388                         }
389                         GPU_buffer_unbind();
390                 }
391         }
392 }
393
394 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges)
395 {
396         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
397         MVert *mvert = cddm->mvert;
398         MEdge *medge = cddm->medge;
399         int i;
400         
401         if( GPU_buffer_legacy(dm) ) {
402                 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
403                 glBegin(GL_LINES);
404                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
405                         if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
406                            && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
407                                 glVertex3fv(mvert[medge->v1].co);
408                                 glVertex3fv(mvert[medge->v2].co);
409                         }
410                 }
411                 glEnd();
412         }
413         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
414                 int prevstart = 0;
415                 int prevdraw = 1;
416                 int draw = 1;
417
418                 GPU_edge_setup(dm);
419                 if( !GPU_buffer_legacy(dm) ) {
420                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
421                                 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
422                                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
423                                         draw = 1;
424                                 } 
425                                 else {
426                                         draw = 0;
427                                 }
428                                 if( prevdraw != draw ) {
429                                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
430                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
431                                         }
432                                         prevstart = i;
433                                 }
434                                 prevdraw = draw;
435                         }
436                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
437                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
438                         }
439                 }
440                 GPU_buffer_unbind();
441         }
442 }
443
444 static void cdDM_drawLooseEdges(DerivedMesh *dm)
445 {
446         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
447         MVert *mvert = cddm->mvert;
448         MEdge *medge = cddm->medge;
449         int i;
450
451         if( GPU_buffer_legacy(dm) ) {
452                 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
453                 glBegin(GL_LINES);
454                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
455                         if(medge->flag&ME_LOOSEEDGE) {
456                                 glVertex3fv(mvert[medge->v1].co);
457                                 glVertex3fv(mvert[medge->v2].co);
458                         }
459                 }
460                 glEnd();
461         }
462         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
463                 int prevstart = 0;
464                 int prevdraw = 1;
465                 int draw = 1;
466
467                 GPU_edge_setup(dm);
468                 if( !GPU_buffer_legacy(dm) ) {
469                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
470                                 if(medge->flag&ME_LOOSEEDGE) {
471                                         draw = 1;
472                                 } 
473                                 else {
474                                         draw = 0;
475                                 }
476                                 if( prevdraw != draw ) {
477                                         if( prevdraw > 0 && (i-prevstart) > 0) {
478                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
479                                         }
480                                         prevstart = i;
481                                 }
482                                 prevdraw = draw;
483                         }
484                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
485                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
486                         }
487                 }
488                 GPU_buffer_unbind();
489         }
490 }
491
492 static void cdDM_drawFacesSolid(DerivedMesh *dm,
493                                 float (*partial_redraw_planes)[4],
494                                 int UNUSED(fast), int (*setMaterial)(int, void *attribs))
495 {
496         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
497         MVert *mvert = cddm->mvert;
498         MFace *mface = cddm->mface;
499         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
500         int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
501
502 #define PASSVERT(index) {                                               \
503         if(shademodel == GL_SMOOTH) {                           \
504                 short *no = mvert[index].no;                    \
505                 glNormal3sv(no);                                                \
506         }                                                                                       \
507         glVertex3fv(mvert[index].co);   \
508 }
509
510         if(cddm->pbvh && cddm->pbvh_draw) {
511                 if(dm->numFaceData) {
512                         float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
513
514                         /* should be per face */
515                         if(!setMaterial(mface->mat_nr+1, NULL))
516                                 return;
517
518                         glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
519                         BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH));
520                         glShadeModel(GL_FLAT);
521                 }
522
523                 return;
524         }
525
526         if( GPU_buffer_legacy(dm) ) {
527                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
528                 glBegin(glmode = GL_QUADS);
529                 for(a = 0; a < dm->numFaceData; a++, mface++) {
530                         int new_glmode, new_matnr, new_shademodel;
531
532                         new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
533                         new_matnr = mface->mat_nr + 1;
534                         new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
535                         
536                         if(new_glmode != glmode || new_matnr != matnr
537                            || new_shademodel != shademodel) {
538                                 glEnd();
539
540                                 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
541
542                                 glShadeModel(shademodel = new_shademodel);
543                                 glBegin(glmode = new_glmode);
544                         } 
545                         
546                         if(drawCurrentMat) {
547                                 if(shademodel == GL_FLAT) {
548                                         if (nors) {
549                                                 glNormal3fv(nors);
550                                         }
551                                         else {
552                                                 /* TODO make this better (cache facenormals as layer?) */
553                                                 float nor[3];
554                                                 if(mface->v4) {
555                                                         normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
556                                                 } else {
557                                                         normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
558                                                 }
559                                                 glNormal3fv(nor);
560                                         }
561                                 }
562
563                                 PASSVERT(mface->v1);
564                                 PASSVERT(mface->v2);
565                                 PASSVERT(mface->v3);
566                                 if(mface->v4) {
567                                         PASSVERT(mface->v4);
568                                 }
569                         }
570
571                         if(nors) nors += 3;
572                 }
573                 glEnd();
574         }
575         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
576                 GPU_vertex_setup( dm );
577                 GPU_normal_setup( dm );
578                 if( !GPU_buffer_legacy(dm) ) {
579                         glShadeModel(GL_SMOOTH);
580                         for( a = 0; a < dm->drawObject->totmaterial; a++ ) {
581                                 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
582                                         glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
583                                                      dm->drawObject->materials[a].totpoint);
584                         }
585                 }
586                 GPU_buffer_unbind( );
587         }
588
589 #undef PASSVERT
590         glShadeModel(GL_FLAT);
591 }
592
593 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
594 {
595         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
596         int a, glmode;
597         unsigned char *cp1, *cp2;
598         MVert *mvert = cddm->mvert;
599         MFace *mface = cddm->mface;
600
601         cp1 = col1;
602         if(col2) {
603                 cp2 = col2;
604         } else {
605                 cp2 = NULL;
606                 useTwoSided = 0;
607         }
608
609         /* there's a conflict here... twosided colors versus culling...? */
610         /* defined by history, only texture faces have culling option */
611         /* we need that as mesh option builtin, next to double sided lighting */
612         if(col2) {
613                 glEnable(GL_CULL_FACE);
614         }
615
616         cdDM_update_normals_from_pbvh(dm);
617
618         if( GPU_buffer_legacy(dm) ) {
619                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
620                 glShadeModel(GL_SMOOTH);
621                 glBegin(glmode = GL_QUADS);
622                 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
623                         int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
624
625                         if(new_glmode != glmode) {
626                                 glEnd();
627                                 glBegin(glmode = new_glmode);
628                         }
629                                 
630                         glColor3ubv(cp1+0);
631                         glVertex3fv(mvert[mface->v1].co);
632                         glColor3ubv(cp1+4);
633                         glVertex3fv(mvert[mface->v2].co);
634                         glColor3ubv(cp1+8);
635                         glVertex3fv(mvert[mface->v3].co);
636                         if(mface->v4) {
637                                 glColor3ubv(cp1+12);
638                                 glVertex3fv(mvert[mface->v4].co);
639                         }
640                                 
641                         if(useTwoSided) {
642                                 glColor3ubv(cp2+8);
643                                 glVertex3fv(mvert[mface->v3].co );
644                                 glColor3ubv(cp2+4);
645                                 glVertex3fv(mvert[mface->v2].co );
646                                 glColor3ubv(cp2+0);
647                                 glVertex3fv(mvert[mface->v1].co );
648                                 if(mface->v4) {
649                                         glColor3ubv(cp2+12);
650                                         glVertex3fv(mvert[mface->v4].co );
651                                 }
652                         }
653                         if(col2) cp2 += 16;
654                 }
655                 glEnd();
656         }
657         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
658                 GPU_color4_upload(dm,cp1);
659                 GPU_vertex_setup(dm);
660                 GPU_color_setup(dm);
661                 if( !GPU_buffer_legacy(dm) ) {
662                         glShadeModel(GL_SMOOTH);
663                         glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
664
665                         if( useTwoSided ) {
666                                 GPU_color4_upload(dm,cp2);
667                                 GPU_color_setup(dm);
668                                 glCullFace(GL_FRONT);
669                                 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
670                                 glCullFace(GL_BACK);
671                         }
672                 }
673                 GPU_buffer_unbind();
674         }
675
676         glShadeModel(GL_FLAT);
677         glDisable(GL_CULL_FACE);
678 }
679
680 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
681                int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
682                int (*drawParamsMapped)(void *userData, int index),
683                void *userData) 
684 {
685         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
686         MVert *mv = cddm->mvert;
687         MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
688         MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
689         float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
690         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
691         int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
692         int startFace = 0, lastFlag = 0xdeadbeef;
693         MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
694         if(!mcol)
695                 mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
696
697         cdDM_update_normals_from_pbvh(dm);
698
699         if( GPU_buffer_legacy(dm) ) {
700                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
701                 for(i = 0; i < dm->numFaceData; i++, mf++) {
702                         MVert *mvert;
703                         int flag;
704                         unsigned char *cp = NULL;
705
706                         if(drawParams) {
707                                 flag = drawParams(tf? &tf[i]: NULL, mcol!=NULL, mf->mat_nr);
708                         }
709                         else {
710                                 if(index) {
711                                         orig = *index++;
712                                         if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
713                                         if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
714                                         else    { if(nors) nors += 3; continue; }
715                                 }
716                                 else
717                                         if(drawParamsMapped) flag = drawParamsMapped(userData, i);
718                                         else    { if(nors) nors += 3; continue; }
719                         }
720                         
721                         if(flag != 0) {
722                                 if (flag==1 && mcol)
723                                         cp= (unsigned char*) &mcol[i*4];
724
725                                 if(!(mf->flag&ME_SMOOTH)) {
726                                         if (nors) {
727                                                 glNormal3fv(nors);
728                                         }
729                                         else {
730                                                 float nor[3];
731                                                 if(mf->v4) {
732                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
733                                                 } else {
734                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
735                                                 }
736                                                 glNormal3fv(nor);
737                                         }
738                                 }
739
740                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
741                                 if(tf) glTexCoord2fv(tf[i].uv[0]);
742                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
743                                 mvert = &mv[mf->v1];
744                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
745                                 glVertex3fv(mvert->co);
746                                         
747                                 if(tf) glTexCoord2fv(tf[i].uv[1]);
748                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
749                                 mvert = &mv[mf->v2];
750                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
751                                 glVertex3fv(mvert->co);
752
753                                 if(tf) glTexCoord2fv(tf[i].uv[2]);
754                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
755                                 mvert = &mv[mf->v3];
756                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
757                                 glVertex3fv(mvert->co);
758
759                                 if(mf->v4) {
760                                         if(tf) glTexCoord2fv(tf[i].uv[3]);
761                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
762                                         mvert = &mv[mf->v4];
763                                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
764                                         glVertex3fv(mvert->co);
765                                 }
766                                 glEnd();
767                         }
768                         
769                         if(nors) nors += 3;
770                 }
771         } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
772                 MCol *col = realcol;
773                 if(!col)
774                         col = mcol;
775
776                 GPU_vertex_setup( dm );
777                 GPU_normal_setup( dm );
778                 GPU_uv_setup( dm );
779                 if( col != NULL ) {
780                         /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL )  {
781                                 col = 0;
782                         } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
783                                 col = 0;
784                         }
785                         
786                         if( col != 0 ) {*/
787                                 unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
788                                 for( i=0; i < dm->getNumTessFaces(dm); i++ ) {
789                                         for( j=0; j < 4; j++ ) {
790                                                 colors[i*12+j*3] = col[i*4+j].r;
791                                                 colors[i*12+j*3+1] = col[i*4+j].g;
792                                                 colors[i*12+j*3+2] = col[i*4+j].b;
793                                         }
794                                 }
795                                 GPU_color3_upload(dm,colors);
796                                 MEM_freeN(colors);
797                                 if(realcol)
798                                         dm->drawObject->colType = CD_TEXTURE_MCOL;
799                                 else if(mcol)
800                                         dm->drawObject->colType = CD_MCOL;
801                         //}
802                         GPU_color_setup( dm );
803                 }
804
805                 if( !GPU_buffer_legacy(dm) ) {
806                         /* warning!, this logic is incorrect, see bug [#27175]
807                          * firstly, there are no checks for changes in context, such as texface image.
808                          * secondly, drawParams() sets the GL context, so checking if there is a change
809                          * from lastFlag is too late once glDrawArrays() runs, since drawing the arrays
810                          * will use the modified, OpenGL settings.
811                          * 
812                          * However its tricky to fix this without duplicating the internal logic
813                          * of drawParams(), perhaps we need an argument like...
814                          * drawParams(..., keep_gl_state_but_return_when_changed) ?.
815                          *
816                          * We could also just disable VBO's here, since texface may be deprecated - campbell.
817                          */
818                         
819                         glShadeModel( GL_SMOOTH );
820                         lastFlag = 0;
821                         for(i = 0; i < dm->drawObject->tot_triangle_point/3; i++) {
822                                 int actualFace = dm->drawObject->triangle_to_mface[i];
823                                 int flag = 1;
824
825                                 if(drawParams) {
826                                         flag = drawParams(tf? &tf[actualFace]: NULL, mcol!=NULL, mf[actualFace].mat_nr);
827                                 }
828                                 else {
829                                         if(index) {
830                                                 orig = index[actualFace];
831                                                 if(orig == ORIGINDEX_NONE) continue;
832                                                 if(drawParamsMapped)
833                                                         flag = drawParamsMapped(userData, orig);
834                                         }
835                                         else
836                                                 if(drawParamsMapped)
837                                                         flag = drawParamsMapped(userData, actualFace);
838                                 }
839                                 if( flag != lastFlag ) {
840                                         if( startFace < i ) {
841                                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
842                                                         if (lastFlag==1 && col)
843                                                                 GPU_color_switch(1);
844                                                         else
845                                                                 GPU_color_switch(0);
846                                                         glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
847                                                 }
848                                         }
849                                         lastFlag = flag;
850                                         startFace = i;
851                                 }
852                         }
853                         if( startFace < dm->drawObject->tot_triangle_point/3 ) {
854                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
855                                         if (lastFlag==1 && col)
856                                                 GPU_color_switch(1);
857                                         else
858                                                 GPU_color_switch(0);
859                                         glDrawArrays(GL_TRIANGLES, startFace*3, dm->drawObject->tot_triangle_point - startFace*3);
860                                 }
861                         }
862                 }
863
864                 GPU_buffer_unbind();
865                 glShadeModel( GL_FLAT );
866         }
867 }
868
869 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
870 {
871         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
872 }
873
874 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
875                         int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
876 {
877         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
878         MVert *mv = cddm->mvert;
879         MFace *mf = cddm->mface;
880         MCol *mc;
881         float *nors= DM_get_tessface_data_layer(dm, CD_NORMAL);
882         int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
883
884         mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL);
885         if(!mc)
886                 mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL);
887         if(!mc)
888                 mc = DM_get_tessface_data_layer(dm, CD_MCOL);
889
890         cdDM_update_normals_from_pbvh(dm);
891
892         /* back-buffer always uses legacy since VBO's would need the
893          * color array temporarily overwritten for drawing, then reset. */
894         if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
895                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
896                 for(i = 0; i < dm->numFaceData; i++, mf++) {
897                         int drawSmooth = (mf->flag & ME_SMOOTH);
898                         int draw= 1;
899
900                         orig= (index==NULL) ? i : *index++;
901                         
902                         if(orig == ORIGINDEX_NONE)
903                                 draw= setMaterial(mf->mat_nr + 1, NULL);
904                         else if (setDrawOptions != NULL)
905                                 draw= setDrawOptions(userData, orig, &drawSmooth);
906
907                         if(draw) {
908                                 unsigned char *cp = NULL;
909
910                                 if(useColors && mc)
911                                         cp = (unsigned char *)&mc[i * 4];
912
913                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
914                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
915
916                                 if (!drawSmooth) {
917                                         if (nors) {
918                                                 glNormal3fv(nors);
919                                         }
920                                         else {
921                                                 float nor[3];
922                                                 if(mf->v4) {
923                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
924                                                 } else {
925                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
926                                                 }
927                                                 glNormal3fv(nor);
928                                         }
929
930                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
931                                         glVertex3fv(mv[mf->v1].co);
932                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
933                                         glVertex3fv(mv[mf->v2].co);
934                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
935                                         glVertex3fv(mv[mf->v3].co);
936                                         if(mf->v4) {
937                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
938                                                 glVertex3fv(mv[mf->v4].co);
939                                         }
940                                 } else {
941                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
942                                         glNormal3sv(mv[mf->v1].no);
943                                         glVertex3fv(mv[mf->v1].co);
944                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
945                                         glNormal3sv(mv[mf->v2].no);
946                                         glVertex3fv(mv[mf->v2].co);
947                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
948                                         glNormal3sv(mv[mf->v3].no);
949                                         glVertex3fv(mv[mf->v3].co);
950                                         if(mf->v4) {
951                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
952                                                 glNormal3sv(mv[mf->v4].no);
953                                                 glVertex3fv(mv[mf->v4].co);
954                                         }
955                                 }
956
957                                 glEnd();
958                         } /*else {
959                                 printf("eek in cddm draw mapped faces!\n");
960                         }*/
961                         
962                         if (nors) nors += 3;
963                 }
964         }
965         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
966                 int prevstart = 0;
967                 GPU_vertex_setup(dm);
968                 GPU_normal_setup(dm);
969                 if( useColors && mc )
970                         GPU_color_setup(dm);
971                 if( !GPU_buffer_legacy(dm) ) {
972                         int tottri = dm->drawObject->tot_triangle_point/3;
973                         glShadeModel(GL_SMOOTH);
974                         
975                         if(tottri == 0) {
976                                 /* avoid buffer problems in following code */
977                         }
978                         if(setDrawOptions == NULL) {
979                                 /* just draw the entire face array */
980                                 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
981                         }
982                         else {
983                                 /* we need to check if the next material changes */
984                                 int next_actualFace= dm->drawObject->triangle_to_mface[0];
985                                 
986                                 for( i = 0; i < tottri; i++ ) {
987                                         //int actualFace = dm->drawObject->triangle_to_mface[i];
988                                         int actualFace = next_actualFace;
989                                         MFace *mface= mf + actualFace;
990                                         int drawSmooth= (mface->flag & ME_SMOOTH);
991                                         int draw = 1;
992                                         int flush = 0;
993
994                                         if(i != tottri-1)
995                                                 next_actualFace= dm->drawObject->triangle_to_mface[i+1];
996
997                                         orig= (index==NULL) ? actualFace : index[actualFace];
998
999                                         if(orig == ORIGINDEX_NONE)
1000                                                 draw= setMaterial(mface->mat_nr + 1, NULL);
1001                                         else if (setDrawOptions != NULL)
1002                                                 draw= setDrawOptions(userData, orig, &drawSmooth);
1003         
1004                                         /* Goal is to draw as long of a contiguous triangle
1005                                            array as possible, so draw when we hit either an
1006                                            invisible triangle or at the end of the array */
1007
1008                                         /* flush buffer if current triangle isn't drawable or it's last triangle... */
1009                                         flush= !draw || i == tottri - 1;
1010
1011                                         /* ... or when material setting is dissferent  */
1012                                         flush|= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
1013
1014                                         if(!flush && compareDrawOptions) {
1015                                                 int next_orig= (index==NULL) ? next_actualFace : index[next_actualFace];
1016
1017                                                 /* also compare draw options and flush buffer if they're different
1018                                                    need for face selection highlight in edit mode */
1019                                                 flush|= compareDrawOptions(userData, orig, next_orig) == 0;
1020                                         }
1021
1022                                         if(flush) {
1023                                                 int first= prevstart*3;
1024                                                 int count= (i-prevstart+(draw ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
1025
1026                                                 if(count)
1027                                                         glDrawArrays(GL_TRIANGLES, first, count);
1028
1029                                                 prevstart = i + 1;
1030                                         }
1031                                 }
1032                         }
1033
1034                         glShadeModel(GL_FLAT);
1035                 }
1036                 GPU_buffer_unbind();
1037         }
1038 }
1039
1040 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1041 {
1042         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
1043 }
1044
1045
1046 static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, int smoothnormal)
1047 {
1048         int b;
1049
1050         /* orco texture coordinates */
1051         if(attribs->totorco) {
1052                 if(attribs->orco.glTexco)
1053                         glTexCoord3fv(attribs->orco.array[index]);
1054                 else
1055                         glVertexAttrib3fvARB(attribs->orco.glIndex, attribs->orco.array[index]);
1056         }
1057
1058         /* uv texture coordinates */
1059         for(b = 0; b < attribs->tottface; b++) {
1060                 MTFace *tf = &attribs->tface[b].array[a];
1061
1062                 if(attribs->tface[b].glTexco)
1063                         glTexCoord2fv(tf->uv[vert]);
1064                 else
1065                         glVertexAttrib2fvARB(attribs->tface[b].glIndex, tf->uv[vert]);
1066         }
1067
1068         /* vertex colors */
1069         for(b = 0; b < attribs->totmcol; b++) {
1070                 MCol *cp = &attribs->mcol[b].array[a*4 + vert];
1071                 GLubyte col[4];
1072                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1073                 glVertexAttrib4ubvARB(attribs->mcol[b].glIndex, col);
1074         }
1075
1076         /* tangent for normal mapping */
1077         if(attribs->tottang) {
1078                 float *tang = attribs->tang.array[a*4 + vert];
1079                 glVertexAttrib4fvARB(attribs->tang.glIndex, tang);
1080         }
1081
1082         /* vertex normal */
1083         if(smoothnormal)
1084                 glNormal3sv(mvert[index].no);
1085
1086         /* vertex coordinate */
1087         glVertex3fv(mvert[index].co);
1088 }
1089
1090
1091 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
1092 {
1093         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1094         GPUVertexAttribs gattribs;
1095         DMVertexAttribs attribs;
1096         MVert *mvert = cddm->mvert;
1097         MFace *mface = cddm->mface;
1098         /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
1099         float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
1100         int a, b, dodraw, matnr, new_matnr;
1101         int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1102
1103         cdDM_update_normals_from_pbvh(dm);
1104
1105         matnr = -1;
1106         dodraw = 0;
1107
1108         glShadeModel(GL_SMOOTH);
1109
1110         if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1111                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1112                 memset(&attribs, 0, sizeof(attribs));
1113
1114                 glBegin(GL_QUADS);
1115
1116                 for(a = 0; a < dm->numFaceData; a++, mface++) {
1117                         const int smoothnormal = (mface->flag & ME_SMOOTH);
1118                         new_matnr = mface->mat_nr + 1;
1119
1120                         if(new_matnr != matnr) {
1121                                 glEnd();
1122
1123                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1124                                 if(dodraw)
1125                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1126
1127                                 glBegin(GL_QUADS);
1128                         }
1129
1130                         if(!dodraw) {
1131                                 continue;
1132                         }
1133                         else if(setDrawOptions) {
1134                                 orig = (index)? index[a]: a;
1135
1136                                 if(orig == ORIGINDEX_NONE) {
1137                                         /* since the material is set by setMaterial(), faces with no
1138                                          * origin can be assumed to be generated by a modifier */ 
1139                                         
1140                                         /* continue */
1141                                 }
1142                                 else if(!setDrawOptions(userData, orig))
1143                                         continue;
1144                         }
1145
1146                         if(!smoothnormal) {
1147                                 if(nors) {
1148                                         glNormal3fv(nors[a]);
1149                                 }
1150                                 else {
1151                                         /* TODO ideally a normal layer should always be available */
1152                                         float nor[3];
1153                                         if(mface->v4) {
1154                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1155                                         } else {
1156                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1157                                         }
1158                                         glNormal3fv(nor);
1159                                 }
1160                         }
1161
1162                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal);
1163                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal);
1164                         cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1165                         if(mface->v4)
1166                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal);
1167                         else
1168                                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1169
1170                 }
1171                 glEnd();
1172         }
1173         else {
1174                 GPUBuffer *buffer = NULL;
1175                 char *varray = NULL;
1176                 int numdata = 0, elementsize = 0, offset;
1177                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1178                 int i;
1179
1180                 MFace *mf = mface;
1181                 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1182                 memset(&attribs, 0, sizeof(attribs));
1183
1184                 GPU_vertex_setup(dm);
1185                 GPU_normal_setup(dm);
1186
1187                 if( !GPU_buffer_legacy(dm) ) {
1188                         for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
1189
1190                                 a = dm->drawObject->triangle_to_mface[i];
1191
1192                                 mface = mf + a;
1193                                 new_matnr = mface->mat_nr + 1;
1194
1195                                 if(new_matnr != matnr ) {
1196                                         numfaces = curface - start;
1197                                         if( numfaces > 0 ) {
1198
1199                                                 if( dodraw ) {
1200
1201                                                         if( numdata != 0 ) {
1202
1203                                                                 GPU_buffer_unlock(buffer);
1204
1205                                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1206                                                         }
1207
1208                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1209
1210                                                         if( numdata != 0 ) {
1211
1212                                                                 GPU_buffer_free(buffer);
1213
1214                                                                 buffer = NULL;
1215                                                         }
1216
1217                                                 }
1218                                         }
1219                                         numdata = 0;
1220                                         start = curface;
1221                                         prevdraw = dodraw;
1222                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1223                                         if(dodraw) {
1224                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1225
1226                                                 if(attribs.totorco) {
1227                                                         datatypes[numdata].index = attribs.orco.glIndex;
1228                                                         datatypes[numdata].size = 3;
1229                                                         datatypes[numdata].type = GL_FLOAT;
1230                                                         numdata++;
1231                                                 }
1232                                                 for(b = 0; b < attribs.tottface; b++) {
1233                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1234                                                         datatypes[numdata].size = 2;
1235                                                         datatypes[numdata].type = GL_FLOAT;
1236                                                         numdata++;
1237                                                 }       
1238                                                 for(b = 0; b < attribs.totmcol; b++) {
1239                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1240                                                         datatypes[numdata].size = 4;
1241                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1242                                                         numdata++;
1243                                                 }       
1244                                                 if(attribs.tottang) {
1245                                                         datatypes[numdata].index = attribs.tang.glIndex;
1246                                                         datatypes[numdata].size = 4;
1247                                                         datatypes[numdata].type = GL_FLOAT;
1248                                                         numdata++;
1249                                                 }
1250                                                 if( numdata != 0 ) {
1251                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1252                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
1253                                                         if( buffer == NULL ) {
1254                                                                 GPU_buffer_unbind();
1255                                                                 dm->drawObject->legacy = 1;
1256                                                                 return;
1257                                                         }
1258                                                         varray = GPU_buffer_lock_stream(buffer);
1259                                                         if( varray == NULL ) {
1260                                                                 GPU_buffer_unbind();
1261                                                                 GPU_buffer_free(buffer);
1262                                                                 dm->drawObject->legacy = 1;
1263                                                                 return;
1264                                                         }
1265                                                 }
1266                                                 else {
1267                                                         /* if the buffer was set, dont use it again.
1268                                                          * prevdraw was assumed true but didnt run so set to false - [#21036] */
1269                                                         prevdraw= 0;
1270                                                         buffer= NULL;
1271                                                 }
1272                                         }
1273                                 }
1274                                 if(!dodraw) {
1275                                         continue;
1276                                 }
1277
1278                                 if( numdata != 0 ) {
1279                                         offset = 0;
1280                                         if(attribs.totorco) {
1281                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1282                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1283                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1284                                                 offset += sizeof(float)*3;
1285                                         }
1286                                         for(b = 0; b < attribs.tottface; b++) {
1287                                                 MTFace *tf = &attribs.tface[b].array[a];
1288                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1289                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1290
1291                                                 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1292                                                 offset += sizeof(float)*2;
1293                                         }
1294                                         for(b = 0; b < attribs.totmcol; b++) {
1295                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1296                                                 GLubyte col[4];
1297                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1298                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1299                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1300                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1301                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1302                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1303                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1304                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1305                                                 offset += sizeof(unsigned char)*4;
1306                                         }       
1307                                         if(attribs.tottang) {
1308                                                 float *tang = attribs.tang.array[a*4 + 0];
1309                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1310                                                 tang = attribs.tang.array[a*4 + 1];
1311                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1312                                                 tang = attribs.tang.array[a*4 + 2];
1313                                                 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1314                                                 offset += sizeof(float)*4;
1315                                         }
1316                                         (void)offset;
1317                                 }
1318                                 curface++;
1319                                 if(mface->v4) {
1320                                         if( numdata != 0 ) {
1321                                                 offset = 0;
1322                                                 if(attribs.totorco) {
1323                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1324                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1325                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1326                                                         offset += sizeof(float)*3;
1327                                                 }
1328                                                 for(b = 0; b < attribs.tottface; b++) {
1329                                                         MTFace *tf = &attribs.tface[b].array[a];
1330                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1331                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1332                                                         VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1333                                                         offset += sizeof(float)*2;
1334                                                 }
1335                                                 for(b = 0; b < attribs.totmcol; b++) {
1336                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1337                                                         GLubyte col[4];
1338                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1339                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1340                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1341                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1342                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1343                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1344                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1345                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1346                                                         offset += sizeof(unsigned char)*4;
1347                                                 }       
1348                                                 if(attribs.tottang) {
1349                                                         float *tang = attribs.tang.array[a*4 + 2];
1350                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1351                                                         tang = attribs.tang.array[a*4 + 3];
1352                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1353                                                         tang = attribs.tang.array[a*4 + 0];
1354                                                         QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1355                                                         offset += sizeof(float)*4;
1356                                                 }
1357                                                 (void)offset;
1358                                         }
1359                                         curface++;
1360                                         i++;
1361                                 }
1362                         }
1363                         numfaces = curface - start;
1364                         if( numfaces > 0 ) {
1365                                 if( dodraw ) {
1366                                         if( numdata != 0 ) {
1367                                                 GPU_buffer_unlock(buffer);
1368                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1369                                         }
1370                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1371                                 }
1372                         }
1373                         GPU_buffer_unbind();
1374                 }
1375                 GPU_buffer_free(buffer);
1376         }
1377
1378         glShadeModel(GL_FLAT);
1379 }
1380
1381 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1382 {
1383         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1384 }
1385
1386 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1387 {
1388         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1389         MVert *vert = cddm->mvert;
1390         MEdge *edge = cddm->medge;
1391         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1392
1393         glBegin(GL_LINES);
1394         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1395                 if(index) {
1396                         orig = *index++;
1397                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1398                 }
1399                 else
1400                         orig = i;
1401
1402                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1403                         glVertex3fv(vert[edge->v1].co);
1404                         glVertex3fv(vert[edge->v2].co);
1405                 }
1406         }
1407         glEnd();
1408 }
1409
1410 static void cdDM_foreachMappedVert(
1411                                                    DerivedMesh *dm,
1412                                                    void (*func)(void *userData, int index, float *co,
1413                                                                                 float *no_f, short *no_s),
1414                                                    void *userData)
1415 {
1416         MVert *mv = CDDM_get_verts(dm);
1417         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1418
1419         for(i = 0; i < dm->numVertData; i++, mv++) {
1420                 if(index) {
1421                         orig = *index++;
1422                         if(orig == ORIGINDEX_NONE) continue;
1423                         func(userData, orig, mv->co, NULL, mv->no);
1424                 }
1425                 else
1426                         func(userData, i, mv->co, NULL, mv->no);
1427         }
1428 }
1429
1430 static void cdDM_foreachMappedEdge(
1431                                                    DerivedMesh *dm,
1432                                                    void (*func)(void *userData, int index,
1433                                                                                 float *v0co, float *v1co),
1434                                                    void *userData)
1435 {
1436         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1437         MVert *mv = cddm->mvert;
1438         MEdge *med = cddm->medge;
1439         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1440
1441         for(i = 0; i < dm->numEdgeData; i++, med++) {
1442                 if (index) {
1443                         orig = *index++;
1444                         if(orig == ORIGINDEX_NONE) continue;
1445                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1446                 }
1447                 else
1448                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1449         }
1450 }
1451
1452 static void cdDM_foreachMappedFaceCenter(
1453                                                    DerivedMesh *dm,
1454                                                    void (*func)(void *userData, int index,
1455                                                                                 float *cent, float *no),
1456                                                    void *userData)
1457 {
1458         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1459         MVert *mv = cddm->mvert;
1460         MPoly *mf = cddm->mpoly;
1461         MLoop *ml = cddm->mloop;
1462         int i, j, orig, *index;
1463
1464         index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
1465         mf = cddm->mpoly;
1466         for(i = 0; i < dm->numPolyData; i++, mf++) {
1467                 float cent[3];
1468                 float no[3];
1469
1470                 if (index) {
1471                         orig = *index++;
1472                         if(orig == ORIGINDEX_NONE) continue;
1473                 } else
1474                         orig = i;
1475                 
1476                 ml = &cddm->mloop[mf->loopstart];
1477                 cent[0] = cent[1] = cent[2] = 0.0f;
1478                 for (j=0; j<mf->totloop; j++, ml++) {
1479                         add_v3_v3v3(cent, cent, mv[ml->v].co);
1480                 }
1481                 mul_v3_fl(cent, 1.0f / (float)j);
1482
1483                 ml = &cddm->mloop[mf->loopstart];
1484                 if (j > 3) {
1485                         normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1486                                        mv[(ml+2)->v].co, mv[(ml+3)->v].co);
1487                 } else {
1488                         normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
1489                                        mv[(ml+2)->v].co);
1490                 }
1491
1492                 func(userData, orig, cent, no);
1493         }
1494
1495 }
1496
1497 static void cdDM_recalcTesselation(DerivedMesh *dm)
1498 {
1499         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1500
1501         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1502                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1503                 dm->numPolyData, 1, 0);
1504         
1505         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1506 }
1507
1508 /*ignores original poly origindex layer*/
1509 static void cdDM_recalcTesselation2(DerivedMesh *dm)
1510 {
1511         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1512
1513         dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
1514                 &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
1515                 dm->numPolyData, 0, 0);
1516         
1517         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1518 }
1519
1520 void CDDM_recalc_tesselation(DerivedMesh *dm, int orig_use_polyorig)
1521 {
1522         if (orig_use_polyorig)
1523                 cdDM_recalcTesselation(dm);
1524         else
1525                 cdDM_recalcTesselation2(dm);
1526 }
1527
1528 static void cdDM_free_internal(CDDerivedMesh *cddm)
1529 {
1530         if(cddm->fmap) MEM_freeN(cddm->fmap);
1531         if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1532 }
1533
1534 static void cdDM_release(DerivedMesh *dm)
1535 {
1536         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1537
1538         if (DM_release(dm)) {
1539                 cdDM_free_internal(cddm);
1540                 MEM_freeN(cddm);
1541         }
1542 }
1543
1544 int CDDM_Check(DerivedMesh *dm)
1545 {
1546         return dm && dm->getMinMax == cdDM_getMinMax;
1547 }
1548
1549 /**************** CDDM interface functions ****************/
1550 static CDDerivedMesh *cdDM_create(const char *desc)
1551 {
1552         CDDerivedMesh *cddm;
1553         DerivedMesh *dm;
1554
1555         cddm = MEM_callocN(sizeof(*cddm), desc);
1556         dm = &cddm->dm;
1557
1558         dm->getMinMax = cdDM_getMinMax;
1559
1560         dm->getNumVerts = cdDM_getNumVerts;
1561         dm->getNumEdges = cdDM_getNumEdges;
1562         dm->getNumTessFaces = cdDM_getNumTessFaces;
1563         dm->getNumFaces = cdDM_getNumFaces;
1564
1565         dm->getVert = cdDM_getVert;
1566         dm->getEdge = cdDM_getEdge;
1567         dm->getTessFace = cdDM_getFace;
1568         dm->copyVertArray = cdDM_copyVertArray;
1569         dm->copyEdgeArray = cdDM_copyEdgeArray;
1570         dm->copyTessFaceArray = cdDM_copyFaceArray;
1571         dm->copyLoopArray = cdDM_copyLoopArray;
1572         dm->copyPolyArray = cdDM_copyPolyArray;
1573         dm->getVertData = DM_get_vert_data;
1574         dm->getEdgeData = DM_get_edge_data;
1575         dm->getTessFaceData = DM_get_face_data;
1576         dm->getVertDataArray = DM_get_vert_data_layer;
1577         dm->getEdgeDataArray = DM_get_edge_data_layer;
1578         dm->getTessFaceDataArray = DM_get_tessface_data_layer;
1579         
1580         //doesn't work yet for all cases
1581         //dm->recalcTesselation = cdDM_recalcTesselation;
1582
1583         dm->getVertCos = cdDM_getVertCos;
1584         dm->getVertCo = cdDM_getVertCo;
1585         dm->getVertNo = cdDM_getVertNo;
1586
1587         dm->getPBVH = cdDM_getPBVH;
1588         dm->getFaceMap = cdDM_getFaceMap;
1589
1590         dm->drawVerts = cdDM_drawVerts;
1591
1592         dm->drawUVEdges = cdDM_drawUVEdges;
1593         dm->drawEdges = cdDM_drawEdges;
1594         dm->drawLooseEdges = cdDM_drawLooseEdges;
1595         dm->drawMappedEdges = cdDM_drawMappedEdges;
1596
1597         dm->drawFacesSolid = cdDM_drawFacesSolid;
1598         dm->drawFacesColored = cdDM_drawFacesColored;
1599         dm->drawFacesTex = cdDM_drawFacesTex;
1600         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1601         dm->drawMappedFaces = cdDM_drawMappedFaces;
1602         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1603         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1604
1605         dm->foreachMappedVert = cdDM_foreachMappedVert;
1606         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1607         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1608
1609         dm->release = cdDM_release;
1610
1611         return cddm;
1612 }
1613
1614 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
1615 {
1616         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1617         DerivedMesh *dm = &cddm->dm;
1618
1619         DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
1620
1621         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1622         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1623         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1624         CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
1625
1626         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1627         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1628         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1629         CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
1630         CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
1631
1632         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1633         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1634         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1635         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1636         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1637
1638         return dm;
1639 }
1640
1641 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1642 {
1643         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1644         DerivedMesh *dm = &cddm->dm;
1645         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1646         int alloctype;
1647
1648         /* this does a referenced copy, with an exception for fluidsim */
1649
1650         DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
1651                     mesh->totloop, mesh->totpoly);
1652
1653         dm->deformedOnly = 1;
1654
1655         alloctype= CD_REFERENCE;
1656
1657         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1658                                          mesh->totvert);
1659         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1660                                          mesh->totedge);
1661         CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype,
1662                                          mesh->totface);
1663         CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
1664                          mesh->totloop);
1665         CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
1666                          mesh->totpoly);
1667
1668         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1669         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1670         cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
1671         cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
1672         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1673
1674         if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
1675                 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
1676
1677         return dm;
1678 }
1679
1680 static DerivedMesh *disabled__CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1681 {
1682         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1683                                    BLI_countlist(&em->edges),
1684                                    BLI_countlist(&em->faces), 0, 0);
1685         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1686         EditVert *eve;
1687         EditEdge *eed;
1688         EditFace *efa;
1689         MVert *mvert = cddm->mvert;
1690         MEdge *medge = cddm->medge;
1691         MFace *mface = cddm->mface;
1692         int i, *index;
1693
1694         dm->deformedOnly = 1;
1695
1696         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1697                                          CD_CALLOC, dm->numVertData);
1698         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1699                                          CD_CALLOC, dm->numEdgeData); */
1700         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1701                                          CD_CALLOC, dm->numFaceData);
1702         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1703                          CD_CALLOC, dm->numFaceData);
1704
1705         /* set eve->hash to vert index */
1706         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1707                 eve->tmp.l = i;
1708
1709         /* Need to be able to mark loose edges */
1710         for(eed = em->edges.first; eed; eed = eed->next) {
1711                 eed->f2 = 0;
1712         }
1713         for(efa = em->faces.first; efa; efa = efa->next) {
1714                 efa->e1->f2 = 1;
1715                 efa->e2->f2 = 1;
1716                 efa->e3->f2 = 1;
1717                 if(efa->e4) efa->e4->f2 = 1;
1718         }
1719
1720         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1721         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1722                 i++, eve = eve->next, index++) {
1723                 MVert *mv = &mvert[i];
1724
1725                 VECCOPY(mv->co, eve->co);
1726
1727                 normal_float_to_short_v3(mv->no, eve->no);
1728                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1729
1730                 mv->flag = 0;
1731
1732                 *index = i;
1733
1734                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1735         }
1736
1737         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1738         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1739                 i++, eed = eed->next, index++) {
1740                 MEdge *med = &medge[i];
1741
1742                 med->v1 = eed->v1->tmp.l;
1743                 med->v2 = eed->v2->tmp.l;
1744                 med->crease = (unsigned char) (eed->crease * 255.0f);
1745                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1746                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1747                 
1748                 if(eed->seam) med->flag |= ME_SEAM;
1749                 if(eed->sharp) med->flag |= ME_SHARP;
1750                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1751
1752                 *index = i;
1753
1754                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1755         }
1756
1757         index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
1758         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1759                 i++, efa = efa->next, index++) {
1760                 MFace *mf = &mface[i];
1761
1762                 mf->v1 = efa->v1->tmp.l;
1763                 mf->v2 = efa->v2->tmp.l;
1764                 mf->v3 = efa->v3->tmp.l;
1765                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1766                 mf->mat_nr = efa->mat_nr;
1767                 mf->flag = efa->flag;
1768
1769                 *index = i;
1770
1771                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1772                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1773         }
1774
1775         return dm;
1776 }
1777
1778 DerivedMesh *CDDM_from_curve(Object *ob)
1779 {
1780         return CDDM_from_curve_customDB(ob, &ob->disp);
1781 }
1782
1783 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1784 {
1785         DerivedMesh *dm;
1786         CDDerivedMesh *cddm;
1787         MVert *allvert;
1788         MEdge *alledge;
1789         MFace *allface;
1790         MLoop *allloop;
1791         MPoly *allpoly;
1792         int totvert, totedge, totface, totloop, totpoly;
1793
1794         if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1795                 &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) {
1796                 /* Error initializing mdata. This often happens when curve is empty */
1797                 return CDDM_new(0, 0, 0, 0, 0);
1798         }
1799
1800         dm = CDDM_new(totvert, totedge, totface, totloop, totpoly);
1801         dm->deformedOnly = 1;
1802
1803         cddm = (CDDerivedMesh*)dm;
1804
1805         memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1806         memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1807         memcpy(cddm->mface, allface, totface*sizeof(MFace));
1808         memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop));
1809         memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly));
1810
1811         MEM_freeN(allvert);
1812         MEM_freeN(alledge);
1813         MEM_freeN(allface);
1814         MEM_freeN(allloop);
1815         MEM_freeN(allpoly);
1816
1817         return dm;
1818 }
1819
1820 static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
1821                                           int cdindex, BMLoop *l3[3],
1822                                           int numCol, int numTex)
1823 {
1824         BMLoop *l;
1825         BMFace *f = l3[0]->f;
1826         MTFace *texface;
1827         MTexPoly *texpoly;
1828         MCol *mcol;
1829         MLoopCol *mloopcol;
1830         MLoopUV *mloopuv;
1831         int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
1832
1833         for(i=0; i < numTex; i++){
1834                 texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
1835                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
1836                 
1837                 texface->tpage = texpoly->tpage;
1838                 texface->flag = texpoly->flag;
1839                 texface->transp = texpoly->transp;
1840                 texface->mode = texpoly->mode;
1841                 texface->tile = texpoly->tile;
1842                 texface->unwrap = texpoly->unwrap;
1843         
1844                 for (j=0; j<3; j++) {
1845                         l = l3[j];
1846                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
1847                         texface->uv[j][0] = mloopuv->uv[0];
1848                         texface->uv[j][1] = mloopuv->uv[1];
1849                 }
1850         }
1851
1852         for(i=0; i < numCol; i++){
1853                 mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
1854                 
1855                 for (j=0; j<3; j++) {
1856                         l = l3[j];
1857                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
1858                         mcol[j].r = mloopcol->r;
1859                         mcol[j].g = mloopcol->g;
1860                         mcol[j].b = mloopcol->b;
1861                         mcol[j].a = mloopcol->a;
1862                 }
1863         }
1864
1865         if (hasWCol) {
1866                 mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
1867
1868                 for (j=0; j<3; j++) {
1869                         l = l3[j];
1870                         mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
1871                         mcol[j].r = mloopcol->r;
1872                         mcol[j].g = mloopcol->g;
1873                         mcol[j].b = mloopcol->b;
1874                         mcol[j].a = mloopcol->a;
1875                 }
1876         }
1877 }
1878
1879 DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps)
1880 {
1881         DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, 
1882                                em->tottri, em->bm->totloop, em->bm->totface);
1883         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1884         BMesh *bm = em->bm;
1885         BMIter iter, liter;
1886         BMVert *eve;
1887         BMEdge *eed;
1888         BMFace *efa;
1889         MVert *mvert = cddm->mvert;
1890         MEdge *medge = cddm->medge;
1891         MFace *mface = cddm->mface;
1892         MLoop *mloop = cddm->mloop;
1893         MPoly *mpoly = cddm->mpoly;
1894         int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
1895         int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
1896         int i, j, *index, add_orig;
1897         int has_crease, has_edge_bweight, has_vert_bweight;
1898         int flag;
1899         
1900         has_edge_bweight = CustomData_has_layer(&em->bm->edata, CD_BWEIGHT);
1901         has_vert_bweight = CustomData_has_layer(&em->bm->vdata, CD_BWEIGHT);
1902         has_crease = CustomData_has_layer(&em->bm->edata, CD_CREASE);
1903         
1904         dm->deformedOnly = 1;
1905         
1906         /*don't add origindex layer if one already exists*/
1907         add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
1908
1909         flag = use_mdisps ? CD_MASK_DERIVEDMESH|CD_MASK_MDISPS : CD_MASK_DERIVEDMESH;
1910         
1911         /*don't process shapekeys, we only feed them through the modifier stack as needed,
1912       e.g. for applying modifiers or the like*/
1913         flag &= ~CD_SHAPEKEY;
1914         CustomData_merge(&em->bm->vdata, &dm->vertData, flag,
1915                          CD_CALLOC, dm->numVertData);
1916         CustomData_merge(&em->bm->edata, &dm->edgeData, flag,
1917                          CD_CALLOC, dm->numEdgeData);
1918         CustomData_merge(&em->bm->ldata, &dm->loopData, flag,
1919                          CD_CALLOC, dm->numLoopData);
1920         CustomData_merge(&em->bm->pdata, &dm->polyData, flag,
1921                          CD_CALLOC, dm->numPolyData);
1922         
1923         /*add tesselation mface layers*/
1924         CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
1925
1926         /* set vert index */
1927         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1928         for (i=0; eve; eve=BMIter_Step(&iter), i++)
1929                 BM_SetIndex(eve, i);
1930
1931         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1932
1933         eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1934         for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
1935                 MVert *mv = &mvert[i];
1936
1937                 VECCOPY(mv->co, eve->co);
1938
1939                 BM_SetIndex(eve, i);
1940
1941                 mv->no[0] = eve->no[0] * 32767.0;
1942                 mv->no[1] = eve->no[1] * 32767.0;
1943                 mv->no[2] = eve->no[2] * 32767.0;
1944
1945                 mv->flag = BMFlags_To_MEFlags(eve);
1946
1947                 if (has_vert_bweight)
1948                         mv->bweight = (unsigned char)(BM_GetCDf(&bm->vdata, eve, CD_BWEIGHT)*255.0f);
1949
1950                 if (add_orig) *index = i;
1951
1952                 CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
1953         }
1954
1955         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1956         eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1957         for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
1958                 MEdge *med = &medge[i];
1959
1960                 BM_SetIndex(eed, i);
1961
1962                 med->v1 = BM_GetIndex(eed->v1);
1963                 med->v2 = BM_GetIndex(eed->v2);
1964                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
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 }