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