fixed crash on loop cut of wire edge
[blender-staging.git] / source / blender / blenkernel / intern / editderivedbmesh.c
1 /**
2  * $Id: editderivedbmesh.c 18571 2009-01-19 06:04:57Z joeedh $
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., 59 Tbmple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2005 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <string.h>
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include "PIL_time.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_effect_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_key_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_modifier_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_object_force.h"
47 #include "DNA_object_fluidsim.h" // N_T
48 #include "DNA_scene_types.h" // N_T
49 #include "DNA_texture_types.h"
50 #include "DNA_view3d_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_particle_types.h"
54
55 #include "BLI_utildefines.h"
56 #include "BLI_math.h"
57 #include "BLI_blenlib.h"
58 #include "BLI_editVert.h"
59 #include "BLI_edgehash.h"
60 #include "BLI_linklist.h"
61 #include "BLI_memarena.h"
62 #include "BLI_scanfill.h"
63 #include "BLI_ghash.h"
64 #include "BLI_array.h"
65
66 #include "BKE_cdderivedmesh.h"
67 #include "BKE_customdata.h"
68 #include "BKE_DerivedMesh.h"
69 #include "BKE_deform.h"
70 #include "BKE_displist.h"
71 #include "BKE_effect.h"
72 #include "BKE_fluidsim.h"
73 #include "BKE_global.h"
74 #include "BKE_key.h"
75 #include "BKE_material.h"
76 #include "BKE_modifier.h"
77 #include "BKE_mesh.h"
78 #include "BKE_object.h"
79 #include "BKE_subsurf.h"
80 #include "BKE_texture.h"
81 #include "BKE_particle.h"
82 #include "BKE_tessmesh.h"
83
84 #include "BLO_sys_types.h" // for intptr_t support
85
86 #include "BIF_gl.h"
87 #include "BIF_glutil.h"
88
89 #include "GPU_draw.h"
90 #include "GPU_extensions.h"
91 #include "GPU_material.h"
92
93 #include "bmesh.h"
94
95 BMEditMesh *BMEdit_Create(BMesh *bm)
96 {
97         BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), "tm");
98         
99         tm->bm = bm;
100
101         BMEdit_RecalcTesselation(tm);
102
103         return tm;
104 }
105
106 BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
107 {
108         BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), "tm2");
109         *tm2 = *tm;
110         
111         tm2->derivedCage = tm2->derivedFinal = NULL;
112         
113         tm2->looptris = NULL;
114         tm2->bm = BM_Copy_Mesh(tm->bm);
115         BMEdit_RecalcTesselation(tm2);
116
117         tm2->vert_index = NULL;
118         tm2->edge_index = NULL;
119         tm2->face_index = NULL;
120
121         return tm2;
122 }
123
124 static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
125 {
126         BMesh *bm = tm->bm;
127         BMLoop **looptris = NULL;
128         BLI_array_declare(looptris);
129         BMIter iter, liter;
130         BMFace *f;
131         BMLoop *l;
132         int i = 0, j;
133         
134         if (tm->looptris) MEM_freeN(tm->looptris);
135
136         f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
137         for ( ; f; f=BMIter_Step(&iter)) {
138                 EditVert *v, *lastv=NULL, *firstv=NULL;
139                 EditEdge *e;
140                 EditFace *efa;
141
142                 /*don't consider two-edged faces*/
143                 if (f->len < 3) continue;
144                 
145                 BLI_begin_edgefill();
146                 /*scanfill time*/
147                 l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
148                 for (j=0; l; l=BMIter_Step(&liter), j++) {
149                         /*mark order*/
150                         l->_index = j;
151
152                         v = BLI_addfillvert(l->v->co);
153                         v->tmp.p = l;
154                         
155                         if (lastv) {
156                                 e = BLI_addfilledge(lastv, v);
157                         }
158
159                         lastv = v;
160                         if (firstv==NULL) firstv = v;
161                 }
162
163                 /*complete the loop*/
164                 BLI_addfilledge(firstv, v);
165
166                 BLI_edgefill(2);
167                 
168                 for (efa = fillfacebase.first; efa; efa=efa->next) {
169                         BMLoop *l1, *l2, *l3;
170
171                         BLI_array_growone(looptris);
172                         BLI_array_growone(looptris);
173                         BLI_array_growone(looptris);
174                         
175                         looptris[i*3] = l1 = efa->v1->tmp.p;
176                         looptris[i*3+1] = l2 = efa->v2->tmp.p;
177                         looptris[i*3+2] = l3 = efa->v3->tmp.p;
178                         
179                         if (l1->_index > l2->_index) {
180                                 SWAP(BMLoop*, l1, l2);
181                         }
182                         if (l2->_index > l3->_index) {
183                                 SWAP(BMLoop*, l2, l3);
184                         }
185                         if (l1->_index > l2->_index) {
186                                 SWAP(BMLoop*, l1, l2);
187                         }
188                         
189                         looptris[i*3] = l1;
190                         looptris[i*3+1] = l2;
191                         looptris[i*3+2] = l3;
192
193                         i += 1;
194                 }
195
196                 BLI_end_edgefill();
197         }
198
199         tm->tottri = i;
200         tm->looptris = (BMLoop *(*)[3])looptris;
201 }
202
203 void BMEdit_RecalcTesselation(BMEditMesh *em)
204 {
205         BMEdit_RecalcTesselation_intern(em);
206
207         if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
208                 if (em->derivedFinal->recalcTesselation) 
209                         em->derivedFinal->recalcTesselation(em->derivedFinal);
210         } else if (em->derivedFinal) {
211                 if (em->derivedCage->recalcTesselation) 
212                         em->derivedCage->recalcTesselation(em->derivedCage);
213                 if (em->derivedFinal->recalcTesselation) 
214                         em->derivedFinal->recalcTesselation(em->derivedFinal);
215         }
216 }
217
218 void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
219 {
220         BMesh *bm = em->bm;
221         int act;
222
223         if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
224                 act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
225                 CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
226
227                 act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
228                 CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
229
230                 act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
231                 CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
232
233                 act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
234                 CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
235         }
236 }
237
238 /*does not free the BMEditMesh struct itself*/
239 void BMEdit_Free(BMEditMesh *em)
240 {
241         if(em->derivedFinal) {
242                 if (em->derivedFinal!=em->derivedCage) {
243                         em->derivedFinal->needsFree= 1;
244                         em->derivedFinal->release(em->derivedFinal);
245                 }
246                 em->derivedFinal= NULL;
247         }
248         if(em->derivedCage) {
249                 em->derivedCage->needsFree= 1;
250                 em->derivedCage->release(em->derivedCage);
251                 em->derivedCage= NULL;
252         }
253
254         em->retopo_paint_data= NULL;
255
256         if (em->looptris) MEM_freeN(em->looptris);
257
258         if (em->vert_index) MEM_freeN(em->vert_index);
259         if (em->edge_index) MEM_freeN(em->edge_index);
260         if (em->face_index) MEM_freeN(em->face_index);
261
262         if (em->bm)
263                 BM_Free_Mesh(em->bm);
264 }
265
266 /*
267 ok, basic design:
268
269 the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
270 to three loops per triangle.  the derivedmesh stores a cache of tesselations
271 for each face.  this cache will smartly update as needed (though at first
272 it'll simply be more brute force).  keeping track of face/edge counts may
273 be a small problbm.
274
275 this won't be the most efficient thing, considering that internal edges and
276 faces of tesselations are exposed.  looking up an edge by index in particular
277 is likely to be a little slow.
278 */
279
280 typedef struct EditDerivedBMesh {
281         DerivedMesh dm;
282
283         Object *ob;
284         BMEditMesh *tc;
285
286         float (*vertexCos)[3];
287         float (*vertexNos)[3];
288         float (*faceNos)[3];
289
290         /*lookup caches; these are rebuilt on dm->RecalcTesselation()
291           (or when the derivedmesh is created, of course)*/
292         GHash *vhash, *ehash, *fhash;
293         BMVert **vtable;
294         BMEdge **etable;
295         BMFace **ftable;
296
297         /*private variables, for number of verts/edges/faces
298           within the above hash/table members*/
299         int tv, te, tf;
300 } EditDerivedBMesh;
301
302 static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
303 {
304         BMIter iter;
305         BMHeader *h;
306         int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
307         
308         bmdm->tv = bmdm->tc->bm->totvert;
309         bmdm->te = bmdm->tc->bm->totedge;
310         bmdm->tf = bmdm->tc->bm->totface;
311
312         if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
313         if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
314         if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
315
316         bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
317         bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
318         bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
319         
320         if (bmdm->vtable) MEM_freeN(bmdm->vtable);
321         if (bmdm->etable) MEM_freeN(bmdm->etable);
322         if (bmdm->ftable) MEM_freeN(bmdm->ftable);
323         
324         if (bmdm->tc->bm->totvert)
325                 bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
326         else bmdm->vtable = NULL;
327
328         if (bmdm->tc->bm->totedge)
329                 bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
330         else bmdm->etable = NULL;
331         
332         if (bmdm->tc->bm->totface)
333                 bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
334         else bmdm->ftable = NULL;
335         
336         for (a=0; a<3; a++) {
337                 h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
338                 for (i=0; h; h=BMIter_Step(&iter), i++) {
339                         switch (a) {
340                                 case 0:
341                                         bmdm->vtable[i] = (BMVert*) h;
342                                         BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i));
343                                         break;
344                                 case 1:
345                                         bmdm->etable[i] = (BMEdge*) h;
346                                         BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i));
347                                         break;
348                                 case 2:
349                                         bmdm->ftable[i] = (BMFace*) h;
350                                         BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i));
351                                         break;
352
353                         }
354                 }
355         }
356 }
357
358 static void bmDM_recalcTesselation(DerivedMesh *UNUSED(dm))
359 {
360         //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
361
362         //bmdm_recalc_lookups(bmdm);
363 }
364
365 static void bmDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
366 {
367         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
368         BMVert *eve;
369         BMIter iter;
370         int i;
371         
372         eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
373         for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
374                 if (bmdm->vertexCos) {
375                         func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
376                 } else {
377                         func(userData, i, eve->co, eve->no, NULL);
378                 }
379         }
380 }
381 static void bmDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
382 {
383         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
384         BMEdge *eed;
385         BMIter iter;
386         int i;
387         
388         if (bmdm->vertexCos) {
389                 BMVert *eve;
390                 BMIter viter;
391
392                 eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
393                 for (i=0; eve; eve=BMIter_Step(&viter), i++) {
394                         BM_SetIndex(eve, i);
395                 }
396
397                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
398                 for(i=0; eed; i++,eed=BMIter_Step(&iter))
399                         func(userData, i, 
400                              bmdm->vertexCos[BM_GetIndex(eed->v1)], 
401                              bmdm->vertexCos[BM_GetIndex(eed->v2)]);
402         } else {
403                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
404                 for(i=0; eed; i++,eed=BMIter_Step(&iter))
405                         func(userData, i, eed->v1->co, eed->v2->co);
406         }
407
408 }
409
410 static void bmDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
411 {
412         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
413         BMEdge *eed;
414         BMIter iter;
415         int i;
416         
417         if (bmdm->vertexCos) {
418                 BMVert *eve;
419                 BMIter viter;
420
421                 eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
422                 for (i=0; eve; eve=BMIter_Step(&viter), i++) {
423                         BM_SetIndex(eve, i);
424                 }
425
426                 glBegin(GL_LINES);
427                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
428                 for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
429                         if(!setDrawOptions || setDrawOptions(userData, i)) {
430                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
431                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
432                         }
433                 }
434                 glEnd();
435
436         } else {
437                 glBegin(GL_LINES);
438                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
439                 for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
440                         if(!setDrawOptions || setDrawOptions(userData, i)) {
441                                 glVertex3fv(eed->v1->co);
442                                 glVertex3fv(eed->v2->co);
443                         }
444                 }
445                 glEnd();
446         }
447 }
448
449 static void bmDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges), int UNUSED(drawAllEdges))
450 {
451         bmDM_drawMappedEdges(dm, NULL, NULL);
452 }
453
454 static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) 
455 {
456         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
457         BMEdge *eed;
458         BMIter iter;
459         int i;
460
461         if (bmdm->vertexCos) {
462                 BMVert *eve;
463
464                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
465                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
466                         BM_SetIndex(eve, i);
467
468                 glBegin(GL_LINES);
469                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
470                 for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
471                         if(!setDrawOptions || setDrawOptions(userData, i)) {
472                                 setDrawInterpOptions(userData, i, 0.0);
473                                 glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v1)]);
474                                 setDrawInterpOptions(userData, i, 1.0);
475                                 glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v2)]);
476                         }
477                 }
478                 glEnd();
479         } else {
480                 glBegin(GL_LINES);
481                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
482                 for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
483                         if(!setDrawOptions || setDrawOptions(userData, i)) {
484                                 setDrawInterpOptions(userData, i, 0.0);
485                                 glVertex3fv(eed->v1->co);
486                                 setDrawInterpOptions(userData, i, 1.0);
487                                 glVertex3fv(eed->v2->co);
488                         }
489                 }
490                 glEnd();
491         }
492 }
493
494 static void bmDM_drawUVEdges(DerivedMesh *dm)
495 {
496         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
497         BMEditMesh *em = bmdm->tc;
498         BMFace *efa;
499         BMIter iter;
500
501         glBegin(GL_LINES);
502         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
503                 BMIter liter;
504                 BMLoop *l;
505                 MLoopUV *lastluv = NULL, *firstluv = NULL;
506                 
507                 if (BM_TestHFlag(efa, BM_HIDDEN))
508                         continue;
509                 
510                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
511                         MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
512                         
513                         if (luv) {
514                                 if (lastluv) 
515                                         glVertex2fv(luv->uv);
516                                 glVertex2fv(luv->uv);
517                                 
518                                 lastluv = luv;
519                                 if (!firstluv) 
520                                         firstluv = luv;
521                         }
522                 }
523                 
524                 if (lastluv) {
525                         glVertex2fv(lastluv->uv);
526                         glVertex2fv(firstluv->uv);
527                 }
528         }
529         glEnd();
530 }
531
532 static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], 
533                                                            float (*vertexCos)[3])
534 {
535         BMIter iter;
536         BMLoop *l;
537         int tot = 0;
538         
539         cent[0] = cent[1] = cent[2] = 0.0f;
540         
541         /*simple (and stupid) median (average) based method :/ */
542         
543         if (vertexCos) {
544                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
545                 for (; l; l=BMIter_Step(&iter)) {
546                         VECADD(cent, cent, vertexCos[BM_GetIndex(l->v)]);
547                         tot++;
548                 }
549         } else {
550                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
551                 for (; l; l=BMIter_Step(&iter)) {
552                         VECADD(cent, cent, l->v->co);
553                         tot++;
554                 }
555         }
556
557         if (tot==0) return;
558         mul_v3_fl(cent, 1.0f/(float)tot);
559 }
560
561 static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
562 {
563         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
564         BMVert *eve;
565         BMFace *efa;
566         BMIter iter;
567         float cent[3];
568         int i;
569
570         if (bmdm->vertexCos) {
571                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
572                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
573                         BM_SetIndex(eve, i);
574         }
575
576         efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
577         for (i=0; efa; efa=BMIter_Step(&iter), i++) {
578                 bmDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
579                 func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no);
580         }
581 }
582
583 static void bmDM_drawMappedFaces(DerivedMesh *dm, 
584         int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), 
585         void *userData, int useColors, 
586         int (*setMaterial)(int, void *attribs))
587 {
588         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
589         BMFace *efa;
590         BMIter iter;
591         int i, draw;
592
593         /*BMESH_TODO*/
594         (void)useColors;
595         (void)setMaterial;
596
597         if (bmdm->vertexCos) {
598                 BMVert *eve;
599                 
600                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
601                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
602                         BM_SetIndex(eve, i);
603
604                 efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
605                 for (i=0; efa; efa=BMIter_Step(&iter), i++)
606                         BM_SetIndex(efa, i);
607
608                 for (i=0; i<bmdm->tc->tottri; i++) {
609                         BMLoop **l = bmdm->tc->looptris[i];
610                         int drawSmooth;
611                         
612                         efa = l[0]->f;
613                         drawSmooth = (efa->head.flag & BM_SMOOTH);
614
615                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
616                         if(draw) {
617                                 if (draw==2) { /* enabled with stipple */
618                                         glEnable(GL_POLYGON_STIPPLE);
619                                         glPolygonStipple(stipple_quarttone);
620                                 }
621                                 
622                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
623
624                                 glBegin(GL_TRIANGLES);
625
626                                 if (!drawSmooth) {
627                                         glNormal3fv(bmdm->faceNos[i]);
628                                         glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(l[0]->v)]);
629                                         glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(l[1]->v)]);
630                                         glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(l[2]->v)]);
631                                 } else {
632                                         glNormal3fv(bmdm->vertexNos[(int) BM_GetIndex(l[0]->v)]);
633                                         glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(l[0]->v)]);
634                                         glNormal3fv(bmdm->vertexNos[(int) BM_GetIndex(l[1]->v)]);
635                                         glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(l[1]->v)]);
636                                         glNormal3fv(bmdm->vertexNos[(int) BM_GetIndex(l[2]->v)]);
637                                         glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(l[2]->v)]);
638                                 }
639                                 glEnd();
640
641                                 if (draw==2)
642                                         glDisable(GL_POLYGON_STIPPLE);
643                         }
644                 }
645         } else {
646                 efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
647                 for (i=0; efa; efa=BMIter_Step(&iter), i++)
648                         BM_SetIndex(efa, i);
649
650                 for (i=0; i<bmdm->tc->tottri; i++) {
651                         BMLoop **l = bmdm->tc->looptris[i];
652                         int drawSmooth;
653
654                         efa = l[0]->f;
655                         drawSmooth = (efa->head.flag & BM_SMOOTH);
656                         
657                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
658                         if(draw) {
659                                 if (draw==2) { /* enabled with stipple */
660                                         glEnable(GL_POLYGON_STIPPLE);
661                                         glPolygonStipple(stipple_quarttone);
662                                 }
663                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
664                                 
665                                 glBegin(GL_TRIANGLES);
666                                 if (!drawSmooth) {
667                                         glNormal3fv(efa->no);
668                                         glVertex3fv(l[0]->v->co);
669                                         glVertex3fv(l[1]->v->co);
670                                         glVertex3fv(l[2]->v->co);
671                                 } else {
672                                         glNormal3fv(l[0]->v->no);
673                                         glVertex3fv(l[0]->v->co);
674                                         glNormal3fv(l[1]->v->no);
675                                         glVertex3fv(l[1]->v->co);
676                                         glNormal3fv(l[2]->v->no);
677                                         glVertex3fv(l[2]->v->co);
678                                 }
679                                 glEnd();
680                                 
681                                 if (draw==2)
682                                         glDisable(GL_POLYGON_STIPPLE);
683                         }
684                 }
685         }
686 }
687
688 static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3], 
689                              int has_uv, int has_col)
690 {
691         if (has_uv) { 
692                 luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
693                 luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
694                 luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
695         }
696
697         if (has_col) {
698                 lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
699                 lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
700                 lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
701         }
702
703
704 }
705
706 static void bmDM_drawFacesTex_common(DerivedMesh *dm,
707                int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
708                int (*drawParamsMapped)(void *userData, int index),
709                void *userData) 
710 {
711         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
712         BMEditMesh *em = bmdm->tc;
713         BMesh *bm= bmdm->tc->bm;
714         float (*vertexCos)[3]= bmdm->vertexCos;
715         float (*vertexNos)[3]= bmdm->vertexNos;
716         BMFace *efa;
717         BMVert *eve;
718         BMIter iter;
719         MLoopUV *luv[3], dummyluv = {{0}};
720         MLoopCol *lcol[3], dummylcol = {0};
721         int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
722         int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
723         
724         luv[0] = luv[1] = luv[2] = &dummyluv;
725         lcol[0] = lcol[1] = lcol[2] = &dummylcol;
726
727         dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
728
729         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
730         glShadeModel(GL_SMOOTH);
731         
732         i = 0;
733         BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL)
734                 BM_SetIndex(efa, i++);
735
736         if (vertexCos) {
737                 i = 0;
738                 BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
739                         BM_SetIndex(eve, i++);
740                                 
741                 glBegin(GL_TRIANGLES);
742                 for (i=0; i<em->tottri; i++) {
743                         BMLoop **ls = em->looptris[i];
744                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
745                         MTFace mtf = {{{0}}};
746                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
747                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
748                         int flag;
749
750                         efa = ls[0]->f;
751                         
752                         if (has_uv) {
753                                 mtf.flag = tp->flag;
754                                 mtf.tpage = tp->tpage;
755                                 mtf.transp = tp->transp;
756                                 mtf.mode = tp->mode;
757                                 mtf.tile = tp->tile;
758                                 mtf.unwrap = tp->unwrap;
759                         }
760
761                         if(drawParams)
762                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
763                         else if(drawParamsMapped)
764                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
765                         else
766                                 flag= 1;
767
768                         if(flag != 0) { /* flag 0 == the face is hidden or invisible */
769                                 
770                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
771                                 if (!has_vcol) {
772                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
773                                 } 
774                                 
775                                 if (!drawSmooth) {
776                                         glNormal3fv(bmdm->faceNos[i]);
777                                         
778                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
779                                         
780                                         glTexCoord2fv(luv[0]->uv);
781                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
782                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
783
784                                         glTexCoord2fv(luv[1]->uv);
785                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
786                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
787
788                                         glTexCoord2fv(luv[2]->uv);
789                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
790                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
791                                 } else {
792                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
793                                         
794                                         glTexCoord2fv(luv[0]->uv);
795                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
796                                         glNormal3fv(vertexNos[BM_GetIndex(ls[0]->v)]);
797                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
798
799                                         glTexCoord2fv(luv[1]->uv);
800                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
801                                         glNormal3fv(vertexNos[BM_GetIndex(ls[1]->v)]);
802                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
803
804                                         glTexCoord2fv(luv[2]->uv);
805                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
806                                         glNormal3fv(vertexNos[BM_GetIndex(ls[2]->v)]);
807                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
808                                 }
809                         }
810                 }
811                 glEnd();
812         } else {
813                 i = 0;
814                 BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
815                         BM_SetIndex(eve, i++);
816                                 
817                 for (i=0; i<em->tottri; i++) {
818                         BMLoop **ls = em->looptris[i];
819                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
820                         MTFace mtf = {{{0}}};
821                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
822                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
823                         int flag;
824
825                         efa = ls[0]->f;
826                         
827                         if (has_uv) {
828                                 mtf.flag = tp->flag;
829                                 mtf.tpage = tp->tpage;
830                                 mtf.transp = tp->transp;
831                                 mtf.mode = tp->mode;
832                                 mtf.tile = tp->tile;
833                                 mtf.unwrap = tp->unwrap;
834                         }
835
836                         if(drawParams)
837                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
838                         else if(drawParamsMapped)
839                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
840                         else
841                                 flag= 1;
842
843                         if(flag != 0) { /* flag 0 == the face is hidden or invisible */
844                                 
845                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
846                                 if (!has_vcol) {
847                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
848                                 } 
849                                 
850                                 glBegin(GL_TRIANGLES);
851                                 if (!drawSmooth) {
852                                         glNormal3fv(efa->no);
853                                         
854                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
855                                         
856                                         if (luv[0])
857                                                 glTexCoord2fv(luv[0]->uv);
858                                         if (lcol[0])
859                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
860                                         else glColor3ub(0, 0, 0);
861                                         glVertex3fv(ls[0]->v->co);
862
863                                         if (luv[1])
864                                                 glTexCoord2fv(luv[1]->uv);
865                                         if (lcol[1])
866                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
867                                         else glColor3ub(0, 0, 0);
868                                         glVertex3fv(ls[1]->v->co);
869
870                                         if (luv[2])
871                                                 glTexCoord2fv(luv[2]->uv);
872                                         if (lcol[2])
873                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
874                                         else glColor3ub(0, 0, 0);
875                                         glVertex3fv(ls[2]->v->co);
876                                 } else {
877                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
878                                         
879                                         if (luv[0])
880                                                 glTexCoord2fv(luv[0]->uv);
881                                         if (lcol[0])
882                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
883                                         else glColor3ub(0, 0, 0);
884                                         glNormal3fv(ls[0]->v->no);
885                                         glVertex3fv(ls[0]->v->co);
886
887                                         if (luv[1])
888                                                 glTexCoord2fv(luv[1]->uv);
889                                         if (lcol[1])
890                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
891                                         else glColor3ub(0, 0, 0);
892                                         glNormal3fv(ls[1]->v->no);
893                                         glVertex3fv(ls[1]->v->co);
894
895                                         if (luv[2])
896                                                 glTexCoord2fv(luv[2]->uv);
897                                         if (lcol[2])
898                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
899                                         else glColor3ub(0, 0, 0);
900                                         glNormal3fv(ls[2]->v->no);
901                                         glVertex3fv(ls[2]->v->co);
902                                 }
903                                 glEnd();
904                         }
905                 }
906         }
907 }
908
909 static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
910 {
911         bmDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
912 }
913
914 static void bmDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
915 {
916         bmDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
917 }
918
919 static void bmDM_drawMappedFacesGLSL(DerivedMesh *dm,
920                int (*setMaterial)(int, void *attribs),
921                int (*setDrawOptions)(void *userData, int index), void *userData)
922 {
923 #if 0
924         (void)dm;
925         (void)setMaterial;
926         (void)setDrawOptions;
927         (void)userData;
928 #else /*BMESH_TODO*/
929
930         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
931         BMesh *bm= bmdm->tc->bm;
932         BMEditMesh *em = bmdm->tc;
933         float (*vertexCos)[3]= bmdm->vertexCos;
934         float (*vertexNos)[3]= bmdm->vertexNos;
935         BMVert *eve;
936         BMFace *efa;
937         BMIter iter;
938         BMLoop **ltri;
939         DMVertexAttribs attribs;
940         GPUVertexAttribs gattribs;
941         MTexPoly *tp;
942         int transp, new_transp, orig_transp;
943         int i, b, matnr, new_matnr, dodraw;
944
945         dodraw = 0;
946         matnr = -1;
947
948         transp = GPU_get_material_blend_mode();
949         orig_transp = transp;
950
951         memset(&attribs, 0, sizeof(attribs));
952
953         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
954         glShadeModel(GL_SMOOTH);
955         BM_ITER_INDEX(eve, &iter, bm, BM_VERTS_OF_MESH, NULL, i) {
956                  BM_SetIndex(eve, i);
957         }
958
959 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
960         if(attribs.totorco) {                                                                                                           \
961                 float *orco = attribs.orco.array[BM_GetIndex(eve)];                                             \
962                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
963         }                                                                                                                                                       \
964         for(b = 0; b < attribs.tottface; b++) {                                                                         \
965                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
966                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
967         }                                                                                                                                                       \
968         for(b = 0; b < attribs.totmcol; b++) {                                                                          \
969                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
970                 GLubyte _col[4];                                                                                                                \
971                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
972                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
973         }                                                                                                                                                       \
974         if(attribs.tottang) {                                                                                                           \
975                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
976                 glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
977         }                                                                                                                                                       \
978         }
979         
980         BM_ITER_INDEX(efa, &iter, bm, BM_FACES_OF_MESH, NULL, i) {
981                 BM_SetIndex(efa, i);
982         }
983         
984         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
985                 int drawSmooth;
986
987                 efa = ltri[0]->f;
988                 drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
989                 
990                 if(setDrawOptions && !setDrawOptions(userData, BM_GetIndex(efa)))
991                         continue;
992
993                 new_matnr = efa->mat_nr + 1;
994                 if(new_matnr != matnr) {
995                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
996                         if(dodraw)
997                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
998                 }
999
1000                 if(attribs.tottface) {
1001                         tp = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
1002                         new_transp = tp->transp;
1003
1004                         if(new_transp != transp) {
1005                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1006                                         GPU_set_material_blend_mode(orig_transp);
1007                                 else
1008                                         GPU_set_material_blend_mode(new_transp);
1009                                 transp = new_transp;
1010                         }
1011                 }
1012
1013                 if(dodraw) {
1014                         glBegin(GL_TRIANGLES);
1015                         if (!drawSmooth) {
1016                                 if(vertexCos) glNormal3fv(bmdm->faceNos[i]);
1017                                 else glNormal3fv(efa->no);
1018
1019                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1020                                 if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1021                                 else glVertex3fv(ltri[0]->v->co);
1022
1023                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1024                                 if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1025                                 else glVertex3fv(ltri[1]->v->co);
1026
1027                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1028                                 if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1029                                 else glVertex3fv(ltri[2]->v->co);
1030                         } else {
1031                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1032                                 if(vertexCos) {
1033                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1034                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1035                                 }
1036                                 else {
1037                                         glNormal3fv(ltri[0]->v->no);
1038                                         glVertex3fv(ltri[0]->v->co);
1039                                 }
1040
1041                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1042                                 if(vertexCos) {
1043                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1044                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1045                                 }
1046                                 else {
1047                                         glNormal3fv(ltri[1]->v->no);
1048                                         glVertex3fv(ltri[1]->v->co);
1049                                 }
1050
1051                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1052                                 if(vertexCos) {
1053                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1054                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1055                                 }
1056                                 else {
1057                                         glNormal3fv(ltri[2]->v->no);
1058                                         glVertex3fv(ltri[2]->v->co);
1059                                 }
1060                         }
1061                         glEnd();
1062                 }
1063         }
1064 #endif
1065 }
1066
1067 static void bmDM_drawFacesGLSL(DerivedMesh *dm,
1068                int (*setMaterial)(int, void *attribs))
1069 {
1070         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1071 }
1072
1073 static void bmDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1074 {
1075         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1076         BMVert *eve;
1077         BMIter iter;
1078         int i;
1079
1080         if (bmdm->tc->bm->totvert) {
1081                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1082                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1083                         if (bmdm->vertexCos) {
1084                                 DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
1085                         } else {
1086                                 DO_MINMAX(eve->co, min_r, max_r);
1087                         }
1088                 }
1089         } else {
1090                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1091         }
1092 }
1093 static int bmDM_getNumVerts(DerivedMesh *dm)
1094 {
1095         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1096
1097         return bmdm->tc->bm->totvert;
1098 }
1099
1100 static int bmDM_getNumEdges(DerivedMesh *dm)
1101 {
1102         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1103
1104         return bmdm->tc->bm->totedge;
1105 }
1106
1107 static int bmDM_getNumTessFaces(DerivedMesh *dm)
1108 {
1109         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1110         
1111         return bmdm->tc->tottri;
1112 }
1113
1114 static int bmDM_getNumFaces(DerivedMesh *dm)
1115 {
1116         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1117         
1118         return bmdm->tc->bm->totface;
1119 }
1120
1121 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1122 {
1123         VECCOPY(vert_r->co, ev->co);
1124
1125         vert_r->no[0] = (short)(ev->no[0] * 32767.0f);
1126         vert_r->no[1] = (short)(ev->no[1] * 32767.0f);
1127         vert_r->no[2] = (short)(ev->no[2] * 32767.0f);
1128
1129         vert_r->flag = BMFlags_To_MEFlags(ev);
1130
1131         if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1132                 vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1133         }
1134
1135         return 1;
1136 }
1137
1138 static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1139 {
1140         BMVert *ev;
1141
1142         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
1143                 printf("error in bmDM_getVert.\n");
1144                 return;
1145         }
1146
1147         ev = ((EditDerivedBMesh *)dm)->vtable[index];
1148         bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r);
1149 }
1150
1151 static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1152 {
1153         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1154         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1155         BMEdge *e;
1156
1157         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
1158                 printf("error in bmDM_getEdge.\n");
1159                 return;
1160         }
1161
1162         e = bmdm->etable[index];
1163
1164         if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1165                 edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f);
1166         }
1167
1168         if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1169                 edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f);
1170         }
1171
1172         edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
1173         edge_r->flag |= BMFlags_To_MEFlags(e);
1174 #if 0
1175         /* this needs setup of f2 field */
1176         if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
1177 #endif
1178         
1179         edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1));
1180         edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2));
1181 }
1182
1183 static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1184 {
1185         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1186         BMFace *ef;
1187         BMLoop **l;
1188         
1189         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
1190                 printf("error in bmDM_getTessFace.\n");
1191                 return;
1192         }
1193
1194         l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
1195
1196         ef = l[0]->f;
1197
1198         face_r->mat_nr = (unsigned char) ef->mat_nr;
1199         face_r->flag = BMFlags_To_MEFlags(ef);
1200
1201         face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v));
1202         face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v));
1203         face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v));
1204         face_r->v4 = 0;
1205
1206         test_index_face(face_r, NULL, 0, 3);
1207 }
1208
1209 static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1210 {
1211         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1212         BMVert *ev;
1213         BMIter iter;
1214
1215         ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1216         for( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
1217                 VECCOPY(vert_r->co, ev->co);
1218
1219                 vert_r->no[0] = (short) (ev->no[0] * 32767.0);
1220                 vert_r->no[1] = (short) (ev->no[1] * 32767.0);
1221                 vert_r->no[2] = (short) (ev->no[2] * 32767.0);
1222
1223                 vert_r->flag = BMFlags_To_MEFlags(ev);
1224
1225                 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1226                         vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1227                 }
1228         }
1229 }
1230
1231 static void bmDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1232 {
1233         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1234         BMEdge *ee;
1235         BMIter iter;
1236         BMVert *ev;
1237         int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1238         int i, has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1239
1240         /* store vertex indices in tmp union */
1241         ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1242         for (i=0; ev; ev=BMIter_Step(&iter), i++)
1243                 BM_SetIndex(ev, i);
1244
1245         ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1246         for( ; ee; ee=BMIter_Step(&iter)) {
1247                 if (has_bweight) {
1248                         edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f);
1249                 }
1250
1251                 if (has_crease) {
1252                         edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f);
1253                 }
1254
1255                 edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
1256                 if (ee->head.flag & BM_SEAM) edge_r->flag |= ME_SEAM;
1257                 if (ee->head.flag & BM_SHARP) edge_r->flag |= ME_SHARP;
1258 #if 0
1259                 /* this needs setup of f2 (edge draw flags, if I remember right) field */
1260                 if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
1261 #endif
1262
1263                 edge_r->v1 = (int)BM_GetIndex(ee->v1);
1264                 edge_r->v2 = (int)BM_GetIndex(ee->v2);
1265         }
1266 }
1267
1268 static void bmDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
1269 {
1270         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1271         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1272         BMFace *ef;
1273         BMVert *ev;
1274         BMIter iter;
1275         BMLoop **l;
1276         int i;
1277
1278         /* store vertexes indices in tmp union */
1279         ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1280         for (i=0; ev; ev=BMIter_Step(&iter), i++)
1281                 BM_SetIndex(ev, i);
1282
1283         for (i=0; i<bmdm->tc->tottri; i++) {
1284                 l = bmdm->tc->looptris[i];
1285                 ef = l[0]->f;
1286
1287                 face_r->mat_nr = (unsigned char) ef->mat_nr;
1288
1289                 /*HACK/BMESH_TODO: need to convert this*/
1290                 face_r->flag = ef->head.flag;
1291
1292                 face_r->v1 = BM_GetIndex(l[0]->v);
1293                 face_r->v2 = BM_GetIndex(l[1]->v);
1294                 face_r->v3 = BM_GetIndex(l[2]->v);
1295                 face_r->v4 = 0;
1296
1297                 test_index_face(face_r, NULL, 0, 3);
1298         }
1299 }
1300
1301
1302 static void bmDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1303 {
1304         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1305         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1306         BMIter iter, liter;
1307         BMVert *v;
1308         BMFace *f;
1309         BMLoop *l;
1310         BMEdge *e;
1311         int i;
1312
1313         i = 0;
1314         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
1315                 BM_SetIndex(v, i++);
1316         }
1317
1318         i = 0;
1319         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
1320                 BM_SetIndex(e, i++);
1321         }
1322
1323         i = 0;
1324         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1325                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
1326                         loop_r[i].v = BM_GetIndex(l->v);
1327                         loop_r[i].e = BM_GetIndex(l->e);
1328                         i++;
1329                 }
1330         }
1331 }
1332
1333 static void bmDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1334 {
1335         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1336         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1337         BMIter iter;
1338         BMFace *f;
1339         int i, j;
1340
1341         i = j = 0;
1342         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1343                 poly_r[i].flag = BMFlags_To_MEFlags(f);
1344                 poly_r[i].loopstart = j;
1345                 poly_r[i].totloop = f->len;
1346                 poly_r[i].mat_nr = f->mat_nr;
1347
1348                 i++;
1349                 j += f->len;
1350         }
1351 }
1352
1353 static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type)
1354 {
1355         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1356         BMesh *bm= bmdm->tc->bm;
1357         BMFace *efa;
1358         char *data, *bmdata;
1359         void *datalayer;
1360         int index, offset, size, i;
1361
1362         datalayer = DM_get_tessface_data_layer(dm, type);
1363         if(datalayer)
1364                 return datalayer;
1365
1366         /* layers are store per face for editmesh, we convert to a tbmporary
1367          * data layer array in the derivedmesh when these are requested */
1368         if(type == CD_MTFACE || type == CD_MCOL) {
1369                 index = CustomData_get_layer_index(&bm->pdata, type);
1370
1371                 if(index != -1) {
1372                         offset = bm->pdata.layers[index].offset;
1373                         size = CustomData_sizeof(type);
1374
1375                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1376                         index = CustomData_get_layer_index(&dm->faceData, type);
1377                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1378
1379                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1380                         for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
1381                                 efa = bmdm->tc->looptris[i][0]->f;
1382                                 /*BMESH_TODO: need to still add tface data,
1383                                   derived from the loops.*/
1384                                 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
1385                                 memcpy(data, bmdata, size);
1386                         }
1387                 }
1388         }
1389
1390         return datalayer;
1391 }
1392
1393 static void bmDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1394 {
1395         EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1396         BMVert *eve;
1397         BMIter iter;
1398         int i;
1399
1400         i= 0;
1401         BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
1402                 if (emdm->vertexCos) {
1403                         copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1404                 } else {
1405                         copy_v3_v3(cos_r[i], eve->co);
1406                 }
1407                 
1408                 i++;
1409         }
1410 }
1411
1412 static void bmDM_release(DerivedMesh *dm)
1413 {
1414         EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1415
1416         if (DM_release(dm)) {
1417                 if (bmdm->vertexCos) {
1418                         MEM_freeN(bmdm->vertexCos);
1419                         MEM_freeN(bmdm->vertexNos);
1420                         MEM_freeN(bmdm->faceNos);
1421                 }
1422                 
1423                 if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
1424                 if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
1425                 if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
1426
1427                 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
1428                 if (bmdm->etable) MEM_freeN(bmdm->etable);
1429                 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
1430                 
1431                 MEM_freeN(bmdm);
1432         }
1433 }
1434
1435 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1436 {
1437         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1438
1439         return &bmdm->tc->bm->vdata;
1440 }
1441
1442 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1443 {
1444         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1445
1446         return &bmdm->tc->bm->edata;
1447 }
1448
1449 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1450 {
1451         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1452
1453         return &bmdm->dm.faceData;
1454 }
1455
1456 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1457 {
1458         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1459
1460         return &bmdm->tc->bm->ldata;
1461 }
1462
1463 static CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm)
1464 {
1465         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1466
1467         return &bmdm->tc->bm->pdata;
1468 }
1469
1470
1471 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *UNUSED(ob),
1472                                            float (*vertexCos)[3])
1473 {
1474         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), "bmdm");
1475         BMesh *bm = em->bm;
1476         
1477         bmdm->tc = em;
1478
1479         DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert, 
1480                  em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1481         
1482         CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
1483         
1484         bmdm->dm.numVertData = bm->totvert;
1485         bmdm->dm.numEdgeData = bm->totedge;
1486         bmdm->dm.numFaceData = em->tottri;
1487         bmdm->dm.numLoopData = bm->totloop;
1488         bmdm->dm.numPolyData = bm->totface;
1489         
1490         bmdm->dm.getVertCos = bmDM_getVertCos;
1491         bmdm->dm.getMinMax = bmDM_getMinMax;
1492
1493         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1494         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1495         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1496         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1497         bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout;
1498
1499         bmdm->dm.getNumVerts = bmDM_getNumVerts;
1500         bmdm->dm.getNumEdges = bmDM_getNumEdges;
1501         bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces;
1502         bmdm->dm.getNumFaces = bmDM_getNumFaces;
1503
1504         bmdm->dm.getVert = bmDM_getVert;
1505         bmdm->dm.getEdge = bmDM_getEdge;
1506         bmdm->dm.getTessFace = bmDM_getTessFace;
1507         bmdm->dm.copyVertArray = bmDM_copyVertArray;
1508         bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray;
1509         bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray;
1510         bmdm->dm.copyLoopArray = bmDM_copyLoopArray;
1511         bmdm->dm.copyPolyArray = bmDM_copyPolyArray;
1512
1513         bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray;
1514
1515         bmdm->dm.recalcTesselation = bmDM_recalcTesselation;
1516
1517         bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert;
1518         bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge;
1519         bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter;
1520
1521         bmdm->dm.drawEdges = bmDM_drawEdges;
1522         bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges;
1523         bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp;
1524         bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces;
1525         bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex;
1526         bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL;
1527         bmdm->dm.drawFacesTex = bmDM_drawFacesTex;
1528         bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL;
1529         bmdm->dm.drawUVEdges = bmDM_drawUVEdges;
1530
1531         bmdm->dm.release = bmDM_release;
1532         
1533         bmdm->vertexCos = vertexCos;
1534
1535         if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1536                 BMIter iter;
1537                 BMVert *eve;
1538                 int i;
1539
1540                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1541                 
1542                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1543                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1544                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1545                                          CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1546         }
1547
1548         if(vertexCos) {
1549                 BMVert *eve;
1550                 BMIter iter;
1551                 int totface = bmdm->tc->tottri;
1552                 int i;
1553                 
1554                 eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1555                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1556                         BM_SetIndex(eve, i);
1557
1558                 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos)*i, "bmdm_vno");
1559                 bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
1560
1561                 for (i=0; i<bmdm->tc->tottri; i++) {
1562                         BMLoop **l = bmdm->tc->looptris[i];
1563                         float *v1 = vertexCos[(int) BM_GetIndex(l[0]->v)];
1564                         float *v2 = vertexCos[(int) BM_GetIndex(l[1]->v)];
1565                         float *v3 = vertexCos[(int) BM_GetIndex(l[2]->v)];
1566                         float *no = bmdm->faceNos[i];
1567                         
1568                         normal_tri_v3( no,v1, v2, v3);
1569                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[0]->v)], bmdm->vertexNos[BM_GetIndex(l[0]->v)], no);
1570                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[1]->v)], bmdm->vertexNos[BM_GetIndex(l[1]->v)], no);
1571                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[2]->v)], bmdm->vertexNos[BM_GetIndex(l[2]->v)], no);
1572                 }
1573
1574                 eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1575                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1576                         float *no = bmdm->vertexNos[i];
1577                         /* following Mesh convention; we use vertex coordinate itself
1578                          * for normal in this case */
1579                         if (normalize_v3(no)==0.0) {
1580                                 VECCOPY(no, vertexCos[i]);
1581                                 normalize_v3(no);
1582                         }
1583                 }
1584         }
1585
1586         //bmdm_recalc_lookups(bmdm);
1587
1588         return (DerivedMesh*) bmdm;
1589 }