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"
44 #include "BKE_cdderivedmesh.h"
45 #include "BKE_global.h"
47 #include "BKE_paint.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_object_types.h"
54 #include "MEM_guardedalloc.h"
56 #include "GPU_buffers.h"
58 #include "GPU_extensions.h"
59 #include "GPU_material.h"
62 #include "BKE_tessmesh.h"
63 #include "BLI_array.h"
64 #include "BLI_scanfill.h"
69 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
72 BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate)
74 BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
78 BMEdit_RecalcTessellation(tm);
84 BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
86 BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
89 tm2->derivedCage = tm2->derivedFinal = NULL;
91 tm2->bm = BM_mesh_copy(tm->bm);
93 /* The tessellation is NOT calculated on the copy here,
94 * because currently all the callers of this function use
95 * it to make a backup copy of the BMEditMesh to restore
96 * it in the case of errors in an operation. For perf
97 * reasons, in that case it makes more sense to do the
98 * tessellation only when/if that copy ends up getting
100 tm2->looptris = NULL;
102 tm2->vert_index = NULL;
103 tm2->edge_index = NULL;
104 tm2->face_index = NULL;
109 static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
111 /* use this to avoid locking pthread for _every_ polygon
112 * and calling the fill function */
113 #define USE_TESSFACE_SPEEDUP
116 BMLoop *(*looptris)[3] = NULL;
117 BLI_array_declare(looptris);
123 ScanFillContext sf_ctx;
126 /* note, we could be clever and re-use this array but would need to ensure
127 * its realloced at some point, for now just free it */
128 if (tm->looptris) MEM_freeN(tm->looptris);
130 /* Use tm->tottri when set, this means no reallocs while transforming,
131 * (unless scanfill fails), otherwise... */
132 /* allocate the length of totfaces, avoid many small reallocs,
133 * if all faces are tri's it will be correct, quads == 2x allocs */
134 BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
137 /* this means no reallocs for quad dominant models, for */
138 if ( (tm->looptris != NULL) &&
140 /* (totrti <= bm->totface * 2) would be fine for all quads,
141 * but in case there are some ngons, still re-use the array */
142 (tm->tottri <= bm->totface * 3))
144 looptris = tm->looptris;
147 if (tm->looptris) MEM_freeN(tm->looptris);
148 BLI_array_reserve(looptris, bm->totface);
153 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
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 (efa->len == 3) {
164 BLI_array_grow_one(looptris);
165 BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
170 else if (efa->len == 4) {
172 BLI_array_grow_items(looptris, 2);
174 BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
178 looptris[i][0] = ltmp[0];
179 looptris[i][1] = ltmp[1];
180 looptris[i][2] = ltmp[2];
183 looptris[i][0] = ltmp[0];
184 looptris[i][1] = ltmp[2];
185 looptris[i][2] = ltmp[3];
189 #endif /* USE_TESSFACE_SPEEDUP */
192 ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
193 /* ScanFillEdge *e; */ /* UNUSED */
194 ScanFillFace *sf_tri;
197 BLI_scanfill_begin(&sf_ctx);
200 BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
202 BM_elem_index_set(l, j); /* set_loop */
204 sf_vert = BLI_scanfill_vert_add(&sf_ctx, l->v->co);
208 /* e = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
211 sf_vert_last = sf_vert;
212 if (sf_vert_first == NULL) sf_vert_first = sf_vert;
215 /* complete the loop */
216 BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
218 totfilltri = BLI_scanfill_calc_ex(&sf_ctx, FALSE, efa->no);
219 BLI_array_grow_items(looptris, totfilltri);
221 for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
222 BMLoop *l1 = sf_tri->v1->tmp.p;
223 BMLoop *l2 = sf_tri->v2->tmp.p;
224 BMLoop *l3 = sf_tri->v3->tmp.p;
226 if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop *, l1, l2); }
227 if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop *, l2, l3); }
228 if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop *, l1, l2); }
236 BLI_scanfill_end(&sf_ctx);
241 tm->looptris = looptris;
243 #undef USE_TESSFACE_SPEEDUP
247 void BMEdit_RecalcTessellation(BMEditMesh *em)
249 BMEdit_RecalcTessellation_intern(em);
251 /* commented because editbmesh_build_data() ensures we get tessfaces */
253 if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
254 if (em->derivedFinal->recalcTessellation)
255 em->derivedFinal->recalcTessellation(em->derivedFinal);
257 else if (em->derivedFinal) {
258 if (em->derivedCage->recalcTessellation)
259 em->derivedCage->recalcTessellation(em->derivedCage);
260 if (em->derivedFinal->recalcTessellation)
261 em->derivedFinal->recalcTessellation(em->derivedFinal);
266 void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
271 if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
272 act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
273 CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
275 act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
276 CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
278 act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
279 CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
281 act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
282 CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
286 /*does not free the BMEditMesh struct itself*/
287 void BMEdit_Free(BMEditMesh *em)
289 if (em->derivedFinal) {
290 if (em->derivedFinal != em->derivedCage) {
291 em->derivedFinal->needsFree = 1;
292 em->derivedFinal->release(em->derivedFinal);
294 em->derivedFinal = NULL;
296 if (em->derivedCage) {
297 em->derivedCage->needsFree = 1;
298 em->derivedCage->release(em->derivedCage);
299 em->derivedCage = NULL;
302 if (em->looptris) MEM_freeN(em->looptris);
304 if (em->vert_index) MEM_freeN(em->vert_index);
305 if (em->edge_index) MEM_freeN(em->edge_index);
306 if (em->face_index) MEM_freeN(em->face_index);
309 BM_mesh_free(em->bm);
315 * the bmesh derivedmesh exposes the mesh as triangles. it stores pointers
316 * to three loops per triangle. the derivedmesh stores a cache of tessellations
317 * for each face. this cache will smartly update as needed (though at first
318 * it'll simply be more brute force). keeping track of face/edge counts may
319 * be a small problbm.
321 * this won't be the most efficient thing, considering that internal edges and
322 * faces of tessellations are exposed. looking up an edge by index in particular
323 * is likely to be a little slow.
326 typedef struct EditDerivedBMesh {
332 float (*vertexCos)[3];
333 float (*vertexNos)[3];
336 /* private variables, for number of verts/edges/faces
337 * within the above hash/table members*/
341 static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
343 /* Nothing to do: normals are already calculated and stored on the
344 * BMVerts and BMFaces */
347 static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
352 static void emDM_foreachMappedVert(DerivedMesh *dm,
353 void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
356 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
361 if (bmdm->vertexCos) {
362 BM_ITER_MESH_INDEX (eve, &iter, bmdm->tc->bm, BM_VERTS_OF_MESH, i) {
363 func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
367 BM_ITER_MESH_INDEX (eve, &iter, bmdm->tc->bm, BM_VERTS_OF_MESH, i) {
368 func(userData, i, eve->co, eve->no, NULL);
372 static void emDM_foreachMappedEdge(DerivedMesh *dm,
373 void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
376 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
381 if (bmdm->vertexCos) {
383 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
385 BM_ITER_MESH_INDEX (eed, &iter, bmdm->tc->bm, BM_EDGES_OF_MESH, i) {
387 bmdm->vertexCos[BM_elem_index_get(eed->v1)],
388 bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
392 BM_ITER_MESH_INDEX (eed, &iter, bmdm->tc->bm, BM_EDGES_OF_MESH, i) {
393 func(userData, i, eed->v1->co, eed->v2->co);
398 static void emDM_drawMappedEdges(DerivedMesh *dm,
399 DMSetDrawOptions setDrawOptions,
402 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
407 if (bmdm->vertexCos) {
409 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
412 BM_ITER_MESH_INDEX (eed, &iter, bmdm->tc->bm, BM_EDGES_OF_MESH, i) {
413 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
414 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
415 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
422 BM_ITER_MESH_INDEX (eed, &iter, bmdm->tc->bm, BM_EDGES_OF_MESH, i) {
423 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
424 glVertex3fv(eed->v1->co);
425 glVertex3fv(eed->v2->co);
431 static void emDM_drawEdges(DerivedMesh *dm,
432 int UNUSED(drawLooseEdges),
433 int UNUSED(drawAllEdges))
435 emDM_drawMappedEdges(dm, NULL, NULL);
438 static void emDM_drawMappedEdgesInterp(DerivedMesh *dm,
439 DMSetDrawOptions setDrawOptions,
440 DMSetDrawInterpOptions setDrawInterpOptions,
443 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
448 if (bmdm->vertexCos) {
450 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
453 BM_ITER_MESH_INDEX (eed, &iter, bmdm->tc->bm, BM_EDGES_OF_MESH, i) {
454 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
455 setDrawInterpOptions(userData, i, 0.0);
456 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
457 setDrawInterpOptions(userData, i, 1.0);
458 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
465 BM_ITER_MESH_INDEX (eed, &iter, bmdm->tc->bm, BM_EDGES_OF_MESH, i) {
466 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
467 setDrawInterpOptions(userData, i, 0.0);
468 glVertex3fv(eed->v1->co);
469 setDrawInterpOptions(userData, i, 1.0);
470 glVertex3fv(eed->v2->co);
477 static void emDM_drawUVEdges(DerivedMesh *dm)
479 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
480 BMEditMesh *em = bmdm->tc;
485 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
488 MLoopUV *lastluv = NULL, *firstluv = NULL;
490 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
493 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
494 MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
498 glVertex2fv(luv->uv);
499 glVertex2fv(luv->uv);
508 glVertex2fv(lastluv->uv);
509 glVertex2fv(firstluv->uv);
515 static void emDM__calcFaceCent(BMFace *efa, float cent[3], float (*vertexCos)[3])
523 /*simple (and stupid) median (average) based method :/ */
526 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
527 add_v3_v3(cent, vertexCos[BM_elem_index_get(l->v)]);
532 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
533 add_v3_v3(cent, l->v->co);
538 if (tot == 0) return;
539 mul_v3_fl(cent, 1.0f / (float)tot);
542 static void emDM_foreachMappedFaceCenter(DerivedMesh *dm,
543 void (*func)(void *userData, int index, const float co[3], const float no[3]),
546 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
547 float (*polyNos)[3] = NULL;
553 /* ensure for face center calculation */
554 if (bmdm->vertexCos) {
555 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
556 polyNos = bmdm->polyNos;
558 BLI_assert(polyNos != NULL);
561 BM_ITER_MESH_INDEX (efa, &iter, bmdm->tc->bm, BM_FACES_OF_MESH, i) {
562 emDM__calcFaceCent(efa, cent, bmdm->vertexCos);
563 func(userData, i, cent, polyNos ? polyNos[i] : efa->no);
567 static void emDM_drawMappedFaces(DerivedMesh *dm,
568 DMSetDrawOptions setDrawOptions,
569 DMSetMaterial setMaterial,
570 DMCompareDrawOptions compareDrawOptions,
574 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
576 struct BMLoop *(*looptris)[3] = bmdm->tc->looptris;
577 const int tottri = bmdm->tc->tottri;
578 const int lasttri = tottri - 1; /* compare agasint this a lot */
579 DMDrawOption draw_option;
581 const int skip_normals = !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
583 /* GL_ZERO is used to detect if drawing has started or not */
584 GLenum poly_prev = GL_ZERO;
585 GLenum shade_prev = GL_ZERO;
587 (void)setMaterial; /* UNUSED */
589 /* currently unused -- each original face is handled separately */
590 (void)compareDrawOptions;
592 if (bmdm->vertexCos) {
593 /* add direct access */
594 float (*vertexCos)[3] = bmdm->vertexCos;
595 float (*vertexNos)[3] = bmdm->vertexNos;
596 float (*polyNos)[3] = bmdm->polyNos;
597 // int *triPolyMap= bmdm->triPolyMap;
599 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
601 for (i = 0; i < tottri; i++) {
602 BMLoop **l = looptris[i];
606 drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
608 draw_option = (!setDrawOptions ?
609 DM_DRAW_OPTION_NORMAL :
610 setDrawOptions(userData, BM_elem_index_get(efa)));
611 if (draw_option != DM_DRAW_OPTION_SKIP) {
612 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
613 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
615 if (poly_prev != GL_ZERO) glEnd();
616 poly_prev = GL_ZERO; /* force glBegin */
618 glEnable(GL_POLYGON_STIPPLE);
619 glPolygonStipple(stipple_quarttone);
623 if (poly_type != poly_prev) {
624 if (poly_prev != GL_ZERO) glEnd();
625 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
627 glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
628 glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
629 glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
632 const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
633 if (shade_type != shade_prev) {
634 if (poly_prev != GL_ZERO) glEnd();
635 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
636 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
638 if (poly_type != poly_prev) {
639 if (poly_prev != GL_ZERO) glEnd();
640 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
644 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
645 glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
646 glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
647 glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
650 glNormal3fv(vertexNos[BM_elem_index_get(l[0]->v)]);
651 glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
652 glNormal3fv(vertexNos[BM_elem_index_get(l[1]->v)]);
653 glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
654 glNormal3fv(vertexNos[BM_elem_index_get(l[2]->v)]);
655 glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
659 flush = (draw_option == DM_DRAW_OPTION_STIPPLE);
660 if (!skip_normals && !flush && (i != lasttri))
661 flush |= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
665 poly_prev = GL_ZERO; /* force glBegin */
667 glDisable(GL_POLYGON_STIPPLE);
673 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_FACE);
675 for (i = 0; i < tottri; i++) {
676 BMLoop **l = looptris[i];
680 drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
682 draw_option = (!setDrawOptions ?
683 DM_DRAW_OPTION_NORMAL :
684 setDrawOptions(userData, BM_elem_index_get(efa)));
685 if (draw_option != DM_DRAW_OPTION_SKIP) {
686 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
687 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
689 if (poly_prev != GL_ZERO) glEnd();
690 poly_prev = GL_ZERO; /* force glBegin */
692 glEnable(GL_POLYGON_STIPPLE);
693 glPolygonStipple(stipple_quarttone);
697 if (poly_type != poly_prev) {
698 if (poly_prev != GL_ZERO) glEnd();
699 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
701 glVertex3fv(l[0]->v->co);
702 glVertex3fv(l[1]->v->co);
703 glVertex3fv(l[2]->v->co);
706 const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
707 if (shade_type != shade_prev) {
708 if (poly_prev != GL_ZERO) glEnd();
709 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
710 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
712 if (poly_type != poly_prev) {
713 if (poly_prev != GL_ZERO) glEnd();
714 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
718 glNormal3fv(efa->no);
719 glVertex3fv(l[0]->v->co);
720 glVertex3fv(l[1]->v->co);
721 glVertex3fv(l[2]->v->co);
724 glNormal3fv(l[0]->v->no);
725 glVertex3fv(l[0]->v->co);
726 glNormal3fv(l[1]->v->no);
727 glVertex3fv(l[1]->v->co);
728 glNormal3fv(l[2]->v->no);
729 glVertex3fv(l[2]->v->co);
733 flush = (draw_option == DM_DRAW_OPTION_STIPPLE);
734 if (!skip_normals && !flush && (i != lasttri)) {
735 flush |= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
740 poly_prev = GL_ZERO; /* force glBegin */
742 glDisable(GL_POLYGON_STIPPLE);
748 /* if non zero we know a face was rendered */
749 if (poly_prev != GL_ZERO) glEnd();
752 static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
753 int has_uv, int has_col)
756 luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
757 luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
758 luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
762 lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
763 lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
764 lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
770 static void emDM_drawFacesTex_common(DerivedMesh *dm,
771 DMSetDrawOptionsTex drawParams,
772 DMSetDrawOptions drawParamsMapped,
773 DMCompareDrawOptions compareDrawOptions,
776 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
777 BMEditMesh *em = bmdm->tc;
778 BMesh *bm = bmdm->tc->bm;
779 float (*vertexCos)[3] = bmdm->vertexCos;
780 float (*vertexNos)[3] = bmdm->vertexNos;
782 MLoopUV *luv[3], dummyluv = {{0}};
783 MLoopCol *lcol[3] = {NULL}, dummylcol = {0};
784 int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
785 int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
787 (void) compareDrawOptions;
789 luv[0] = luv[1] = luv[2] = &dummyluv;
791 dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255;
793 /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
794 glShadeModel(GL_SMOOTH);
796 BM_mesh_elem_index_ensure(bm, BM_FACE);
799 BM_mesh_elem_index_ensure(bm, BM_VERT);
801 for (i = 0; i < em->tottri; i++) {
802 BMLoop **ls = em->looptris[i];
803 MTexPoly *tp = has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
804 MTFace mtf = {{{0}}};
805 /*unsigned char *cp= NULL;*/ /*UNUSED*/
806 int drawSmooth = BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
807 DMDrawOption draw_option;
812 ME_MTEXFACE_CPY(&mtf, tp);
816 draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
817 else if (drawParamsMapped)
818 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
820 draw_option = DM_DRAW_OPTION_NORMAL;
822 if (draw_option != DM_DRAW_OPTION_SKIP) {
824 glBegin(GL_TRIANGLES);
826 glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
828 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
830 glTexCoord2fv(luv[0]->uv);
832 glColor3ubv((const GLubyte *)&(lcol[0]->r));
833 glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
835 glTexCoord2fv(luv[1]->uv);
837 glColor3ubv((const GLubyte *)&(lcol[1]->r));
838 glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
840 glTexCoord2fv(luv[2]->uv);
842 glColor3ubv((const GLubyte *)&(lcol[2]->r));
843 glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
846 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
848 glTexCoord2fv(luv[0]->uv);
850 glColor3ubv((const GLubyte *)&(lcol[0]->r));
851 glNormal3fv(vertexNos[BM_elem_index_get(ls[0]->v)]);
852 glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
854 glTexCoord2fv(luv[1]->uv);
856 glColor3ubv((const GLubyte *)&(lcol[1]->r));
857 glNormal3fv(vertexNos[BM_elem_index_get(ls[1]->v)]);
858 glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
860 glTexCoord2fv(luv[2]->uv);
862 glColor3ubv((const GLubyte *)&(lcol[2]->r));
863 glNormal3fv(vertexNos[BM_elem_index_get(ls[2]->v)]);
864 glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
871 BM_mesh_elem_index_ensure(bm, BM_VERT);
873 for (i = 0; i < em->tottri; i++) {
874 BMLoop **ls = em->looptris[i];
875 MTexPoly *tp = has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
876 MTFace mtf = {{{0}}};
877 /*unsigned char *cp= NULL;*/ /*UNUSED*/
878 int drawSmooth = BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
879 DMDrawOption draw_option;
884 ME_MTEXFACE_CPY(&mtf, tp);
888 draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
889 else if (drawParamsMapped)
890 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
892 draw_option = DM_DRAW_OPTION_NORMAL;
894 if (draw_option != DM_DRAW_OPTION_SKIP) {
896 glBegin(GL_TRIANGLES);
898 glNormal3fv(efa->no);
900 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
903 glTexCoord2fv(luv[0]->uv);
905 glColor3ubv((const GLubyte *)&(lcol[0]->r));
906 glVertex3fv(ls[0]->v->co);
909 glTexCoord2fv(luv[1]->uv);
911 glColor3ubv((const GLubyte *)&(lcol[1]->r));
912 glVertex3fv(ls[1]->v->co);
915 glTexCoord2fv(luv[2]->uv);
917 glColor3ubv((const GLubyte *)&(lcol[2]->r));
918 glVertex3fv(ls[2]->v->co);
921 bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
924 glTexCoord2fv(luv[0]->uv);
926 glColor3ubv((const GLubyte *)&(lcol[0]->r));
927 glNormal3fv(ls[0]->v->no);
928 glVertex3fv(ls[0]->v->co);
931 glTexCoord2fv(luv[1]->uv);
933 glColor3ubv((const GLubyte *)&(lcol[1]->r));
934 glNormal3fv(ls[1]->v->no);
935 glVertex3fv(ls[1]->v->co);
938 glTexCoord2fv(luv[2]->uv);
940 glColor3ubv((const GLubyte *)&(lcol[2]->r));
941 glNormal3fv(ls[2]->v->no);
942 glVertex3fv(ls[2]->v->co);
949 glShadeModel(GL_FLAT);
952 static void emDM_drawFacesTex(DerivedMesh *dm,
953 DMSetDrawOptionsTex setDrawOptions,
954 DMCompareDrawOptions compareDrawOptions,
957 emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
960 static void emDM_drawMappedFacesTex(DerivedMesh *dm,
961 DMSetDrawOptions setDrawOptions,
962 DMCompareDrawOptions compareDrawOptions,
965 emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
968 static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
969 DMSetMaterial setMaterial,
970 DMSetDrawOptions setDrawOptions,
973 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
974 BMesh *bm = bmdm->tc->bm;
975 BMEditMesh *em = bmdm->tc;
976 float (*vertexCos)[3] = bmdm->vertexCos;
977 float (*vertexNos)[3] = bmdm->vertexNos;
980 DMVertexAttribs attribs;
981 GPUVertexAttribs gattribs;
983 int i, b, matnr, new_matnr, dodraw;
988 memset(&attribs, 0, sizeof(attribs));
990 /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
991 glShadeModel(GL_SMOOTH);
992 BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
994 #define PASSATTRIB(loop, eve, vert) { \
995 if (attribs.totorco) { \
996 float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \
997 glVertexAttrib3fvARB(attribs.orco.gl_index, orco); \
999 for (b = 0; b < attribs.tottface; b++) { \
1000 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b); \
1001 glVertexAttrib2fvARB(attribs.tface[b].gl_index, _luv->uv); \
1003 for (b = 0; b < attribs.totmcol; b++) { \
1004 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b); \
1006 _col[0] = _cp->b; _col[1] = _cp->g; _col[2] = _cp->r; _col[3] = _cp->a; \
1007 glVertexAttrib4ubvARB(attribs.mcol[b].gl_index, _col); \
1009 if (attribs.tottang) { \
1010 float *tang = attribs.tang.array[i * 4 + vert]; \
1011 glVertexAttrib3fvARB(attribs.tang.gl_index, tang); \
1016 for (i = 0, ltri = em->looptris[0]; i < em->tottri; i++, ltri += 3) {
1020 drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1022 if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
1025 new_matnr = efa->mat_nr + 1;
1026 if (new_matnr != matnr) {
1027 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1029 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1033 glBegin(GL_TRIANGLES);
1035 if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
1036 else glNormal3fv(efa->no);
1038 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1039 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1040 else glVertex3fv(ltri[0]->v->co);
1042 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1043 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1044 else glVertex3fv(ltri[1]->v->co);
1046 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1047 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1048 else glVertex3fv(ltri[2]->v->co);
1051 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1053 glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1054 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1057 glNormal3fv(ltri[0]->v->no);
1058 glVertex3fv(ltri[0]->v->co);
1061 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1063 glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1064 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1067 glNormal3fv(ltri[1]->v->no);
1068 glVertex3fv(ltri[1]->v->co);
1071 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1073 glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1074 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1077 glNormal3fv(ltri[2]->v->no);
1078 glVertex3fv(ltri[2]->v->co);
1087 static void emDM_drawFacesGLSL(DerivedMesh *dm,
1088 int (*setMaterial)(int, void *attribs))
1090 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1093 static void emDM_drawMappedFacesMat(DerivedMesh *dm,
1094 void (*setMaterial)(void *userData, int, void *attribs),
1095 int (*setFace)(void *userData, int index), void *userData)
1097 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1098 BMesh *bm = bmdm->tc->bm;
1099 BMEditMesh *em = bmdm->tc;
1100 float (*vertexCos)[3] = bmdm->vertexCos;
1101 float (*vertexNos)[3] = bmdm->vertexNos;
1104 DMVertexAttribs attribs = {{{0}}};
1105 GPUVertexAttribs gattribs;
1106 int i, b, matnr, new_matnr;
1110 /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1111 glShadeModel(GL_SMOOTH);
1113 BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
1115 #define PASSATTRIB(loop, eve, vert) { \
1116 if (attribs.totorco) { \
1117 float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \
1118 if (attribs.orco.gl_texco) \
1119 glTexCoord3fv(orco); \
1121 glVertexAttrib3fvARB(attribs.orco.gl_index, orco); \
1123 for (b = 0; b < attribs.tottface; b++) { \
1124 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b); \
1125 if (attribs.tface[b].gl_texco) \
1126 glTexCoord2fv(_luv->uv); \
1128 glVertexAttrib2fvARB(attribs.tface[b].gl_index, _luv->uv); \
1130 for (b = 0; b < attribs.totmcol; b++) { \
1131 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b); \
1133 _col[0] = _cp->b; _col[1] = _cp->g; _col[2] = _cp->r; _col[3] = _cp->a; \
1134 glVertexAttrib4ubvARB(attribs.mcol[b].gl_index, _col); \
1136 if (attribs.tottang) { \
1137 float *tang = attribs.tang.array[i * 4 + vert]; \
1138 glVertexAttrib4fvARB(attribs.tang.gl_index, tang); \
1142 for (i = 0, ltri = em->looptris[0]; i < em->tottri; i++, ltri += 3) {
1146 drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1149 if (setFace && !setFace(userData, BM_elem_index_get(efa)))
1153 new_matnr = efa->mat_nr + 1;
1154 if (new_matnr != matnr) {
1155 setMaterial(userData, matnr = new_matnr, &gattribs);
1156 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1160 glBegin(GL_TRIANGLES);
1162 if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
1163 else glNormal3fv(efa->no);
1165 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1166 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1167 else glVertex3fv(ltri[0]->v->co);
1169 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1170 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1171 else glVertex3fv(ltri[1]->v->co);
1173 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1174 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1175 else glVertex3fv(ltri[2]->v->co);
1179 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1181 glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1182 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1185 glNormal3fv(ltri[0]->v->no);
1186 glVertex3fv(ltri[0]->v->co);
1189 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1191 glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1192 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1195 glNormal3fv(ltri[1]->v->no);
1196 glVertex3fv(ltri[1]->v->co);
1199 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1201 glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1202 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1205 glNormal3fv(ltri[2]->v->no);
1206 glVertex3fv(ltri[2]->v->co);
1214 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1216 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1221 if (bmdm->tc->bm->totvert) {
1222 if (bmdm->vertexCos) {
1223 BM_ITER_MESH_INDEX (eve, &iter, bmdm->tc->bm, BM_VERTS_OF_MESH, i) {
1224 minmax_v3v3_v3(min_r, max_r, bmdm->vertexCos[i]);
1228 BM_ITER_MESH (eve, &iter, bmdm->tc->bm, BM_VERTS_OF_MESH) {
1229 minmax_v3v3_v3(min_r, max_r, eve->co);
1238 static int emDM_getNumVerts(DerivedMesh *dm)
1240 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1242 return bmdm->tc->bm->totvert;
1245 static int emDM_getNumEdges(DerivedMesh *dm)
1247 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1249 return bmdm->tc->bm->totedge;
1252 static int emDM_getNumTessFaces(DerivedMesh *dm)
1254 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1256 return bmdm->tc->tottri;
1259 static int emDM_getNumLoops(DerivedMesh *dm)
1261 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1263 return bmdm->tc->bm->totloop;
1266 static int emDM_getNumPolys(DerivedMesh *dm)
1268 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1270 return bmdm->tc->bm->totface;
1273 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1275 copy_v3_v3(vert_r->co, ev->co);
1277 normal_float_to_short_v3(vert_r->no, ev->no);
1279 vert_r->flag = BM_vert_flag_to_mflag(ev);
1281 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1282 vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT) * 255.0f);
1288 static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1290 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1293 if (index < 0 || index >= bmdm->tv) {
1294 printf("error in emDM_getVert.\n");
1298 // ev = EDBM_vert_at_index(bmdm->tc, index);
1299 ev = BM_vert_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
1301 bmvert_to_mvert(bmdm->tc->bm, ev, vert_r);
1302 if (bmdm->vertexCos)
1303 copy_v3_v3(vert_r->co, bmdm->vertexCos[index]);
1306 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1308 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1309 BMesh *bm = bmdm->tc->bm;
1312 if (index < 0 || index >= bmdm->te) {
1313 printf("error in emDM_getEdge.\n");
1317 // e = EDBM_edge_at_index(bmdm->tc, index);
1318 e = BM_edge_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
1320 if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1321 edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) * 255.0f);
1324 if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1325 edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_CREASE) * 255.0f);
1328 edge_r->flag = BM_edge_flag_to_mflag(e);
1330 edge_r->v1 = BM_elem_index_get(e->v1);
1331 edge_r->v2 = BM_elem_index_get(e->v2);
1334 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1336 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1340 if (index < 0 || index >= bmdm->tf) {
1341 printf("error in emDM_getTessFace.\n");
1345 l = bmdm->tc->looptris[index];
1349 face_r->mat_nr = (unsigned char) ef->mat_nr;
1350 face_r->flag = BM_face_flag_to_mflag(ef);
1352 face_r->v1 = BM_elem_index_get(l[0]->v);
1353 face_r->v2 = BM_elem_index_get(l[1]->v);
1354 face_r->v3 = BM_elem_index_get(l[2]->v);
1357 test_index_face(face_r, NULL, 0, 3);
1360 static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1362 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1363 BMesh *bm = bmdm->tc->bm;
1366 const int has_bweight = CustomData_has_layer(&bm->vdata, CD_BWEIGHT);
1368 if (bmdm->vertexCos) {
1371 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1372 copy_v3_v3(vert_r->co, bmdm->vertexCos[i]);
1373 normal_float_to_short_v3(vert_r->no, eve->no);
1374 vert_r->flag = BM_vert_flag_to_mflag(eve);
1377 vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, eve, CD_BWEIGHT) * 255.0f);
1383 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1384 copy_v3_v3(vert_r->co, eve->co);
1385 normal_float_to_short_v3(vert_r->no, eve->no);
1386 vert_r->flag = BM_vert_flag_to_mflag(eve);
1389 vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, eve, CD_BWEIGHT) * 255.0f);
1396 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1398 BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1401 const int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1402 const int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1404 BM_mesh_elem_index_ensure(bm, BM_VERT);
1406 BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1408 edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, eed, CD_BWEIGHT) * 255.0f);
1412 edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, eed, CD_CREASE) * 255.0f);
1415 edge_r->flag = BM_edge_flag_to_mflag(eed);
1417 edge_r->v1 = BM_elem_index_get(eed->v1);
1418 edge_r->v2 = BM_elem_index_get(eed->v2);
1424 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
1426 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1427 BMesh *bm = bmdm->tc->bm;
1432 BM_mesh_elem_index_ensure(bm, BM_VERT);
1434 for (i = 0; i < bmdm->tc->tottri; i++, face_r++) {
1435 l = bmdm->tc->looptris[i];
1438 face_r->mat_nr = (unsigned char) ef->mat_nr;
1440 face_r->flag = BM_face_flag_to_mflag(ef);
1442 face_r->v1 = BM_elem_index_get(l[0]->v);
1443 face_r->v2 = BM_elem_index_get(l[1]->v);
1444 face_r->v3 = BM_elem_index_get(l[2]->v);
1447 test_index_face(face_r, NULL, 0, 3);
1451 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1453 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1454 BMesh *bm = bmdm->tc->bm;
1459 BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
1461 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1462 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1463 loop_r->v = BM_elem_index_get(l->v);
1464 loop_r->e = BM_elem_index_get(l->e);
1470 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1472 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1473 BMesh *bm = bmdm->tc->bm;
1479 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1480 poly_r->flag = BM_face_flag_to_mflag(efa);
1481 poly_r->loopstart = i;
1482 poly_r->totloop = efa->len;
1483 poly_r->mat_nr = efa->mat_nr;
1490 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1492 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1493 BMesh *bm = bmdm->tc->bm;
1496 datalayer = DM_get_tessface_data_layer(dm, type);
1500 /* layers are store per face for editmesh, we convert to a temporary
1501 * data layer array in the derivedmesh when these are requested */
1502 if (type == CD_MTFACE || type == CD_MCOL) {
1503 const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
1505 char *data, *bmdata;
1506 index = CustomData_get_layer_index(&bm->pdata, type_from);
1509 /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1510 const int size = CustomData_sizeof(type);
1513 DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1514 index = CustomData_get_layer_index(&dm->faceData, type);
1515 dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1517 data = datalayer = DM_get_tessface_data_layer(dm, type);
1519 if (type == CD_MTFACE) {
1520 for (i = 0; i < bmdm->tc->tottri; i++, data += size) {
1521 BMFace *efa = bmdm->tc->looptris[i][0]->f;
1522 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
1523 ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
1524 for (j = 0; j < 3; j++) {
1525 bmdata = CustomData_bmesh_get(&bm->ldata, bmdm->tc->looptris[i][j]->head.data, CD_MLOOPUV);
1526 copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
1531 for (i = 0; i < bmdm->tc->tottri; i++, data += size) {
1532 for (j = 0; j < 3; j++) {
1533 bmdata = CustomData_bmesh_get(&bm->ldata, bmdm->tc->looptris[i][j]->head.data, CD_MLOOPCOL);
1534 MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
1544 static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1546 EditDerivedBMesh *emdm = (EditDerivedBMesh *)dm;
1551 if (emdm->vertexCos) {
1552 BM_ITER_MESH_INDEX (eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, i) {
1553 copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1557 BM_ITER_MESH_INDEX (eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, i) {
1558 copy_v3_v3(cos_r[i], eve->co);
1563 static void emDM_release(DerivedMesh *dm)
1565 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1567 if (DM_release(dm)) {
1568 if (bmdm->vertexCos) {
1569 MEM_freeN(bmdm->vertexCos);
1570 MEM_freeN(bmdm->vertexNos);
1571 MEM_freeN(bmdm->polyNos);
1578 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1580 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1582 return &bmdm->tc->bm->vdata;
1585 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1587 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1589 return &bmdm->tc->bm->edata;
1592 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1594 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1596 return &bmdm->dm.faceData;
1599 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1601 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1603 return &bmdm->tc->bm->ldata;
1606 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1608 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1610 return &bmdm->tc->bm->pdata;
1614 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
1616 float (*vertexCos)[3])
1618 EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1623 DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
1624 em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1626 bmdm->dm.getVertCos = emDM_getVertCos;
1627 bmdm->dm.getMinMax = emDM_getMinMax;
1629 bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1630 bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1631 bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1632 bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1633 bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1635 bmdm->dm.getNumVerts = emDM_getNumVerts;
1636 bmdm->dm.getNumEdges = emDM_getNumEdges;
1637 bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1638 bmdm->dm.getNumLoops = emDM_getNumLoops;
1639 bmdm->dm.getNumPolys = emDM_getNumPolys;
1641 bmdm->dm.getVert = emDM_getVert;
1642 bmdm->dm.getEdge = emDM_getEdge;
1643 bmdm->dm.getTessFace = emDM_getTessFace;
1644 bmdm->dm.copyVertArray = emDM_copyVertArray;
1645 bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1646 bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1647 bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1648 bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1650 bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1652 bmdm->dm.calcNormals = emDM_calcNormals;
1653 bmdm->dm.recalcTessellation = emDM_recalcTessellation;
1655 bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1656 bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1657 bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1659 bmdm->dm.drawEdges = emDM_drawEdges;
1660 bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1661 bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1662 bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1663 bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1664 bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1665 bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1666 bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1667 bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1668 bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1670 bmdm->dm.release = emDM_release;
1672 bmdm->vertexCos = vertexCos;
1674 if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1679 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1681 BM_ITER_MESH_INDEX (eve, &iter, bmdm->tc->bm, BM_VERTS_OF_MESH, i) {
1682 DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1683 CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1694 BM_mesh_elem_index_ensure(bm, BM_VERT);
1696 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
1697 bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos) * bm->totface, "bmdm_pno");
1699 BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
1700 BM_elem_index_set(efa, i); /* set_inline */
1701 BM_face_normal_update_vcos(bm, efa, bmdm->polyNos[i], (float const (*)[3])vertexCos);
1703 bm->elem_index_dirty &= ~BM_FACE;
1705 BM_ITER_MESH_INDEX (eve, &viter, bm, BM_VERTS_OF_MESH, i) {
1706 float *no = bmdm->vertexNos[i];
1707 BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) {
1708 add_v3_v3(no, bmdm->polyNos[BM_elem_index_get(efa)]);
1711 /* following Mesh convention; we use vertex coordinate itself
1712 * for normal in this case */
1713 if (normalize_v3(no) == 0.0f) {
1714 copy_v3_v3(no, vertexCos[i]);
1720 return (DerivedMesh *)bmdm;
1724 * \brief Return the BMEditMesh for a given object
1726 * \note this function assumes this is a mesh object,
1727 * don't add NULL data check here. caller must do that
1729 BMEditMesh *BMEdit_FromObject(Object *ob)
1731 BLI_assert(ob->type == OB_MESH);
1732 return ((Mesh *)ob->data)->edit_btmesh;