2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2005 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/editderivedmesh.c
38 #include "BLI_utildefines.h"
39 #include "BLI_blenlib.h"
40 #include "BLI_edgehash.h"
41 #include "BLI_editVert.h"
45 #include "BKE_cdderivedmesh.h"
46 #include "BKE_global.h"
48 #include "BKE_paint.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_curve_types.h" /* for Curve */
55 #include "MEM_guardedalloc.h"
57 #include "GPU_buffers.h"
59 #include "GPU_extensions.h"
60 #include "GPU_material.h"
63 #include "BKE_tessmesh.h"
64 #include "BLI_array.h"
65 #include "BLI_scanfill.h"
70 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
73 BMEditMesh *BMEdit_Create(BMesh *bm, int do_tesselate)
75 BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
79 BMEdit_RecalcTesselation(tm);
85 BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
87 BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
90 tm2->derivedCage = tm2->derivedFinal = NULL;
92 tm2->bm = BM_Copy_Mesh(tm->bm);
94 /*The tesselation is NOT calculated on the copy here,
95 because currently all the callers of this function use
96 it to make a backup copy of the BMEditMesh to restore
97 it in the case of errors in an operation. For perf
98 reasons, in that case it makes more sense to do the
99 tesselation only when/if that copy ends up getting
101 tm2->looptris = NULL;
103 tm2->vert_index = NULL;
104 tm2->edge_index = NULL;
105 tm2->face_index = NULL;
110 static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
112 /* use this to avoid locking pthread for _every_ polygon
113 * and calling the fill function */
114 #define USE_TESSFACE_SPEEDUP
117 BMLoop *(*looptris)[3]= NULL;
118 BLI_array_declare(looptris);
125 /* note, we could be clever and re-use this array but would need to ensure
126 * its realloced at some point, for now just free it */
127 if (tm->looptris) MEM_freeN(tm->looptris);
129 /* Use tm->tottri when set, this means no reallocs while transforming,
130 * (unless scanfill fails), otherwise... */
131 /* allocate the length of totfaces, avoid many small reallocs,
132 * if all faces are tri's it will be correct, quads == 2x allocs */
133 BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
136 /* this means no reallocs for quad dominant models, for */
137 if ( (tm->looptris != NULL) &&
139 /* (totrti <= bm->totface * 2) would be fine for all quads,
140 * but incase there are some ngons, still re-use the array */
141 (tm->tottri <= bm->totface * 3))
143 looptris = tm->looptris;
146 if (tm->looptris) MEM_freeN(tm->looptris);
147 BLI_array_reserve(looptris, bm->totface);
152 f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
153 for ( ; f; f=BMIter_Step(&iter)) {
154 /*don't consider two-edged faces*/
159 #ifdef USE_TESSFACE_SPEEDUP
161 /* no need to ensure the loop order, we know its ok */
163 else if (f->len == 3) {
164 BLI_array_growone(looptris);
165 l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
166 for (j=0; l; l=BMIter_Step(&liter), j++) {
171 else if (f->len == 4) {
173 BLI_array_growitems(looptris, 2);
175 l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
176 for (j=0; l; l=BMIter_Step(&liter), j++) {
180 looptris[i][0] = ltmp[0];
181 looptris[i][1] = ltmp[1];
182 looptris[i][2] = ltmp[2];
185 looptris[i][0] = ltmp[0];
186 looptris[i][1] = ltmp[2];
187 looptris[i][2] = ltmp[3];
191 #endif /* USE_TESSFACE_SPEEDUP */
194 EditVert *v, *lastv=NULL, *firstv=NULL;
199 BLI_begin_edgefill();
201 l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
202 for (j=0; l; l=BMIter_Step(&liter), j++) {
204 BM_SetIndex(l, j); /* set_loop */
206 v = BLI_addfillvert(l->v->co);
210 e = BLI_addfilledge(lastv, v);
214 if (firstv==NULL) firstv = v;
217 /*complete the loop*/
218 BLI_addfilledge(firstv, v);
220 totfilltri = BLI_edgefill(2);
221 BLI_array_growitems(looptris, totfilltri);
223 for (efa = fillfacebase.first; efa; efa=efa->next) {
224 BMLoop *l1= efa->v1->tmp.p;
225 BMLoop *l2= efa->v2->tmp.p;
226 BMLoop *l3= efa->v3->tmp.p;
228 if (BM_GetIndex(l1) > BM_GetIndex(l2)) { SWAP(BMLoop*, l1, l2); }
229 if (BM_GetIndex(l2) > BM_GetIndex(l3)) { SWAP(BMLoop*, l2, l3); }
230 if (BM_GetIndex(l1) > BM_GetIndex(l2)) { SWAP(BMLoop*, l1, l2); }
243 tm->looptris = looptris;
245 #undef USE_TESSFACE_SPEEDUP
249 void BMEdit_RecalcTesselation(BMEditMesh *em)
251 BMEdit_RecalcTesselation_intern(em);
253 /* commented because editbmesh_build_data() ensures we get tessfaces */
255 if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
256 if (em->derivedFinal->recalcTesselation)
257 em->derivedFinal->recalcTesselation(em->derivedFinal);
259 else if (em->derivedFinal) {
260 if (em->derivedCage->recalcTesselation)
261 em->derivedCage->recalcTesselation(em->derivedCage);
262 if (em->derivedFinal->recalcTesselation)
263 em->derivedFinal->recalcTesselation(em->derivedFinal);
268 void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
273 if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
274 act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
275 CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
277 act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
278 CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
280 act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
281 CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
283 act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
284 CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
288 /*does not free the BMEditMesh struct itself*/
289 void BMEdit_Free(BMEditMesh *em)
291 if (em->derivedFinal) {
292 if (em->derivedFinal!=em->derivedCage) {
293 em->derivedFinal->needsFree= 1;
294 em->derivedFinal->release(em->derivedFinal);
296 em->derivedFinal= NULL;
298 if (em->derivedCage) {
299 em->derivedCage->needsFree= 1;
300 em->derivedCage->release(em->derivedCage);
301 em->derivedCage= NULL;
304 if (em->looptris) MEM_freeN(em->looptris);
306 if (em->vert_index) MEM_freeN(em->vert_index);
307 if (em->edge_index) MEM_freeN(em->edge_index);
308 if (em->face_index) MEM_freeN(em->face_index);
311 BM_Free_Mesh(em->bm);
317 the bmesh derivedmesh exposes the mesh as triangles. it stores pointers
318 to three loops per triangle. the derivedmesh stores a cache of tesselations
319 for each face. this cache will smartly update as needed (though at first
320 it'll simply be more brute force). keeping track of face/edge counts may
323 this won't be the most efficient thing, considering that internal edges and
324 faces of tesselations are exposed. looking up an edge by index in particular
325 is likely to be a little slow.
328 typedef struct EditDerivedBMesh {
334 float (*vertexCos)[3];
335 float (*vertexNos)[3];
338 /*lookup caches; these are rebuilt on dm->RecalcTesselation()
339 (or when the derivedmesh is created, of course)*/
344 /*private variables, for number of verts/edges/faces
345 within the above hash/table members*/
349 /* BMESH_TODO, since this is not called get functions fail! */
350 static void UNUSED_FUNCTION(bmdm_recalc_lookups)(EditDerivedBMesh *bmdm)
352 const char iter_types[3] = {BM_VERTS_OF_MESH,
356 BMHeader **iters_table[3] = {(BMHeader **)bmdm->vtable,
357 (BMHeader **)bmdm->etable,
358 (BMHeader **)bmdm->ftable};
363 bmdm->tv = bmdm->tc->bm->totvert;
364 bmdm->te = bmdm->tc->bm->totedge;
365 bmdm->tf = bmdm->tc->bm->totface;
367 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
368 if (bmdm->etable) MEM_freeN(bmdm->etable);
369 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
371 if (bmdm->tc->bm->totvert)
372 bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
373 else bmdm->vtable = NULL;
375 if (bmdm->tc->bm->totedge)
376 bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
377 else bmdm->etable = NULL;
379 if (bmdm->tc->bm->totface)
380 bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
381 else bmdm->ftable = NULL;
383 for (a=0; a<3; a++) {
384 BMHeader **table = iters_table[a];
387 ele = BMIter_New(&iter, bmdm->tc->bm, iter_types[a], NULL);
388 for (i=0; ele; ele=BMIter_Step(&iter), i++) {
390 BM_SetIndex(ele, i); /* set_ok */
393 bmdm->tc->bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
397 static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
399 /* Nothing to do: normals are already calculated and stored on the
400 BMVerts and BMFaces */
403 static void emDM_recalcTesselation(DerivedMesh *UNUSED(dm))
405 //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
407 //bmdm_recalc_lookups(bmdm);
410 static void emDM_foreachMappedVert(
412 void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
415 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
420 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
421 for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
422 if (bmdm->vertexCos) {
423 func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
426 func(userData, i, eve->co, eve->no, NULL);
430 static void emDM_foreachMappedEdge(
432 void (*func)(void *userData, int index, float *v0co, float *v1co),
435 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
440 if (bmdm->vertexCos) {
442 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
444 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
445 for (i=0; eed; i++,eed=BMIter_Step(&iter))
447 bmdm->vertexCos[BM_GetIndex(eed->v1)],
448 bmdm->vertexCos[BM_GetIndex(eed->v2)]);
451 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
452 for (i=0; eed; i++,eed=BMIter_Step(&iter))
453 func(userData, i, eed->v1->co, eed->v2->co);
457 static void emDM_drawMappedEdges(
459 int (*setDrawOptions)(void *userData, int index),
462 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
467 if (bmdm->vertexCos) {
469 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
472 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
473 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
474 if (!setDrawOptions || setDrawOptions(userData, i)) {
475 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
476 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
483 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
484 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
485 if (!setDrawOptions || setDrawOptions(userData, i)) {
486 glVertex3fv(eed->v1->co);
487 glVertex3fv(eed->v2->co);
493 static void emDM_drawEdges(
495 int UNUSED(drawLooseEdges),
496 int UNUSED(drawAllEdges))
498 emDM_drawMappedEdges(dm, NULL, NULL);
501 static void emDM_drawMappedEdgesInterp(
503 int (*setDrawOptions)(void *userData, int index),
504 void (*setDrawInterpOptions)(void *userData, int index, float t),
507 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
512 if (bmdm->vertexCos) {
514 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
517 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
518 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
519 if (!setDrawOptions || setDrawOptions(userData, i)) {
520 setDrawInterpOptions(userData, i, 0.0);
521 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
522 setDrawInterpOptions(userData, i, 1.0);
523 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
530 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
531 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
532 if (!setDrawOptions || setDrawOptions(userData, i)) {
533 setDrawInterpOptions(userData, i, 0.0);
534 glVertex3fv(eed->v1->co);
535 setDrawInterpOptions(userData, i, 1.0);
536 glVertex3fv(eed->v2->co);
543 static void emDM_drawUVEdges(DerivedMesh *dm)
545 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
546 BMEditMesh *em = bmdm->tc;
551 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
554 MLoopUV *lastluv = NULL, *firstluv = NULL;
556 if (BM_TestHFlag(efa, BM_HIDDEN))
559 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
560 MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
564 glVertex2fv(luv->uv);
565 glVertex2fv(luv->uv);
574 glVertex2fv(lastluv->uv);
575 glVertex2fv(firstluv->uv);
581 static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3])
589 /*simple (and stupid) median (average) based method :/ */
592 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
593 for (; l; l=BMIter_Step(&iter)) {
594 add_v3_v3(cent, vertexCos[BM_GetIndex(l->v)]);
599 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
600 for (; l; l=BMIter_Step(&iter)) {
601 add_v3_v3(cent, l->v->co);
607 mul_v3_fl(cent, 1.0f/(float)tot);
610 static void emDM_foreachMappedFaceCenter(
612 void (*func)(void *userData, int index, float *co, float *no),
615 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
616 float (*polyNos)[3] = NULL;
622 /* ensure for face center calculation */
623 if (bmdm->vertexCos) {
624 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
625 polyNos = bmdm->polyNos;
627 BLI_assert(polyNos != NULL);
630 efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
631 for (i=0; efa; efa=BMIter_Step(&iter), i++) {
632 emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
633 func(userData, i, cent, polyNos ? polyNos[i] : efa->no);
637 static void emDM_drawMappedFaces(
639 int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
640 int (*setMaterial)(int, void *attribs),
641 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
642 void *userData, int UNUSED(useColors))
644 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
646 struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
647 const int tottri= bmdm->tc->tottri;
648 const int lasttri= tottri - 1; /* compare agasint this a lot */
650 const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
652 /* GL_ZERO is used to detect if drawing has started or not */
653 GLenum poly_prev= GL_ZERO;
654 GLenum shade_prev= GL_ZERO;
656 (void)setMaterial; /* UNUSED */
658 /* currently unused -- each original face is handled separately */
659 (void)compareDrawOptions;
661 if (bmdm->vertexCos) {
662 /* add direct access */
663 float (*vertexCos)[3]= bmdm->vertexCos;
664 float (*vertexNos)[3]= bmdm->vertexNos;
665 float (*polyNos)[3]= bmdm->polyNos;
666 // int *triPolyMap= bmdm->triPolyMap;
668 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
670 for (i=0; i < tottri; i++) {
671 BMLoop **l = looptris[i];
675 drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
677 draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
679 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
680 if (draw==2) { /* enabled with stipple */
682 if (poly_prev != GL_ZERO) glEnd();
683 poly_prev= GL_ZERO; /* force glBegin */
685 glEnable(GL_POLYGON_STIPPLE);
686 glPolygonStipple(stipple_quarttone);
690 if (poly_type != poly_prev) {
691 if (poly_prev != GL_ZERO) glEnd();
692 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
694 glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
695 glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
696 glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
699 const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
700 if (shade_type != shade_prev) {
701 if (poly_prev != GL_ZERO) glEnd();
702 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
703 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
705 if (poly_type != poly_prev) {
706 if (poly_prev != GL_ZERO) glEnd();
707 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
711 glNormal3fv(polyNos[BM_GetIndex(efa)]);
712 glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
713 glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
714 glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
717 glNormal3fv(vertexNos[BM_GetIndex(l[0]->v)]);
718 glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
719 glNormal3fv(vertexNos[BM_GetIndex(l[1]->v)]);
720 glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
721 glNormal3fv(vertexNos[BM_GetIndex(l[2]->v)]);
722 glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
727 if (!skip_normals && !flush && (i != lasttri))
728 flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
732 poly_prev= GL_ZERO; /* force glBegin */
734 glDisable(GL_POLYGON_STIPPLE);
740 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_FACE);
742 for (i=0; i < tottri; i++) {
743 BMLoop **l = looptris[i];
747 drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
749 draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
751 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
752 if (draw==2) { /* enabled with stipple */
754 if (poly_prev != GL_ZERO) glEnd();
755 poly_prev= GL_ZERO; /* force glBegin */
757 glEnable(GL_POLYGON_STIPPLE);
758 glPolygonStipple(stipple_quarttone);
762 if (poly_type != poly_prev) {
763 if (poly_prev != GL_ZERO) glEnd();
764 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
766 glVertex3fv(l[0]->v->co);
767 glVertex3fv(l[1]->v->co);
768 glVertex3fv(l[2]->v->co);
771 const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
772 if (shade_type != shade_prev) {
773 if (poly_prev != GL_ZERO) glEnd();
774 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
775 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
777 if (poly_type != poly_prev) {
778 if (poly_prev != GL_ZERO) glEnd();
779 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
783 glNormal3fv(efa->no);
784 glVertex3fv(l[0]->v->co);
785 glVertex3fv(l[1]->v->co);
786 glVertex3fv(l[2]->v->co);
789 glNormal3fv(l[0]->v->no);
790 glVertex3fv(l[0]->v->co);
791 glNormal3fv(l[1]->v->no);
792 glVertex3fv(l[1]->v->co);
793 glNormal3fv(l[2]->v->no);
794 glVertex3fv(l[2]->v->co);
799 if (!skip_normals && !flush && (i != lasttri)) {
800 flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
805 poly_prev= GL_ZERO; /* force glBegin */
807 glDisable(GL_POLYGON_STIPPLE);
813 /* if non zero we know a face was rendered */
814 if (poly_prev != GL_ZERO) glEnd();
817 static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
818 int has_uv, int has_col)
821 luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
822 luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
823 luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
827 lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
828 lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
829 lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
835 static void emDM_drawFacesTex_common(
837 int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
838 int (*drawParamsMapped)(void *userData, int index),
839 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
842 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
843 BMEditMesh *em = bmdm->tc;
844 BMesh *bm= bmdm->tc->bm;
845 float (*vertexCos)[3]= bmdm->vertexCos;
846 float (*vertexNos)[3]= bmdm->vertexNos;
848 MLoopUV *luv[3], dummyluv = {{0}};
849 MLoopCol *lcol[3], dummylcol = {0};
850 int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
851 int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
853 (void) compareDrawOptions;
855 luv[0] = luv[1] = luv[2] = &dummyluv;
856 lcol[0] = lcol[1] = lcol[2] = &dummylcol;
858 dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
860 /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
861 glShadeModel(GL_SMOOTH);
863 BM_ElemIndex_Ensure(bm, BM_FACE);
866 BM_ElemIndex_Ensure(bm, BM_VERT);
868 glBegin(GL_TRIANGLES);
869 for (i=0; i<em->tottri; i++) {
870 BMLoop **ls = em->looptris[i];
871 MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
872 MTFace mtf = {{{0}}};
873 /*unsigned char *cp= NULL;*/ /*UNUSED*/
874 int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
881 mtf.tpage = tp->tpage;
882 mtf.transp = tp->transp;
885 mtf.unwrap = tp->unwrap;
889 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
890 else if (drawParamsMapped)
891 flag= drawParamsMapped(userData, BM_GetIndex(efa));
895 if (flag != 0) { /* flag 0 == the face is hidden or invisible */
897 /* we always want smooth here since otherwise vertex colors dont interpolate */
899 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
903 glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]);
905 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
907 glTexCoord2fv(luv[0]->uv);
908 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
909 glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
911 glTexCoord2fv(luv[1]->uv);
912 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
913 glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
915 glTexCoord2fv(luv[2]->uv);
916 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
917 glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
920 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
922 glTexCoord2fv(luv[0]->uv);
923 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
924 glNormal3fv(vertexNos[BM_GetIndex(ls[0]->v)]);
925 glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
927 glTexCoord2fv(luv[1]->uv);
928 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
929 glNormal3fv(vertexNos[BM_GetIndex(ls[1]->v)]);
930 glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
932 glTexCoord2fv(luv[2]->uv);
933 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
934 glNormal3fv(vertexNos[BM_GetIndex(ls[2]->v)]);
935 glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
942 BM_ElemIndex_Ensure(bm, BM_VERT);
944 for (i=0; i<em->tottri; i++) {
945 BMLoop **ls = em->looptris[i];
946 MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
947 MTFace mtf = {{{0}}};
948 /*unsigned char *cp= NULL;*/ /*UNUSED*/
949 int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
956 mtf.tpage = tp->tpage;
957 mtf.transp = tp->transp;
960 mtf.unwrap = tp->unwrap;
964 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
965 else if (drawParamsMapped)
966 flag= drawParamsMapped(userData, BM_GetIndex(efa));
970 if (flag != 0) { /* flag 0 == the face is hidden or invisible */
972 /* we always want smooth here since otherwise vertex colors dont interpolate */
974 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
977 glBegin(GL_TRIANGLES);
979 glNormal3fv(efa->no);
981 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
984 glTexCoord2fv(luv[0]->uv);
986 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
987 else glColor3ub(0, 0, 0);
988 glVertex3fv(ls[0]->v->co);
991 glTexCoord2fv(luv[1]->uv);
993 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
994 else glColor3ub(0, 0, 0);
995 glVertex3fv(ls[1]->v->co);
998 glTexCoord2fv(luv[2]->uv);
1000 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
1001 else glColor3ub(0, 0, 0);
1002 glVertex3fv(ls[2]->v->co);
1005 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
1008 glTexCoord2fv(luv[0]->uv);
1010 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
1011 else glColor3ub(0, 0, 0);
1012 glNormal3fv(ls[0]->v->no);
1013 glVertex3fv(ls[0]->v->co);
1016 glTexCoord2fv(luv[1]->uv);
1018 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
1019 else glColor3ub(0, 0, 0);
1020 glNormal3fv(ls[1]->v->no);
1021 glVertex3fv(ls[1]->v->co);
1024 glTexCoord2fv(luv[2]->uv);
1026 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
1027 else glColor3ub(0, 0, 0);
1028 glNormal3fv(ls[2]->v->no);
1029 glVertex3fv(ls[2]->v->co);
1037 static void emDM_drawFacesTex(
1039 int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr),
1040 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1043 emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
1046 static void emDM_drawMappedFacesTex(
1048 int (*setDrawOptions)(void *userData, int index),
1049 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1052 emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
1055 static void emDM_drawMappedFacesGLSL(
1057 int (*setMaterial)(int, void *attribs),
1058 int (*setDrawOptions)(void *userData, int index),
1061 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1062 BMesh *bm= bmdm->tc->bm;
1063 BMEditMesh *em = bmdm->tc;
1064 float (*vertexCos)[3]= bmdm->vertexCos;
1065 float (*vertexNos)[3]= bmdm->vertexNos;
1068 DMVertexAttribs attribs;
1069 GPUVertexAttribs gattribs;
1071 int i, b, matnr, new_matnr, dodraw;
1076 memset(&attribs, 0, sizeof(attribs));
1078 /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1079 glShadeModel(GL_SMOOTH);
1080 BM_ElemIndex_Ensure(bm, BM_VERT | BM_FACE);
1082 #define PASSATTRIB(loop, eve, vert) { \
1083 if (attribs.totorco) { \
1084 float *orco = attribs.orco.array[BM_GetIndex(eve)]; \
1085 glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
1087 for (b = 0; b < attribs.tottface; b++) { \
1088 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1089 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv); \
1091 for (b = 0; b < attribs.totmcol; b++) { \
1092 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1094 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a; \
1095 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col); \
1097 if (attribs.tottang) { \
1098 float *tang = attribs.tang.array[i*4 + vert]; \
1099 glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
1104 for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1108 drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
1110 if (setDrawOptions && !setDrawOptions(userData, BM_GetIndex(efa)))
1113 new_matnr = efa->mat_nr + 1;
1114 if (new_matnr != matnr) {
1115 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1117 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1121 glBegin(GL_TRIANGLES);
1123 if (vertexCos) glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]);
1124 else glNormal3fv(efa->no);
1126 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1127 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1128 else glVertex3fv(ltri[0]->v->co);
1130 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1131 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1132 else glVertex3fv(ltri[1]->v->co);
1134 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1135 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1136 else glVertex3fv(ltri[2]->v->co);
1139 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1141 glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1142 glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1145 glNormal3fv(ltri[0]->v->no);
1146 glVertex3fv(ltri[0]->v->co);
1149 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1151 glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1152 glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1155 glNormal3fv(ltri[1]->v->no);
1156 glVertex3fv(ltri[1]->v->co);
1159 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1161 glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1162 glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1165 glNormal3fv(ltri[2]->v->no);
1166 glVertex3fv(ltri[2]->v->co);
1175 static void emDM_drawFacesGLSL(
1177 int (*setMaterial)(int, void *attribs))
1179 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1182 static void emDM_drawMappedFacesMat(
1184 void (*setMaterial)(void *userData, int, void *attribs),
1185 int (*setFace)(void *userData, int index), void *userData)
1187 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1188 BMesh *bm= bmdm->tc->bm;
1189 BMEditMesh *em = bmdm->tc;
1190 float (*vertexCos)[3]= bmdm->vertexCos;
1191 float (*vertexNos)[3]= bmdm->vertexNos;
1194 DMVertexAttribs attribs= {{{0}}};
1195 GPUVertexAttribs gattribs;
1196 int i, b, matnr, new_matnr;
1200 /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1201 glShadeModel(GL_SMOOTH);
1203 BM_ElemIndex_Ensure(bm, BM_VERT);
1205 #define PASSATTRIB(loop, eve, vert) { \
1206 if (attribs.totorco) { \
1207 float *orco = attribs.orco.array[BM_GetIndex(eve)]; \
1208 glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
1210 for (b = 0; b < attribs.tottface; b++) { \
1211 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1212 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv); \
1214 for (b = 0; b < attribs.totmcol; b++) { \
1215 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1217 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a; \
1218 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col); \
1220 if (attribs.tottang) { \
1221 float *tang = attribs.tang.array[i*4 + vert]; \
1222 glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \
1226 for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1230 drawSmooth = BM_TestHFlag(efa, BM_SMOOTH);
1233 if (setFace && !setFace(userData, BM_GetIndex(efa)))
1237 new_matnr = efa->mat_nr + 1;
1238 if (new_matnr != matnr) {
1239 setMaterial(userData, matnr = new_matnr, &gattribs);
1240 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1244 glBegin(GL_TRIANGLES);
1246 if (vertexCos) glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]);
1247 else glNormal3fv(efa->no);
1249 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1250 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1251 else glVertex3fv(ltri[0]->v->co);
1253 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1254 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1255 else glVertex3fv(ltri[1]->v->co);
1257 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1258 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1259 else glVertex3fv(ltri[2]->v->co);
1263 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1265 glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1266 glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1269 glNormal3fv(ltri[0]->v->no);
1270 glVertex3fv(ltri[0]->v->co);
1273 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1275 glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1276 glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1279 glNormal3fv(ltri[1]->v->no);
1280 glVertex3fv(ltri[1]->v->co);
1283 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1285 glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1286 glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1289 glNormal3fv(ltri[2]->v->no);
1290 glVertex3fv(ltri[2]->v->co);
1298 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1300 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1305 if (bmdm->tc->bm->totvert) {
1306 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1307 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1308 if (bmdm->vertexCos) {
1309 DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
1312 DO_MINMAX(eve->co, min_r, max_r);
1317 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1320 static int emDM_getNumVerts(DerivedMesh *dm)
1322 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1324 return bmdm->tc->bm->totvert;
1327 static int emDM_getNumEdges(DerivedMesh *dm)
1329 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1331 return bmdm->tc->bm->totedge;
1334 static int emDM_getNumTessFaces(DerivedMesh *dm)
1336 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1338 return bmdm->tc->tottri;
1341 static int emDM_getNumLoops(DerivedMesh *dm)
1343 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1345 return bmdm->tc->bm->totloop;
1348 static int emDM_getNumPolys(DerivedMesh *dm)
1350 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1352 return bmdm->tc->bm->totface;
1355 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1357 copy_v3_v3(vert_r->co, ev->co);
1359 normal_float_to_short_v3(vert_r->no, ev->no);
1361 vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1363 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1364 vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1370 static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1374 if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
1375 printf("error in emDM_getVert.\n");
1379 ev = ((EditDerivedBMesh *)dm)->vtable[index];
1380 bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r);
1383 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1385 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1386 BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1389 if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
1390 printf("error in emDM_getEdge.\n");
1394 e = bmdm->etable[index];
1396 if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1397 edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f);
1400 if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1401 edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f);
1404 edge_r->flag = BM_Edge_Flag_To_MEFlag(e);
1406 edge_r->v1 = BM_GetIndex(e->v1);
1407 edge_r->v2 = BM_GetIndex(e->v2);
1410 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1412 /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */
1416 if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
1417 printf("error in emDM_getTessFace.\n");
1421 l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
1425 face_r->mat_nr = (unsigned char) ef->mat_nr;
1426 face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1428 face_r->v1 = BM_GetIndex(l[0]->v);
1429 face_r->v2 = BM_GetIndex(l[1]->v);
1430 face_r->v3 = BM_GetIndex(l[2]->v);
1433 test_index_face(face_r, NULL, 0, 3);
1436 static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1438 BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1442 ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1443 for ( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
1444 copy_v3_v3(vert_r->co, ev->co);
1446 normal_float_to_short_v3(vert_r->no, ev->no);
1448 vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1450 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1451 vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1456 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1458 BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1461 int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1462 int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1464 BM_ElemIndex_Ensure(bm, BM_VERT);
1466 ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1467 for ( ; ee; ee=BMIter_Step(&iter), edge_r++) {
1469 edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f);
1473 edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f);
1476 edge_r->flag = BM_Edge_Flag_To_MEFlag(ee);
1478 edge_r->v1 = BM_GetIndex(ee->v1);
1479 edge_r->v2 = BM_GetIndex(ee->v2);
1483 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
1485 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1486 BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1491 BM_ElemIndex_Ensure(bm, BM_VERT);
1493 for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
1494 l = bmdm->tc->looptris[i];
1497 face_r->mat_nr = (unsigned char) ef->mat_nr;
1499 face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1501 face_r->v1 = BM_GetIndex(l[0]->v);
1502 face_r->v2 = BM_GetIndex(l[1]->v);
1503 face_r->v3 = BM_GetIndex(l[2]->v);
1506 test_index_face(face_r, NULL, 0, 3);
1511 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1513 /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1514 BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1519 BM_ElemIndex_Ensure(bm, BM_VERT | BM_EDGE);
1521 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1522 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
1523 loop_r->v = BM_GetIndex(l->v);
1524 loop_r->e = BM_GetIndex(l->e);
1530 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1532 /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1533 BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1539 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1540 poly_r->flag = BM_Face_Flag_To_MEFlag(f);
1541 poly_r->loopstart = i;
1542 poly_r->totloop = f->len;
1543 poly_r->mat_nr = f->mat_nr;
1550 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1552 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1553 BMesh *bm= bmdm->tc->bm;
1555 char *data, *bmdata;
1557 int index /*, offset*/ /*UNUSED */, size, i;
1559 datalayer = DM_get_tessface_data_layer(dm, type);
1563 /* layers are store per face for editmesh, we convert to a tbmporary
1564 * data layer array in the derivedmesh when these are requested */
1565 if (type == CD_MTFACE || type == CD_MCOL) {
1566 index = CustomData_get_layer_index(&bm->pdata, type);
1569 /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1570 size = CustomData_sizeof(type);
1572 DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1573 index = CustomData_get_layer_index(&dm->faceData, type);
1574 dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1576 data = datalayer = DM_get_tessface_data_layer(dm, type);
1577 for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
1578 efa = bmdm->tc->looptris[i][0]->f;
1579 /*BMESH_TODO: need to still add tface data,
1580 derived from the loops.*/
1581 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
1582 memcpy(data, bmdata, size);
1590 static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1592 EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1598 BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
1599 if (emdm->vertexCos) {
1600 copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1603 copy_v3_v3(cos_r[i], eve->co);
1610 static void emDM_release(DerivedMesh *dm)
1612 EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1614 if (DM_release(dm)) {
1615 if (bmdm->vertexCos) {
1616 MEM_freeN(bmdm->vertexCos);
1617 MEM_freeN(bmdm->vertexNos);
1618 MEM_freeN(bmdm->polyNos);
1621 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
1622 if (bmdm->etable) MEM_freeN(bmdm->etable);
1623 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
1629 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1631 EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1633 return &bmdm->tc->bm->vdata;
1636 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1638 EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1640 return &bmdm->tc->bm->edata;
1643 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1645 EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1647 return &bmdm->dm.faceData;
1650 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1652 EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1654 return &bmdm->tc->bm->ldata;
1657 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1659 EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1661 return &bmdm->tc->bm->pdata;
1665 DerivedMesh *getEditDerivedBMesh(
1668 float (*vertexCos)[3])
1670 EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1675 DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
1676 em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1678 CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
1680 bmdm->dm.getVertCos = emDM_getVertCos;
1681 bmdm->dm.getMinMax = emDM_getMinMax;
1683 bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1684 bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1685 bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1686 bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1687 bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1689 bmdm->dm.getNumVerts = emDM_getNumVerts;
1690 bmdm->dm.getNumEdges = emDM_getNumEdges;
1691 bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1692 bmdm->dm.getNumLoops = emDM_getNumLoops;
1693 bmdm->dm.getNumPolys = emDM_getNumPolys;
1695 bmdm->dm.getVert = emDM_getVert;
1696 bmdm->dm.getEdge = emDM_getEdge;
1697 bmdm->dm.getTessFace = emDM_getTessFace;
1698 bmdm->dm.copyVertArray = emDM_copyVertArray;
1699 bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1700 bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1701 bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1702 bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1704 bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1706 bmdm->dm.calcNormals = emDM_calcNormals;
1707 bmdm->dm.recalcTesselation = emDM_recalcTesselation;
1709 bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1710 bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1711 bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1713 bmdm->dm.drawEdges = emDM_drawEdges;
1714 bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1715 bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1716 bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1717 bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1718 bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1719 bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1720 bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1721 bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1722 bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1724 bmdm->dm.release = emDM_release;
1726 bmdm->vertexCos = vertexCos;
1728 if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1733 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1735 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1736 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1737 DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1738 CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1748 BM_ElemIndex_Ensure(bm, BM_VERT);
1750 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
1751 bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos)*bm->totface, "bmdm_pno");
1754 BM_ITER(efa, &fiter, bm, BM_FACES_OF_MESH, NULL) {
1755 BM_SetIndex(efa, i); /* set_inline */
1756 BM_Face_UpdateNormal_VertexCos(bm, efa, bmdm->polyNos[i], vertexCos);
1759 bm->elem_index_dirty &= ~BM_FACE;
1761 eve=BMIter_New(&viter, bm, BM_VERTS_OF_MESH, NULL);
1762 for (i=0; eve; eve=BMIter_Step(&viter), i++) {
1763 float *no = bmdm->vertexNos[i];
1764 BM_ITER(efa, &fiter, bm, BM_FACES_OF_VERT, eve) {
1765 add_v3_v3(no, bmdm->polyNos[BM_GetIndex(efa)]);
1768 /* following Mesh convention; we use vertex coordinate itself
1769 * for normal in this case */
1770 if (normalize_v3(no)==0.0) {
1771 copy_v3_v3(no, vertexCos[i]);
1777 //bmdm_recalc_lookups(bmdm);
1779 return (DerivedMesh*) bmdm;