remove unused vars
[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_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 *tm)
204 {
205         BMEdit_RecalcTesselation_intern(tm);
206
207         if (tm->derivedFinal && tm->derivedFinal == tm->derivedCage) {
208                 if (tm->derivedFinal->recalcTesselation) 
209                         tm->derivedFinal->recalcTesselation(tm->derivedFinal);
210         } else if (tm->derivedFinal) {
211                 if (tm->derivedCage->recalcTesselation) 
212                         tm->derivedCage->recalcTesselation(tm->derivedCage);
213                 if (tm->derivedFinal->recalcTesselation) 
214                         tm->derivedFinal->recalcTesselation(tm->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/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 static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type)
1302 {
1303         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1304         BMesh *bm= bmdm->tc->bm;
1305         BMFace *efa;
1306         char *data, *bmdata;
1307         void *datalayer;
1308         int index, offset, size, i;
1309
1310         datalayer = DM_get_tessface_data_layer(dm, type);
1311         if(datalayer)
1312                 return datalayer;
1313
1314         /* layers are store per face for editmesh, we convert to a tbmporary
1315          * data layer array in the derivedmesh when these are requested */
1316         if(type == CD_MTFACE || type == CD_MCOL) {
1317                 index = CustomData_get_layer_index(&bm->pdata, type);
1318
1319                 if(index != -1) {
1320                         offset = bm->pdata.layers[index].offset;
1321                         size = CustomData_sizeof(type);
1322
1323                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1324                         index = CustomData_get_layer_index(&dm->faceData, type);
1325                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1326
1327                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1328                         for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
1329                                 efa = bmdm->tc->looptris[i][0]->f;
1330                                 /*BMESH_TODO: need to still add tface data,
1331                                   derived from the loops.*/
1332                                 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
1333                                 memcpy(data, bmdata, size);
1334                         }
1335                 }
1336         }
1337
1338         return datalayer;
1339 }
1340
1341 typedef struct bmDM_loopIter {
1342         DMLoopIter head;
1343
1344         BMFace *f;
1345         BMLoop *l, *nextl;
1346         BMIter iter;
1347         BMesh *bm;
1348 } bmDM_loopIter;
1349
1350 typedef struct bmDM_faceIter {
1351         DMFaceIter head;
1352
1353         BMFace *f, *nextf;
1354         BMIter iter;
1355         BMesh *bm;
1356
1357         bmDM_loopIter loopiter;
1358 } bmDM_faceIter;
1359
1360 static void bmDM_faceIterStep(void *self)
1361 {
1362         bmDM_faceIter *iter = self;
1363         
1364         if (iter->f) {
1365                 iter->f->mat_nr = iter->head.mat_nr;
1366                 iter->f->head.flag = MEFlags_To_BMFlags(iter->head.flags, BM_FACE);
1367         }
1368
1369         iter->f = iter->nextf;
1370
1371         iter->head.mat_nr = iter->f->mat_nr;
1372         iter->head.flags = BMFlags_To_MEFlags(iter->f);
1373         iter->head.index++;
1374
1375         iter->head.len = iter->f->len;
1376
1377         iter->nextf = BMIter_Step(&iter->iter);
1378
1379         if (!iter->nextf) iter->head.done = 1;
1380 }
1381
1382 static void *bmDM_getFaceCDData(void *self, int type, int layer)
1383 {
1384         bmDM_faceIter *iter = self;
1385
1386         if (layer == -1) 
1387                 return CustomData_bmesh_get(&iter->bm->pdata, iter->f->head.data, type);
1388         else return CustomData_bmesh_get_n(&iter->bm->pdata, iter->f->head.data, type, layer);
1389 }
1390
1391 static void bmDM_loopIterStep(void *self)
1392 {
1393         bmDM_loopIter *iter = self;
1394
1395         iter->l = BMIter_Step(&iter->iter);
1396         if (!iter->l) {
1397                 iter->head.done = 1;
1398                 return;
1399         }
1400
1401         bmvert_to_mvert(iter->bm, iter->l->v, &iter->head.v);
1402         iter->head.index++;
1403         iter->head.vindex = BM_GetIndex(iter->l->v);
1404         iter->head.eindex = BM_GetIndex(iter->l->e);
1405 }
1406
1407 static void *bmDM_getLoopCDData(void *self, int type, int layer)
1408 {
1409         bmDM_loopIter *iter = self;
1410
1411         if (layer == -1) 
1412                 return CustomData_bmesh_get(&iter->bm->ldata, iter->l->head.data, type);
1413         else return CustomData_bmesh_get_n(&iter->bm->ldata, iter->l->head.data, type, layer);
1414 }
1415
1416 static void *bmDM_getVertCDData(void *self, int type, int layer)
1417 {
1418         bmDM_loopIter *iter = self;
1419
1420         if (layer == -1) 
1421                 return CustomData_bmesh_get(&iter->bm->vdata, iter->l->v->head.data, type);
1422         else return CustomData_bmesh_get_n(&iter->bm->vdata, iter->l->v->head.data, type, layer);
1423 }
1424
1425 static void bmDM_iterFree(void *self)
1426 {
1427         MEM_freeN(self);
1428 }
1429
1430 static void bmDM_nulliterFree(void *UNUSED(self))
1431 {
1432 }
1433
1434 static DMLoopIter *bmDM_newLoopsIter(void *faceiter)
1435 {
1436         bmDM_faceIter *fiter = faceiter;
1437         bmDM_loopIter *iter = &fiter->loopiter;
1438
1439         memset(&fiter->loopiter, 0, sizeof(bmDM_loopIter));
1440
1441         iter->bm = fiter->bm;
1442         iter->f = fiter->f;
1443         iter->l = BMIter_New(&iter->iter, iter->bm, BM_LOOPS_OF_FACE, iter->f);
1444
1445         iter->head.step = bmDM_loopIterStep;
1446         iter->head.getLoopCDData = bmDM_getLoopCDData;
1447         iter->head.getVertCDData = bmDM_getVertCDData;
1448
1449         bmvert_to_mvert(iter->bm, iter->l->v, &iter->head.v);
1450         iter->head.vindex = BM_GetIndex(iter->l->v);
1451         iter->head.eindex = BM_GetIndex(iter->l->e);
1452
1453         return (DMLoopIter*) iter;
1454 }
1455
1456 static DMFaceIter *bmDM_getFaceIter(DerivedMesh *dm)
1457 {
1458         EditDerivedBMesh *bmdm= (EditDerivedBMesh*)dm;
1459         bmDM_faceIter *iter = MEM_callocN(sizeof(bmDM_faceIter), "bmDM_faceIter");
1460         BMIter biter;
1461         BMVert *v;
1462         BMEdge *e;
1463         int i;
1464
1465         iter->bm = bmdm->tc->bm;
1466         iter->f = iter->nextf = BMIter_New(&iter->iter, iter->bm, BM_FACES_OF_MESH, NULL);
1467         
1468         iter->head.step = bmDM_faceIterStep;
1469         iter->head.free = bmDM_iterFree;
1470         iter->head.getCDData = bmDM_getFaceCDData;
1471         iter->head.getLoopsIter = bmDM_newLoopsIter;
1472         
1473         iter->head.mat_nr = iter->f->mat_nr;
1474         iter->head.flags = BMFlags_To_MEFlags(iter->f);
1475
1476         /*set up vert/edge indices*/
1477         i = 0;
1478         BM_ITER(v, &biter, iter->bm, BM_VERTS_OF_MESH, NULL) {
1479                 BM_SetIndex(v, i);
1480                 i++;
1481         }
1482
1483         i = 0;
1484         BM_ITER(e, &biter, iter->bm, BM_EDGES_OF_MESH, NULL) {
1485                 BM_SetIndex(e, i);
1486                 i++;
1487         }
1488
1489         return (DMFaceIter*) iter;
1490 }
1491
1492 static void bmDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1493 {
1494         EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1495         BMVert *eve;
1496         BMIter iter;
1497         int i;
1498
1499         i= 0;
1500         BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
1501                 if (emdm->vertexCos) {
1502                         copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1503                 } else {
1504                         copy_v3_v3(cos_r[i], eve->co);
1505                 }
1506                 
1507                 i++;
1508         }
1509 }
1510
1511 static void bmDM_release(DerivedMesh *dm)
1512 {
1513         EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1514
1515         if (DM_release(dm)) {
1516                 if (bmdm->vertexCos) {
1517                         MEM_freeN(bmdm->vertexCos);
1518                         MEM_freeN(bmdm->vertexNos);
1519                         MEM_freeN(bmdm->faceNos);
1520                 }
1521                 
1522                 if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
1523                 if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
1524                 if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
1525
1526                 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
1527                 if (bmdm->etable) MEM_freeN(bmdm->etable);
1528                 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
1529                 
1530                 MEM_freeN(bmdm);
1531         }
1532 }
1533
1534 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1535 {
1536         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1537
1538         return &bmdm->tc->bm->vdata;
1539 }
1540
1541 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1542 {
1543         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1544
1545         return &bmdm->tc->bm->edata;
1546 }
1547
1548 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1549 {
1550         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1551
1552         return &bmdm->dm.faceData;
1553 }
1554
1555 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1556 {
1557         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1558
1559         return &bmdm->tc->bm->ldata;
1560 }
1561
1562 static CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm)
1563 {
1564         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1565
1566         return &bmdm->tc->bm->pdata;
1567 }
1568
1569
1570 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *UNUSED(ob),
1571                                            float (*vertexCos)[3])
1572 {
1573         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), "bmdm");
1574         BMesh *bm = em->bm;
1575         
1576         bmdm->tc = em;
1577
1578         DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert, 
1579                  em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1580         
1581         CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
1582         
1583         bmdm->dm.numVertData = bm->totvert;
1584         bmdm->dm.numEdgeData = bm->totedge;
1585         bmdm->dm.numFaceData = em->tottri;
1586         bmdm->dm.numLoopData = bm->totloop;
1587         bmdm->dm.numPolyData = bm->totface;
1588         
1589         bmdm->dm.getVertCos = bmDM_getVertCos;
1590         bmdm->dm.getMinMax = bmDM_getMinMax;
1591
1592         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1593         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1594         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1595         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1596         bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout;
1597
1598         bmdm->dm.getNumVerts = bmDM_getNumVerts;
1599         bmdm->dm.getNumEdges = bmDM_getNumEdges;
1600         bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces;
1601         bmdm->dm.getNumFaces = bmDM_getNumFaces;
1602
1603         bmdm->dm.getVert = bmDM_getVert;
1604         bmdm->dm.getEdge = bmDM_getEdge;
1605         bmdm->dm.getTessFace = bmDM_getTessFace;
1606         bmdm->dm.copyVertArray = bmDM_copyVertArray;
1607         bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray;
1608         bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray;
1609         bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray;
1610
1611         bmdm->dm.newFaceIter = bmDM_getFaceIter;
1612         bmdm->dm.recalcTesselation = bmDM_recalcTesselation;
1613
1614         bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert;
1615         bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge;
1616         bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter;
1617
1618         bmdm->dm.drawEdges = bmDM_drawEdges;
1619         bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges;
1620         bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp;
1621         bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces;
1622         bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex;
1623         bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL;
1624         bmdm->dm.drawFacesTex = bmDM_drawFacesTex;
1625         bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL;
1626         bmdm->dm.drawUVEdges = bmDM_drawUVEdges;
1627
1628         bmdm->dm.release = bmDM_release;
1629         
1630         bmdm->vertexCos = vertexCos;
1631
1632         if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1633                 BMIter iter;
1634                 BMVert *eve;
1635                 int i;
1636
1637                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1638                 
1639                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1640                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1641                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1642                                          CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1643         }
1644
1645         if(vertexCos) {
1646                 BMVert *eve;
1647                 BMIter iter;
1648                 int totface = bmdm->tc->tottri;
1649                 int i;
1650                 
1651                 eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1652                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1653                         BM_SetIndex(eve, i);
1654
1655                 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos)*i, "bmdm_vno");
1656                 bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
1657
1658                 for (i=0; i<bmdm->tc->tottri; i++) {
1659                         BMLoop **l = bmdm->tc->looptris[i];
1660                         float *v1 = vertexCos[(int) BM_GetIndex(l[0]->v)];
1661                         float *v2 = vertexCos[(int) BM_GetIndex(l[1]->v)];
1662                         float *v3 = vertexCos[(int) BM_GetIndex(l[2]->v)];
1663                         float *no = bmdm->faceNos[i];
1664                         
1665                         normal_tri_v3( no,v1, v2, v3);
1666                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[0]->v)], bmdm->vertexNos[BM_GetIndex(l[0]->v)], no);
1667                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[1]->v)], bmdm->vertexNos[BM_GetIndex(l[1]->v)], no);
1668                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[2]->v)], bmdm->vertexNos[BM_GetIndex(l[2]->v)], no);
1669                 }
1670
1671                 eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1672                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1673                         float *no = bmdm->vertexNos[i];
1674                         /* following Mesh convention; we use vertex coordinate itself
1675                          * for normal in this case */
1676                         if (normalize_v3(no)==0.0) {
1677                                 VECCOPY(no, vertexCos[i]);
1678                                 normalize_v3(no);
1679                         }
1680                 }
1681         }
1682
1683         //bmdm_recalc_lookups(bmdm);
1684
1685         return (DerivedMesh*) bmdm;
1686 }