sculpt-dev: DynTopo cleanup

* Moved dyntopo.c to c++.
* The new element id system now mostly
  works. Doesn't yet work with collapse
  though, which is a tricky case.  Element
  IDs have to be manually freed now, doing that
  with something as convoluted as a non-manifold
  BREP's edge collapse is not easy.
This commit is contained in:
Joseph Eagar 2022-12-11 00:38:14 -08:00
parent e53a8f9c51
commit bb764e418a
26 changed files with 1109 additions and 659 deletions

View File

@ -540,7 +540,7 @@ class MESH_UL_attributes(UIList):
show_all = _context.tool_settings.save_temp_layers if hasattr(_context, "tool_settings") else False
for item in attributes:
flags.append(0 if item.is_internal else self.bitflag_filter_item)
flags.append(0 if (not show_all and item.is_internal) else self.bitflag_filter_item)
return flags, indices

View File

@ -2158,10 +2158,10 @@ def brush_settings_advanced(layout, context, brush, popover=False):
is_cavity_active = "CAVITY" in flags or "CAVITY_INVERTED" in flags
if is_cavity_active:
props = row.operator("sculpt.mask_from_cavity", text="Create Mask")
props = layout.operator("sculpt.mask_from_cavity", text="Create Mask")
props.settings_source = "BRUSH"
col.prop(brush, "use_automasking_cavity_inverted", text="Cavity (inverted)")
layout.prop(brush, "use_automasking_cavity_inverted", text="Cavity (inverted)")
if is_cavity_active:
col = layout.column(align=True)

View File

@ -1148,6 +1148,8 @@ class SCULPT_OT_set_dyntopo_mode(Operator):
elif self.mode == "C":
finalch.flags_value = oldf.union({"COLLAPSE"})
print("NEWF", finalch.flags_value)
return {'FINISHED'}
@ -2891,7 +2893,8 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
preset_add_operator = "scene.gpencil_brush_preset_add"
classes = (VIEW3D_MT_brush_context_menu,
classes = (SCULPT_OT_set_dyntopo_mode,
VIEW3D_MT_brush_context_menu,
VIEW3D_MT_brush_gpencil_context_menu,
VIEW3D_PT_tools_object_options,
VIEW3D_PT_tools_object_options_transform,
@ -2990,8 +2993,7 @@ classes = (VIEW3D_MT_brush_context_menu,
VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff,
VIEW3D_PT_tools_brush_swatches_channels,
VIEW3D_PT_tools_persistent_base_channels,
VIEW3D_PT_sculpt_dyntopo_advanced,
SCULPT_OT_set_dyntopo_mode)
VIEW3D_PT_sculpt_dyntopo_advanced)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class

View File

@ -30,6 +30,7 @@ struct SculptAttribute;
struct MSculptVert;
struct BMFace;
struct BMesh;
struct BMIdMap;
struct BlendDataReader;
struct BlendLibReader;
struct BlendWriter;
@ -821,6 +822,7 @@ typedef struct SculptSession {
/* BMesh for dynamic topology sculpting */
struct BMesh *bm;
struct BMIdMap *bm_idmap;
/* TODO: get rid of these cd_ members and use
* .attrs.XXX.bmesh_cd_offset directly.
@ -1042,7 +1044,9 @@ void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
int BKE_sculptsession_vertex_count(const SculptSession *ss);
/* Ensure an attribute layer exists. */
void BKE_sculpt_ensure_idmap(struct Object *ob);
/* Ensure an attribute layer exists. */
SculptAttribute *BKE_sculpt_attribute_ensure(struct Object *ob,
eAttrDomain domain,
eCustomDataType proptype,

View File

@ -98,6 +98,7 @@ struct BMesh;
struct BMVert;
struct BMEdge;
struct BMFace;
struct BMIdMap;
struct Scene;
struct CCGElem;
struct MeshElemMap;
@ -276,6 +277,8 @@ typedef enum {
PBVH_UpdateOtherVerts = 1 << 21
} PBVHNodeFlags;
ENUM_OPERATORS(PBVHNodeFlags, PBVH_UpdateOtherVerts);
typedef struct PBVHFrustumPlanes {
float (*planes)[4];
int num_planes;
@ -433,6 +436,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct BMesh *bm,
bool smooth_shading,
struct BMLog *log,
struct BMIdMap *idmap,
const int cd_vert_node_offset,
const int cd_face_node_offset,
const int cd_sculpt_vert,
@ -440,6 +444,9 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
const int cd_boundary_flag,
bool fast_draw,
bool update_sculptverts);
void BKE_pbvh_set_idmap(PBVH *pbvh, struct BMIdMap *idmap);
void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_vert_node_offset,
const int cd_face_node_offset,

View File

@ -131,7 +131,7 @@ set(SRC
intern/deform.c
intern/displist.cc
intern/dynamicpaint.c
intern/dyntopo.c
intern/dyntopo.cc
intern/editlattice.c
intern/editmesh.cc
intern/editmesh_bvh.c

View File

@ -71,6 +71,7 @@
#include "BLO_read_write.h"
#include "../../bmesh/intern/bmesh_idmap.h"
#include "bmesh.h"
#include "bmesh_log.h"
@ -1579,6 +1580,11 @@ void BKE_sculptsession_free(Object *ob)
ss->msculptverts = nullptr;
}
if (ss->bm_idmap) {
BM_idmap_destroy(ss->bm_idmap);
ss->bm_idmap = nullptr;
}
if (ss->bm_log && BM_log_free(ss->bm_log, true)) {
ss->bm_log = nullptr;
}
@ -1746,6 +1752,16 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
return false;
}
void BKE_sculpt_ensure_idmap(Object *ob)
{
if (!ob->sculpt->bm_idmap) {
ob->sculpt->bm_idmap = BM_idmap_new(ob->sculpt->bm, BM_VERT | BM_EDGE | BM_FACE);
BM_idmap_check_ids(ob->sculpt->bm_idmap);
BKE_sculptsession_update_attr_refs(ob);
}
}
char BKE_get_fset_boundary_symflag(Object *object)
{
const Mesh *mesh = BKE_mesh_from_object(object);
@ -2575,12 +2591,15 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob, bool update_sculptverts
sculpt_boundary_flags_ensure(ob, pbvh, ob->sculpt->bm->totvert);
sculpt_check_face_areas(ob, pbvh);
BKE_sculpt_ensure_idmap(ob);
sculptsession_bmesh_add_layers(ob);
BKE_pbvh_build_bmesh(pbvh,
BKE_object_get_original_mesh(ob),
ob->sculpt->bm,
ob->sculpt->bm_smooth_shading,
ob->sculpt->bm_log,
ob->sculpt->bm_idmap,
ob->sculpt->attrs.dyntopo_node_id_vertex->bmesh_cd_offset,
ob->sculpt->attrs.dyntopo_node_id_face->bmesh_cd_offset,
ob->sculpt->cd_sculpt_vert,
@ -3609,6 +3628,7 @@ static void sculptsession_bmesh_attr_update_internal(Object *ob)
ss->attrs.dyntopo_node_id_face->bmesh_cd_offset :
-1;
BKE_pbvh_set_idmap(ss->pbvh, ss->bm_idmap);
BKE_pbvh_update_offsets(ss->pbvh,
cd_dyntopo_vert,
cd_dyntopo_face,

View File

@ -2144,12 +2144,18 @@ void BKE_pbvh_update_sculpt_verts(PBVH *pbvh)
}
}
void BKE_pbvh_set_idmap(PBVH *pbvh, BMIdMap *idmap)
{
pbvh->bm_idmap = idmap;
}
/* Build a PBVH from a BMesh */
void BKE_pbvh_build_bmesh(PBVH *pbvh,
Mesh *me,
BMesh *bm,
bool smooth_shading,
BMLog *log,
BMIdMap *idmap,
const int cd_vert_node_offset,
const int cd_face_node_offset,
const int cd_sculpt_vert,
@ -2160,6 +2166,8 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
{
// coalese_pbvh(pbvh, bm);
pbvh->bm_idmap = idmap;
pbvh->cd_hide_poly = CustomData_get_offset_named(
&bm->pdata, CD_PROP_INT32, ".sculpt_face_areas");
pbvh->cd_face_area = cd_face_areas;
@ -2347,6 +2355,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
void BKE_pbvh_set_bm_log(PBVH *pbvh, struct BMLog *log)
{
pbvh->bm_log = log;
BM_log_set_idmap(log, pbvh->bm_idmap);
}
bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
@ -3933,6 +3942,10 @@ void BKE_pbvh_update_offsets(PBVH *pbvh,
pbvh->totuv = CustomData_number_of_layers(&pbvh->header.bm->ldata, CD_MLOOPUV);
pbvh->cd_boundary_flag = cd_boundary_flag;
if (pbvh->bm_idmap) {
BM_idmap_check_attributes(pbvh->bm_idmap);
}
}
static void scan_edge_split(BMesh *bm, BMEdge **edges, int totedge)
@ -5426,6 +5439,8 @@ void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
BM_data_layer_add(bm, &bm->vdata, CD_DYNTOPO_VERT);
BM_data_layer_add(bm, &bm->vdata, CD_PROP_COLOR);
BMIdMap *idmap = BM_idmap_new(bm, BM_VERT | BM_EDGE | BM_FACE);
for (int side = 0; side < 6; side++) {
int axis = side >= 3 ? side - 3 : side;
float sign = side >= 3 ? -1.0f : 1.0f;
@ -5552,7 +5567,7 @@ void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
cd_face_area = bm->pdata.layers[cd_face_area].offset;
const int cd_sculpt_vert = CustomData_get_offset(&bm->vdata, CD_DYNTOPO_VERT);
BMLog *bmlog = BM_log_create(bm, cd_sculpt_vert);
BMLog *bmlog = BM_log_create(bm, idmap, cd_sculpt_vert);
PBVH *pbvh = BKE_pbvh_new(PBVH_BMESH);
@ -5566,6 +5581,7 @@ void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
bm,
false,
bmlog,
idmap,
cd_vert_node,
cd_face_node,
cd_sculpt_vert,

View File

@ -13,6 +13,7 @@
#include "BKE_pbvh.h"
#include "bmesh.h"
#include "../../bmesh/intern/bmesh_idmap.h"
#define PBVH_STACK_FIXED_DEPTH 100
@ -31,6 +32,7 @@ extern "C" {
struct MLoop;
struct MLoopTri;
struct BMIdMap;
struct MPoly;
struct MVert;
@ -116,7 +118,7 @@ struct PBVHNode {
/* Indicates whether this node is a leaf or not; also used for
* marking various updates that need to be applied. */
PBVHNodeFlags flag : 32;
PBVHNodeFlags flag;
/* Used for raycasting: how close bb is to the ray point. */
float tmin;
@ -234,6 +236,7 @@ struct PBVH {
float bm_max_edge_len;
float bm_min_edge_len;
float bm_detail_range;
struct BMIdMap *bm_idmap;
int cd_sculpt_vert;
int cd_vert_node_offset;

View File

@ -375,13 +375,23 @@ bool BLI_table_gset_haskey(TableGSet *ts, void *elem);
int BLI_table_gset_len(TableGSet *ts);
#define TGSET_ITER(v, ts) \
{ \
int _i1; \
for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \
if (!(ts)->elems[_i1]) \
continue; \
v = (ts)->elems[_i1];
#ifdef __cplusplus
# define TGSET_ITER(v, ts) \
{ \
int _i1; \
for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \
if (!(ts)->elems[_i1]) \
continue; \
v = static_cast<decltype(v)>((ts)->elems[_i1]);
#else
# define TGSET_ITER(v, ts) \
{ \
int _i1; \
for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \
if (!(ts)->elems[_i1]) \
continue; \
v = (ts)->elems[_i1];
#endif
#define TGSET_ITER_END \
} \

View File

@ -77,7 +77,7 @@
#define SMHASH_NEXT(h, hoff) \
(CHECK_TYPE_INLINE(&(h), uintptr_t *), \
CHECK_TYPE_INLINE(&(hoff), uintptr_t *), \
((h) + (((hoff) = ((hoff)*2) + 1), (hoff))))
((h) + (((hoff) = ((hoff)*3) + 1), (hoff))))
BLI_INLINE bool check_stack_move(SmallHash *sh)
{
@ -188,7 +188,7 @@ BLI_INLINE SmallHashEntry *smallhash_lookup(SmallHash *sh, const uintptr_t key)
return NULL;
}
BLI_INLINE SmallHashEntry *smallhash_lookup_first_free(SmallHash *sh, const uintptr_t key)
ATTR_NO_OPT BLI_INLINE SmallHashEntry *smallhash_lookup_first_free(SmallHash *sh, const uintptr_t key)
{
check_stack_move(sh);

View File

@ -6,6 +6,12 @@
* Core BMesh functions for adding, removing BMesh elements.
*/
//#define FORCE_BMESH_CHECK
#if !defined(NDEBUG) || defined(FORCE_BMESH_CHECK)
# define BMESH_DEBUG
#endif
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
@ -29,12 +35,6 @@
#include <stdarg.h>
#if 0
#ifdef NDEBUG
# undef NDEBUG
#endif
#endif
/* use so valgrinds memcheck alerts us when undefined index is used.
* TESTING ONLY! */
// #define USE_DEBUG_INDEX_MEMCHECK
@ -265,7 +265,7 @@ static BMLoop *bm_loop_create(BMesh *bm,
BLI_assert((l_example == NULL) || (l_example->head.htype == BM_LOOP));
BLI_assert(!(create_flag & 1));
#ifndef NDEBUG
#ifdef BMESH_DEBUG
if (l_example) {
/* ensure passing a loop is either sharing the same vertex, or entirely disconnected
* use to catch mistake passing in loop offset-by-one. */
@ -593,7 +593,7 @@ typedef enum {
IS_FACE_WRONG_LENGTH = (1 << 26),
} BMeshInternalError;
#ifndef NDEBUG
#ifdef BMESH_DEBUG
int bmesh_elem_check(void *element, const char htype)
{
@ -778,7 +778,7 @@ int bmesh_elem_check(void *element, const char htype)
return err;
}
#endif /* NDEBUG */
#endif /* BMESH_DEBUG */
/**
* low level function, only frees the vert,
@ -1009,7 +1009,7 @@ void BM_face_kill(BMesh *bm, BMFace *f)
BMLoopList *ls, *ls_next;
#endif
#ifdef NDEBUG
#ifndef BMESH_DEBUG
/* check length since we may be removing degenerate faces */
if (f->len >= 3) {
BM_CHECK_ELEMENT(f);
@ -1199,7 +1199,7 @@ void bmesh_kernel_loop_reverse(BMesh *bm,
/* step to next (now swapped) */
} while ((l_iter = l_iter->prev) != l_first);
#ifndef NDEBUG
#ifdef BMESH_DEBUG
/* validate radial */
int i;
for (i = 0, l_iter = l_first; i < f->len; i++, l_iter = l_iter->next) {
@ -1665,7 +1665,7 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd
BMLoop *l_next;
BMEdge *e_new;
BMVert *v_new, *v_old;
#ifndef NDEBUG
#ifdef BMESH_DEBUG
int valence1, valence2;
bool edok;
int i;
@ -1675,7 +1675,7 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd
v_old = BM_edge_other_vert(e, tv);
#ifndef NDEBUG
#ifdef BMESH_DEBUG
valence1 = bmesh_disk_count(v_old);
valence2 = bmesh_disk_count(tv);
#endif
@ -1696,7 +1696,7 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd
/* add e_new to tv's disk cycle */
bmesh_disk_edge_append(e_new, tv);
#ifndef NDEBUG
#ifdef BMESH_DEBUG
/* verify disk cycles */
edok = bmesh_disk_validate(valence1, v_old->e, v_old);
BMESH_ASSERT(edok != false);
@ -1711,7 +1711,7 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd
e->l = NULL;
if (l_next) {
BMLoop *l_new, *l;
#ifndef NDEBUG
#ifdef BMESH_DEBUG
int radlen = bmesh_radial_length(l_next);
#endif
bool is_first = true;
@ -1759,7 +1759,7 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd
}
}
#ifndef NDEBUG
#ifdef BMESH_DEBUG
/* verify length of radial cycle */
edok = bmesh_radial_validate(radlen, e->l);
BMESH_ASSERT(edok != false);
@ -1824,7 +1824,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
BMEdge *e_old;
BMVert *v_old, *v_target;
BMLoop *l_kill;
#ifndef NDEBUG
#ifdef BMESH_DEBUG
int radlen, i;
bool edok;
#endif
@ -1836,7 +1836,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
}
if (bmesh_disk_count_at_most(v_kill, 3) == 2) {
#ifndef NDEBUG
#ifdef BMESH_DEBUG
int valence1, valence2;
BMLoop *l;
#endif
@ -1857,7 +1857,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
/* Candidates for being duplicate. */
BLI_SMALLSTACK_DECLARE(faces_duplicate_candidate, BMFace *);
#ifndef NDEBUG
#ifdef BMESH_DEBUG
/* For verification later, count valence of 'v_old' and 'v_target' */
valence1 = bmesh_disk_count(v_old);
valence2 = bmesh_disk_count(v_target);
@ -1872,7 +1872,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
/* remove e_kill from 'v_target's disk cycle */
bmesh_disk_edge_remove(e_kill, v_target);
#ifndef NDEBUG
#ifdef BMESH_DEBUG
/* deal with radial cycle of e_kill */
radlen = bmesh_radial_length(e_kill->l);
#endif
@ -1910,7 +1910,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
} while ((l_kill = l_kill_next) != e_kill->l);
/* `e_kill->l` is invalid but the edge is freed next. */
#ifndef NDEBUG
#ifdef BMESH_DEBUG
/* Validate radial cycle of e_old */
edok = bmesh_radial_validate(radlen, e_old->l);
BMESH_ASSERT(edok != false);
@ -1927,7 +1927,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
v_kill->e = NULL;
}
#ifndef NDEBUG
#ifdef BMESH_DEBUG
/* Validate disk cycle lengths of 'v_old', 'v_target' are unchanged */
edok = bmesh_disk_validate(valence1, v_old->e, v_old);
BMESH_ASSERT(edok != false);
@ -2441,7 +2441,7 @@ char *_last_local_obj = NULL;
# define JVKE_CHECK_ELEMENT(elem)
#endif
static bool cleanup_vert(BMesh *bm, BMVert *v, const BMTracer *tracer)
ATTR_NO_OPT static bool cleanup_vert(BMesh *bm, BMVert *v, const BMTracer *tracer)
{
BMEdge *e = v->e;
@ -2452,12 +2452,11 @@ static bool cleanup_vert(BMesh *bm, BMVert *v, const BMTracer *tracer)
BMFace *f_example = NULL;
do {
if (tracer) {
tracer->on_edge_kill(bm, e, tracer->userdata);
}
BMLoop *l = e->l;
if (!l) {
if (tracer) {
tracer->on_edge_kill(bm, e, tracer->userdata);
}
continue;
}
@ -2470,6 +2469,10 @@ static bool cleanup_vert(BMesh *bm, BMVert *v, const BMTracer *tracer)
tracer->on_face_kill(bm, l->f, tracer->userdata);
}
} while ((l = l->radial_next) != e->l);
if (tracer) {
tracer->on_edge_kill(bm, e, tracer->userdata);
}
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
if (tracer) {
@ -2500,7 +2503,7 @@ static bool cleanup_vert(BMesh *bm, BMVert *v, const BMTracer *tracer)
return true;
}
static void bmesh_kernel_check_val3_vert(BMesh *bm, BMEdge *e, const BMTracer *tracer)
ATTR_NO_OPT static void bmesh_kernel_check_val3_vert(BMesh *bm, BMEdge *e, const BMTracer *tracer)
{
if (!e->l) {
return;
@ -2534,12 +2537,12 @@ static void bmesh_kernel_check_val3_vert(BMesh *bm, BMEdge *e, const BMTracer *t
} while (!stop);
}
BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
BMEdge *e,
BMVert *v_kill,
const bool do_del,
const bool combine_flags,
const BMTracer *tracer)
ATTR_NO_OPT BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
BMEdge *e,
BMVert *v_kill,
const bool do_del,
const bool combine_flags,
const BMTracer *tracer)
{
BMVert *v_conn = BM_edge_other_vert(e, v_kill);
@ -2570,10 +2573,13 @@ BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
const int tag = _FLAG_WALK_ALT; // using bmhead.api_flag here
const int dup_tag = _FLAG_OVERLAP;
const int final_tag = _FLAG_JF;
const int deleted_tag = _FLAG_WALK;
JVKE_CHECK_ELEMENT(v_conn);
JVKE_CHECK_ELEMENT(v_del);
#define _OTHER_TRACES //paranoia (and likely duplicate) calls to tracer callbacks
/* first clear tags */
for (int i = 0; i < 2; i++) {
BMVert *v = i ? v_del : v_conn;
@ -2753,9 +2759,15 @@ BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
e2->l = NULL;
// if (tracer) {
// tracer->on_edge_kill(bm, deles[i], tracer->userdata);
//}
#ifdef _OTHER_TRACES
if (tracer) {
tracer->on_edge_kill(bm, deles[i], tracer->userdata);
}
#endif
if (deles[i]->l) {
printf("%s: edge is not cleared\n", __func__);
}
BM_edge_kill(bm, deles[i]);
}
@ -2788,9 +2800,11 @@ BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
} while (lnext && (l = lnext) != f->l_first);
if (f->len <= 2) {
// if (tracer) {
// tracer->on_face_kill(bm, f, tracer->userdata);
//}
#ifdef _OTHER_TRACES
if (tracer) {
tracer->on_face_kill(bm, f, tracer->userdata);
}
#endif
/* kill face */
while (f->l_first) {
@ -2972,6 +2986,10 @@ BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
tracer->on_vert_kill(bm, v_del, tracer->userdata);
}
if (v_del->e) {
printf("%s: vert is not cleared\n", __func__);
}
BM_vert_kill(bm, v_del);
}
@ -3020,6 +3038,9 @@ BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
return v_conn;
}
#ifdef _OTHER_TRACES
# undef _OTHER_TRACES
#endif
/*original version of bmesh_kernel_join_vert_kill_edge*/
BMVert *bmesh_kernel_join_vert_kill_edge_fast(BMesh *bm,
@ -3282,7 +3303,7 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
return is_double;
}
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
ATTR_NO_OPT bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
{
BMEdge *e;
@ -3627,7 +3648,7 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src, bool combine_flags)
void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select)
{
BMEdge *e_new;
#ifndef NDEBUG
#ifdef BMESH_DEBUG
const int radlen = bmesh_radial_length(e->l);
#endif

View File

@ -1,6 +1,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_assert.h"
#include "BLI_compiler_attrs.h"
#include "BLI_compiler_compat.h"
#include "BLI_index_range.hh"
#include "BLI_map.hh"
#include "BLI_set.hh"
@ -19,7 +21,7 @@ using namespace blender;
#define FREELIST_HASHMAP_THRESHOLD_HIGH 1024
#define FREELIST_HASHMAP_THRESHOLD_LOW 700
BMIdMap *BM_idmap_new(BMesh *bm, int elem_mask)
ATTR_NO_OPT BMIdMap *BM_idmap_new(BMesh *bm, int elem_mask)
{
BMIdMap *idmap = MEM_new<BMIdMap>("BMIdMap");
@ -35,7 +37,7 @@ BMIdMap *BM_idmap_new(BMesh *bm, int elem_mask)
return idmap;
}
static void idmap_grow_map(BMIdMap *idmap, int newid)
ATTR_NO_OPT static void idmap_grow_map(BMIdMap *idmap, int newid)
{
if (idmap->map_size > newid) {
return;
@ -54,77 +56,77 @@ static void idmap_grow_map(BMIdMap *idmap, int newid)
idmap->map_size = newsize;
}
void BM_idmap_check_ids(BMIdMap *idmap)
ATTR_NO_OPT void BM_idmap_check_ids(BMIdMap *idmap)
{
BMIter iter;
BMVert *v;
BMEdge *e;
BMFace *f;
BM_idmap_check_attributes(idmap);
idmap->freelist.clear();
if (idmap->free_idx_map) {
MEM_delete<BMIdMap::FreeIdxMap>(idmap->free_idx_map);
idmap->free_idx_map = nullptr;
}
Set<int> used;
int max_id = 0;
if (idmap->flag & BM_VERT) {
BM_ITER_MESH (v, &iter, idmap->bm, BM_VERTS_OF_MESH) {
int id = BM_ELEM_CD_GET_INT(v, idmap->cd_id_off[BM_VERT]);
max_id = max_ff(max_id, id);
max_id = max_ii(max_id, id);
}
}
if (idmap->flag & BM_EDGE) {
BM_ITER_MESH (e, &iter, idmap->bm, BM_EDGES_OF_MESH) {
int id = BM_ELEM_CD_GET_INT(e, idmap->cd_id_off[BM_EDGE]);
max_id = max_ff(max_id, id);
max_id = max_ii(max_id, id);
}
}
if (idmap->flag & (BM_FACE | BM_LOOP)) {
BM_ITER_MESH (f, &iter, idmap->bm, BM_FACES_OF_MESH) {
if (idmap->flag & BM_FACE) {
int id = BM_ELEM_CD_GET_INT(f, idmap->cd_id_off[BM_FACE]);
max_id = max_ff(max_id, id);
max_id = max_ii(max_id, id);
}
if (idmap->flag & BM_LOOP) {
BMLoop *l = f->l_first;
do {
int id = BM_ELEM_CD_GET_INT(l, idmap->cd_id_off[BM_LOOP]);
max_id = max_ff(max_id, id);
max_id = max_ii(max_id, id);
} while ((l = l->next) != f->l_first);
}
}
}
max_id++;
if (idmap->map_size >= max_id) {
memset((void *)idmap->map, 0, sizeof(void *) * idmap->map_size);
}
else {
MEM_SAFE_FREE(idmap->map);
idmap->map_size = max_id;
idmap->map = (BMElem **)MEM_calloc_arrayN(max_id, sizeof(BMElem *), "bm idmap->map");
idmap->map_size = max_id + 1;
idmap->map = (BMElem **)MEM_calloc_arrayN(max_id + 1, sizeof(BMElem *), "bm idmap->map");
}
auto check_elem = [&](auto *elem) {
int id = BM_ELEM_CD_GET_INT(elem, idmap->cd_id_off[(int)elem->head.htype]);
if (id < 0 || used.contains(id)) {
if (id < 0 || id >= idmap->map_size || idmap->map[id]) {
id = max_id++;
BM_ELEM_CD_SET_INT(elem, idmap->cd_id_off[(int)elem->head.htype], id);
}
idmap_grow_map(idmap, id);
idmap->map[id] = reinterpret_cast<BMElem *>(elem);
used.add(id);
};
idmap->maxid = max_id;
if (idmap->flag & BM_VERT) {
BM_ITER_MESH (v, &iter, idmap->bm, BM_VERTS_OF_MESH) {
check_elem(v);
@ -152,9 +154,11 @@ void BM_idmap_check_ids(BMIdMap *idmap)
check_elem(v);
}
}
idmap->maxid = max_id;
}
void BM_idmap_check_attributes(BMIdMap *idmap)
ATTR_NO_OPT void BM_idmap_check_attributes(BMIdMap *idmap)
{
auto check_attr = [&](int type) {
if (!(idmap->flag & type)) {
@ -166,19 +170,19 @@ void BM_idmap_check_attributes(BMIdMap *idmap)
switch (type) {
case BM_VERT:
name = ".sculpt.vertex.id";
name = "vertex_id";
cdata = &idmap->bm->vdata;
break;
case BM_EDGE:
name = ".sculpt.edge.id";
name = "edge_id";
cdata = &idmap->bm->edata;
break;
case BM_LOOP:
name = ".sculpt.loop.id";
name = "loop_id";
cdata = &idmap->bm->ldata;
break;
case BM_FACE:
name = ".sculpt.face.id";
name = "face_id";
cdata = &idmap->bm->pdata;
break;
default:
@ -186,11 +190,11 @@ void BM_idmap_check_attributes(BMIdMap *idmap)
return;
}
int idx = CustomData_get_named_layer(cdata, CD_PROP_INT32, name);
int idx = CustomData_get_named_layer_index(cdata, CD_PROP_INT32, name);
if (idx < 0) {
if (idx == -1) {
BM_data_layer_add_named(idmap->bm, cdata, CD_PROP_INT32, name);
idx = CustomData_get_named_layer(cdata, CD_PROP_INT32, name);
idx = CustomData_get_named_layer_index(cdata, CD_PROP_INT32, name);
}
if (!cdata->layers[idx].default_data) {
@ -211,22 +215,22 @@ void BM_idmap_check_attributes(BMIdMap *idmap)
check_attr(BM_FACE);
}
void BM_idmap_destroy(BMIdMap *idmap)
ATTR_NO_OPT void BM_idmap_destroy(BMIdMap *idmap)
{
MEM_SAFE_FREE(idmap->map);
MEM_delete<BMIdMap>(idmap);
}
static void check_idx_map(BMIdMap *idmap)
ATTR_NO_OPT static void check_idx_map(BMIdMap *idmap)
{
if (idmap->free_idx_map && idmap->freelist.size() < FREELIST_HASHMAP_THRESHOLD_LOW) {
printf("%s: Deleting free_idx_map\n", __func__);
//printf("%s: Deleting free_idx_map\n", __func__);
MEM_delete<BMIdMap::FreeIdxMap>(idmap->free_idx_map);
idmap->free_idx_map = nullptr;
}
else if (!idmap->free_idx_map && idmap->freelist.size() < FREELIST_HASHMAP_THRESHOLD_HIGH) {
printf("%s: Adding free_idx_map\n", __func__);
//printf("%s: Adding free_idx_map\n", __func__);
idmap->free_idx_map = MEM_new<BMIdMap::FreeIdxMap>("BMIdMap::FreeIdxMap");
@ -236,7 +240,7 @@ static void check_idx_map(BMIdMap *idmap)
}
}
void BM_idmap_assign(BMIdMap *idmap, BMElem *elem)
ATTR_NO_OPT int BM_idmap_alloc(BMIdMap *idmap, BMElem *elem)
{
int id = -1;
@ -260,10 +264,15 @@ void BM_idmap_assign(BMIdMap *idmap, BMElem *elem)
idmap_grow_map(idmap, id);
idmap->map[id] = elem;
BM_ELEM_CD_SET_INT(elem, idmap->cd_id_off[elem->head.htype], id);
return id;
}
void BM_idmap_reassign(BMIdMap *idmap, BMElem *elem, int id)
ATTR_NO_OPT void BM_idmap_assign(BMIdMap *idmap, BMElem *elem, int id)
{
/* Remove id from freelist. */
if (idmap->free_idx_map) {
const int *val;
@ -280,13 +289,15 @@ void BM_idmap_reassign(BMIdMap *idmap, BMElem *elem, int id)
}
}
BM_ELEM_CD_SET_INT(elem, idmap->cd_id_off[elem->head.htype], id);
idmap_grow_map(idmap, id);
idmap->map[id] = elem;
check_idx_map(idmap);
}
void BM_idmap_release(BMIdMap *idmap, BMElem *elem)
ATTR_NO_OPT void BM_idmap_release(BMIdMap *idmap, BMElem *elem, bool clear_id)
{
int id = BM_ELEM_CD_GET_INT(elem, idmap->cd_id_off[(int)elem->head.htype]);
@ -295,7 +306,13 @@ void BM_idmap_release(BMIdMap *idmap, BMElem *elem)
return;
}
idmap->map[id] = nullptr;
if (id < 0 || id >= idmap->map_size || (idmap->map[id] && idmap->map[id] != elem)) {
printf("%s: id corruptions\n", __func__);
}
else {
idmap->map[id] = nullptr;
}
idmap->freelist.append(id);
if (idmap->free_idx_map) {
@ -303,13 +320,19 @@ void BM_idmap_release(BMIdMap *idmap, BMElem *elem)
}
check_idx_map(idmap);
if (clear_id) {
BM_ELEM_CD_SET_INT(elem, idmap->cd_id_off[elem->head.htype], -1);
}
}
void BM_idmap_check_assign(BMIdMap *idmap, BMElem *elem)
int BM_idmap_check_assign(BMIdMap *idmap, BMElem *elem)
{
int id = BM_ELEM_CD_GET_INT(elem, idmap->cd_id_off[(int)elem->head.htype]);
if (id == -1) {
BM_idmap_assign(idmap, elem);
return BM_idmap_alloc(idmap, elem);
}
return id;
}

View File

@ -8,6 +8,8 @@
# define WITH_BM_ID_FREELIST
#endif
//#define USE_NEW_IDMAP
#ifdef __cplusplus
# include "BLI_map.hh"
# include "BLI_vector.hh"
@ -39,15 +41,15 @@ typedef struct BMIdMap {
extern "C" {
#endif
BMIdMap *BM_idmap_new(BMesh *bm);
BMIdMap *BM_idmap_new(BMesh *bm, int elem_mask);
void BM_idmap_check_attributes(BMIdMap *idmap);
void BM_idmap_check_ids(BMIdMap *idmap);
void BM_idmap_destroy(BMIdMap *idmap);
void BM_idmap_assign(BMIdMap *idmap, BMElem *elem);
void BM_idmap_reassign(BMIdMap *idmap, BMElem *elem);
void BM_idmap_release(BMIdMap *idmap, BMElem *elem);
void BM_idmap_check_assign(BMIdMap *idmap, BMElem *elem);
int BM_idmap_alloc(BMIdMap *idmap, BMElem *elem);
void BM_idmap_assign(BMIdMap *idmap, BMElem *elem, int id);
void BM_idmap_release(BMIdMap *idmap, BMElem *elem, bool clear_id);
int BM_idmap_check_assign(BMIdMap *idmap, BMElem *elem);
BLI_INLINE int BM_idmap_get_id(BMIdMap *map, BMElem *elem)
{

View File

@ -11,7 +11,7 @@ struct MemArena;
typedef struct BMCustomLayerReq {
int type;
char *name; // can be NULL
const char *name; // can be NULL
int flag;
} BMCustomLayerReq;

View File

@ -38,8 +38,10 @@
//#include "BLI_strict_flags.h"
#include "bmesh.h"
#include "bmesh_idmap.h"
#include "bmesh_log_intern.h"
#include "bmesh_private.h"
#include "range_tree.h"
//#define BM_VALIDATE_LOG
@ -410,6 +412,8 @@ struct BMLog {
bool has_edges;
int cd_sculpt_vert;
bool dead;
BMIdMap *idmap;
};
static void _bm_log_addref(BMLog *log, const char *func)
@ -473,46 +477,6 @@ typedef struct BMLogFace {
} BMLogFace;
/************************* Get/set element IDs ************************/
BLI_INLINE int get_vert_id(BMesh *bm, BMVert *v)
{
return BM_ELEM_GET_ID(bm, v);
}
BLI_INLINE int get_edge_id(BMesh *bm, BMEdge *e)
{
return BM_ELEM_GET_ID(bm, e);
#if 0
return id;
int id = BM_ELEM_GET_ID(bm, e);
int v1id = BM_ELEM_GET_ID(bm, e->v1);
int v2id = BM_ELEM_GET_ID(bm, e->v2);
// if (v2id < v1id) {
// SWAP(int, v2id, v1id);
//}
id = id | (((v1id ^ v2id) & 1023) << 20);
// return id;
#endif
}
BLI_INLINE int get_face_id(BMesh *bm, BMFace *f)
{
return BM_ELEM_GET_ID(bm, f);
#if 0
int id = BM_ELEM_GET_ID(bm, f);
int id2 = 0;
BMLoop* l = f->l_first;
do {
id2 ^= BM_ELEM_GET_ID(bm, l->v);
} while ((l = l->next) != f->l_first);
return id + ((id2 & 1023) << 20);
#endif
}
/* bypass actual hashing, the keys don't overlap */
#define logkey_hash BLI_ghashutil_inthash_p_simple
@ -530,6 +494,70 @@ BMLogEntry *bm_log_entry_add_ex(
static bool bm_log_entry_free(BMLogEntry *entry);
static bool bm_log_free_direct(BMLog *log, bool safe_mode);
static unsigned char *get_elem_htype_str(int htype)
{
switch (htype) {
case BM_VERT:
return "vertex";
case BM_EDGE:
return "edge";
case BM_LOOP:
return "loop";
case BM_FACE:
return "face";
default:
return "unknown type";
}
}
#ifdef USE_NEW_IDMAP
void bm_log_free_id(BMLog *log, BMElem *elem, bool clear_id)
{
BM_idmap_release(log->idmap, elem, clear_id);
}
void bm_log_alloc_id(BMLog *log, BMElem *elem)
{
BM_idmap_check_assign(log->idmap, elem);
}
void bm_log_assign_id(BMLog *log, BMElem *elem, int id, bool check_unique)
{
if (check_unique) {
BMElem *old;
if ((old = BM_idmap_lookup(log->idmap, id))) {
printf("id conflict in bm_assign_id; elem %p (a %s) is being reassinged to id %d.\n",
elem,
get_elem_htype_str((int)elem->head.htype),
(int)id);
printf(
" elem %p (a %s) will get a new id\n", old, get_elem_htype_str((int)old->head.htype));
BM_idmap_assign(log->idmap, elem, id);
return;
}
}
BM_idmap_assign(log->idmap, elem, id);
}
#else
void bm_log_free_id(BMLog *log, BMElem *elem, bool /* clear_id */)
{
bm_free_id(log->bm, elem);
}
void bm_log_alloc_id(BMLog *log, BMElem *elem)
{
bm_alloc_id(log->bm, elem);
}
void bm_log_assign_id(BMLog *log, BMElem *elem, int id, bool check_unique)
{
bm_assign_id(log->bm, elem, id, check_unique);
}
#endif
static void *log_ghash_lookup(BMLog *log, GHash *gh, const void *key)
{
BLI_rw_mutex_lock(&log->lock, THREAD_LOCK_READ);
@ -611,6 +639,80 @@ static bool log_ghash_ensure_p(BMLog *log, GHash *gh, void *key, void ***val)
return ret;
}
#ifdef USE_NEW_IDMAP
ATTR_NO_OPT static void bm_log_set_id_raw(BMLog *log, BMElem *elem, int id)
{
BM_ELEM_CD_SET_INT(elem, log->idmap->cd_id_off[elem->head.htype], id);
}
/* Get the vertex's unique ID from the log */
ATTR_NO_OPT static uint bm_log_vert_id_get(BMLog *log, BMVert *v)
{
return BM_idmap_get_id(log->idmap, (BMElem *)v);
}
/*Get a vertex from its unique ID */
ATTR_NO_OPT static BMElem *bm_log_elem_from_id(BMLog *log, uint id)
{
if (log->idmap->map && id >= ((unsigned int)log->idmap->map_size)) {
return NULL;
}
return BM_idmap_lookup(log->idmap, id);
}
/* Get a vertex from its unique ID */
ATTR_NO_OPT static BMVert *bm_log_vert_from_id(BMLog *log, uint id)
{
return (BMVert *)bm_log_elem_from_id(log, id);
}
BMVert *BM_log_id_vert_get(BMLog *log, uint id)
{
return bm_log_vert_from_id(log, id);
}
/* Get the edges's unique ID from the log */
ATTR_NO_OPT static uint bm_log_edge_id_get(BMLog *log, BMEdge *e)
{
return BM_idmap_get_id(log->idmap, (BMElem *)e);
}
static uint bm_log_loop_id_get(BMLog *log, BMLoop *l)
{
return BM_idmap_get_id(log->idmap, (BMElem *)l);
}
/* Get a vertex from its unique ID */
static BMEdge *bm_log_edge_from_id(BMLog *log, uint id)
{
return (BMEdge *)bm_log_elem_from_id(log, id);
}
/* Get the face's unique ID from the log */
ATTR_NO_OPT static uint bm_log_face_id_get(BMLog *log, BMFace *f)
{
return BM_idmap_get_id(log->idmap, (BMElem *)f);
}
ATTR_NO_OPT static uint bm_log_elem_id_get(BMLog *log, BMElem *elem)
{
return BM_idmap_get_id(log->idmap, elem);
}
/* Get a face from its unique ID */
ATTR_NO_OPT static BMFace *bm_log_face_from_id(BMLog *log, uint id)
{
return (BMFace *)bm_log_elem_from_id(log, id);
}
#else
ATTR_NO_OPT static void bm_log_set_id_raw(BMLog *log, BMElem *elem, int id)
{
BM_ELEM_CD_SET_INT(elem, log->bm->idmap.cd_id_off[elem->head.htype], id);
}
/* Get the vertex's unique ID from the log */
static uint bm_log_vert_id_get(BMLog *log, BMVert *v)
{
@ -642,10 +744,15 @@ BMVert *BM_log_id_vert_get(BMLog *log, uint id)
return bm_log_vert_from_id(log, id);
}
/* Get the vertex's unique ID from the log */
/* Get the edges's unique ID from the log */
static uint bm_log_edge_id_get(BMLog *log, BMEdge *e)
{
return (uint)get_edge_id(log->bm, e);
return BM_ELEM_GET_ID(log->bm, e);
}
static uint bm_log_loop_id_get(BMLog *log, BMLoop *l)
{
return BM_ELEM_GET_ID(log->bm, l);
}
/* Get a vertex from its unique ID */
@ -654,25 +761,15 @@ static BMEdge *bm_log_edge_from_id(BMLog *log, uint id)
return (BMEdge *)BM_ELEM_FROM_ID(log->bm, id);
}
BMEdge *BM_log_id_edge_get(BMLog *log, uint id)
{
return bm_log_edge_from_id(log, id);
}
/* Get the face's unique ID from the log */
static uint bm_log_face_id_get(BMLog *log, BMFace *f)
{
return (uint)get_face_id(log->bm, f);
return BM_ELEM_GET_ID(log->bm, f);
}
uint BM_log_vert_id_get(BMLog *log, BMVert *v)
static uint bm_log_elem_id_get(BMLog *log, BMElem *elem)
{
return bm_log_vert_id_get(log, v);
}
uint BM_log_face_id_get(BMLog *log, BMFace *f)
{
return bm_log_face_id_get(log, f);
return BM_ELEM_GET_ID(log->bm, elem);
}
/* Get a face from its unique ID */
@ -685,6 +782,23 @@ static BMFace *bm_log_face_from_id(BMLog *log, uint id)
return (BMFace *)BM_ELEM_FROM_ID(log->bm, id);
}
#endif
uint BM_log_vert_id_get(BMLog *log, BMVert *v)
{
return bm_log_vert_id_get(log, v);
}
BMEdge *BM_log_id_edge_get(BMLog *log, uint id)
{
return bm_log_edge_from_id(log, id);
}
uint BM_log_face_id_get(BMLog *log, BMFace *f)
{
return bm_log_face_id_get(log, f);
}
BMFace *BM_log_id_face_get(BMLog *log, uint id)
{
return bm_log_face_from_id(log, id);
@ -813,10 +927,13 @@ static void bm_log_edge_bmedge_copy(
DEBUG_FILE, "%s: e is not an edge; htype: %d\n", GET_TRACE(le, entry), (int)e->head.htype);
}
le->v1 = (uint)BM_ELEM_GET_ID(log->bm, e->v1);
le->v2 = (uint)BM_ELEM_GET_ID(log->bm, e->v2);
BM_idmap_check_assign(log->idmap, (BMElem *)e->v1);
BM_idmap_check_assign(log->idmap, (BMElem *)e->v2);
le->head.id = (uint)BM_ELEM_GET_ID(log->bm, e);
le->v1 = (uint)bm_log_vert_id_get(log, e->v1);
le->v2 = (uint)bm_log_vert_id_get(log, e->v2);
le->head.id = (uint)bm_log_edge_id_get(log, e);
le->hflag = e->head.hflag;
if (copy_customdata) {
@ -849,12 +966,16 @@ static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
BMLogFace *lf = BLI_mempool_alloc(entry->pool_faces);
lf->len = (size_t)f->len;
lf->head.id = (uint)BM_ELEM_GET_ID(log->bm, f);
lf->head.id = (uint)bm_log_face_id_get(log, f);
lf->mat_nr = f->mat_nr;
SET_TRACE(lf);
#ifdef USE_NEW_IDMAP
bool have_loop_ids = (log->idmap->flag & BM_LOOP);
#else
bool have_loop_ids = (log->bm->idmap.flag & BM_LOOP);
#endif
if (f->len > MAX_FACE_RESERVED) {
lf->v_ids = (uint *)BLI_memarena_alloc(entry->arena, sizeof(*lf->v_ids) * lf->len);
@ -875,12 +996,14 @@ static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
BMLoop *l = f->l_first;
do {
if (have_loop_ids) {
lf->l_ids[i] = (uint)BM_ELEM_GET_ID(log->bm, l);
BM_idmap_check_assign(log->idmap, (BMElem *)l);
lf->l_ids[i] = (uint)bm_log_loop_id_get(log, l);
}
else {
lf->l_ids[i] = (uint)-1;
}
BM_idmap_check_assign(log->idmap, (BMElem *)l->v);
lf->v_ids[i] = bm_log_vert_id_get(log, l->v);
lf->customdata[i] = NULL;
@ -896,6 +1019,8 @@ static void bm_log_face_bmface_copy(
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)f);
if ((int)lf->len != (int)f->len) {
fprintf(DEBUG_FILE,
"%s: face %d's topology mismatches log entry's\n",
@ -905,7 +1030,7 @@ static void bm_log_face_bmface_copy(
return;
}
if ((int)BM_ELEM_GET_ID(log->bm, f) != (int)lf->head.id) {
if ((int)bm_log_face_id_get(log, f) != (int)lf->head.id) {
fprintf(DEBUG_FILE,
"%s: face %d's id mismstaches log entry's\n",
GET_TRACE(lf, entry),
@ -1099,6 +1224,9 @@ static void bm_log_edges_unmake(
continue;
}
#ifdef USE_NEW_IDMAP
BM_idmap_release(log->idmap, (BMElem *)e, false);
#endif
BM_edge_kill(bm, e);
}
}
@ -1125,6 +1253,9 @@ static void bm_log_verts_unmake(
continue;
}
#ifdef USE_NEW_IDMAP
BM_idmap_release(log->idmap, (BMElem *)v, false);
#endif
BM_vert_kill(bm, v);
}
}
@ -1153,9 +1284,9 @@ static void bm_log_faces_unmake(
BLI_array_clear(e_tri);
BMLoop *l;
int i;
#ifdef USE_NEW_IDMAP
BM_idmap_release(log->idmap, (BMElem *)f, false);
#endif
BM_face_kill(bm, f);
#if 0
@ -1244,7 +1375,7 @@ static void bm_log_verts_restore(
}
#endif
bm_assign_id(bm, (BMElem *)v, POINTER_AS_UINT(key), true);
bm_log_assign_id(log, (BMElem *)v, POINTER_AS_UINT(key), true);
if (callbacks) {
callbacks->on_vert_add(v, callbacks->userdata);
@ -1283,10 +1414,10 @@ static void bm_log_edges_restore(
"%s: edge already %d existed (but id was %d):\n",
GET_TRACE(le, entry),
(int)le->head.id,
BM_ELEM_GET_ID(bm, e));
bm_log_edge_id_get(log, e));
if (BM_ELEM_GET_ID(bm, e) != (int)le->head.id) {
bm_free_id(bm, (BMElem *)e);
if (bm_log_edge_id_get(log, e) != (int)le->head.id) {
bm_log_free_id(log, (BMElem *)e, true);
}
else {
assign_id = false;
@ -1305,10 +1436,10 @@ static void bm_log_edges_restore(
#endif
if (assign_id) {
bm_assign_id(bm, (BMElem *)e, le->head.id, true);
bm_log_assign_id(log, (BMElem *)e, le->head.id, true);
}
if ((uint)BM_ELEM_GET_ID(bm, e) != le->head.id) {
if ((uint)bm_log_edge_id_get(log, e) != le->head.id) {
fprintf(DEBUG_FILE, "%s: error assigning id\n", GET_TRACE(le, entry));
}
@ -1318,22 +1449,28 @@ static void bm_log_edges_restore(
}
}
static void bm_log_faces_restore(
ATTR_NO_OPT static void bm_log_faces_restore(
BMesh *bm, BMLog *log, GHash *faces, BMLogEntry *entry, BMLogCallbacks *callbacks)
{
GHashIterator gh_iter;
BMVert **vs_tmp = NULL;
BLI_array_staticdeclare(vs_tmp, 32);
void *_scratch = alloca(bm->idmap.cd_id_off[BM_FACE] + sizeof(void *));
#ifdef USE_NEW_IDMAP
void *_scratch = alloca(log->idmap->cd_id_off[BM_FACE] + sizeof(void *));
bool have_loop_ids = (log->idmap->flag & BM_LOOP);
#else
void *_scratch = alloca(bm->idmap.cd_id_off[BM_FACE] + sizeof(void *));
bool have_loop_ids = (log->bm->idmap.flag & BM_LOOP);
#endif
GHASH_ITER (gh_iter, faces) {
BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
BMElem id_holder = {0};
id_holder.head.htype = BM_FACE;
id_holder.head.data = _scratch;
bm_assign_id(bm, &id_holder, lf->head.id, true);
bm_log_assign_id(log, &id_holder, lf->head.id, true);
BLI_array_clear(vs_tmp);
bool bad = false;
@ -1355,7 +1492,12 @@ static void bm_log_faces_restore(
if (!v) {
BMIter iter;
BMVert *v2;
#ifdef USE_NEW_IDMAP
const int cd_id = log->idmap->cd_id_off[BM_VERT];
#else
const int cd_id = bm->idmap.cd_id_off[BM_VERT];
#endif
bad = true;
@ -1429,15 +1571,15 @@ static void bm_log_faces_restore(
CustomData_bmesh_copy_data(&entry->pdata, &bm->pdata, lf->customdata_f, &f->head.data);
}
bm_free_id(bm, &id_holder);
bm_assign_id(bm, (BMElem *)f, lf->head.id, true);
bm_log_free_id(log, &id_holder, true);
bm_log_assign_id(log, (BMElem *)f, lf->head.id, true);
BMLoop *l = f->l_first;
int j = 0;
do {
if (have_loop_ids) {
bm_assign_id(bm, (BMElem *)l, lf->l_ids[j], true);
bm_log_assign_id(log, (BMElem *)l, lf->l_ids[j], true);
}
if (lf->customdata[j]) {
@ -1498,6 +1640,9 @@ static void bm_log_vert_values_swap(
}
CustomData_bmesh_swap_data(&entry->vdata, &bm->vdata, lv->customdata, &v->head.data);
/* Ensure we have the correct id */
bm_log_set_id_raw(log, (BMElem *)v, id);
}
if (callbacks) {
@ -1533,6 +1678,9 @@ static void bm_log_edge_values_swap(
}
CustomData_bmesh_swap_data(&entry->edata, &bm->edata, le->customdata, &e->head.data);
/* Ensure we have the correct id. */
bm_log_set_id_raw(log, (BMElem *)e, le->head.id);
}
if (callbacks) {
@ -1598,6 +1746,9 @@ static void bm_log_face_values_swap(BMLog *log,
}
} while ((i++, l = l->next) != f->l_first);
/* Ensure we have the correct id. */
bm_log_set_id_raw(log, (BMElem *)f, lf->head.id);
if (callbacks) {
callbacks->on_face_change(f, callbacks->userdata, old_cdata);
}
@ -1812,10 +1963,12 @@ void BM_log_set_bm(BMesh *bm, BMLog *log)
}
/* Allocate, initialize, and assign a new BMLog */
BMLog *BM_log_create(BMesh *bm, int cd_sculpt_vert)
BMLog *BM_log_create(BMesh *bm, BMIdMap *idmap, int cd_sculpt_vert)
{
BMLog *log = MEM_callocN(sizeof(*log), __func__);
log->idmap = idmap;
#ifdef DEBUG_LOG_TO_FILE
if (!DEBUG_FILE) {
DEBUG_FILE = fopen("bmlog_debug.txt", "w");
@ -1878,9 +2031,9 @@ BMLog *bm_log_from_existing_entries_create(BMesh *bm, BMLog *log, BMLogEntry *en
* The unused IDs field of the log will be initialized by taking all
* keys from all GHashes in the log entry.
*/
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMIdMap *idmap, BMLogEntry *entry)
{
BMLog *log = BM_log_create(bm, -1);
BMLog *log = BM_log_create(bm, idmap, -1);
bm_log_from_existing_entries_create(bm, log, entry);
@ -2442,7 +2595,7 @@ static void log_idmap_load(BMesh *bm, BMLog *log, BMLogEntry *entry)
int *lmap = idmap->maps[BM_LOOP];
BM_ITER_MESH_INDEX (elem, &iter, bm, iters[i], j) {
bm_assign_id(bm, elem, (uint)map[j], true);
bm_log_assign_id(log, elem, (uint)map[j], true);
// deal with loops
if (type == BM_FACE && cd_loop_id >= 0) {
@ -2450,7 +2603,7 @@ static void log_idmap_load(BMesh *bm, BMLog *log, BMLogEntry *entry)
BMLoop *l = f->l_first;
do {
bm_assign_id(bm, (BMElem *)l, (uint)lmap[loopi], true);
bm_log_assign_id(log, (BMElem *)l, (uint)lmap[loopi], true);
loopi++;
} while ((l = l->next) != f->l_first);
@ -2506,7 +2659,7 @@ static void log_idmap_swap(BMesh *bm, BMLog *log, BMLogEntry *entry)
BM_ITER_MESH_INDEX (elem, &iter, bm, iters[i], j) {
int id = BM_ELEM_CD_GET_INT(elem, cd_id);
bm_assign_id(bm, elem, (uint)map[j], true);
bm_log_assign_id(log, elem, (uint)map[j], true);
map[j] = id;
// deal with loops
@ -2517,7 +2670,7 @@ static void log_idmap_swap(BMesh *bm, BMLog *log, BMLogEntry *entry)
do {
int id2 = BM_ELEM_CD_GET_INT(l, cd_loop_id);
bm_assign_id(bm, (BMElem *)l, (uint)lmap[loopi], true);
bm_log_assign_id(log, (BMElem *)l, (uint)lmap[loopi], true);
lmap[loopi] = id2;
loopi++;
@ -2601,6 +2754,8 @@ static void bm_log_undo_intern(BMesh *bm, BMLog *log, BMLogEntry *entry, BMLogCa
bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
bm->elem_table_dirty |= BM_VERT | BM_EDGE | BM_FACE;
BM_idmap_check_attributes(log->idmap);
if (entry->type == LOG_ENTRY_FULL_MESH) {
full_copy_swap(bm, log, entry);
@ -2615,6 +2770,8 @@ static void bm_log_undo_intern(BMesh *bm, BMLog *log, BMLogEntry *entry, BMLogCa
if (callbacks && callbacks->on_mesh_id_restore) {
callbacks->on_mesh_id_restore(callbacks->userdata);
}
BM_idmap_check_attributes(log->idmap);
return;
}
@ -2696,6 +2853,8 @@ void BM_log_undo(BMesh *bm, BMLog *log, BMLogCallbacks *callbacks)
* Has no effect if there's nothing left to redo */
static void bm_log_redo_intern(BMesh *bm, BMLog *log, BMLogEntry *entry, BMLogCallbacks *callbacks)
{
BM_idmap_check_attributes(log->idmap);
if (entry->type == LOG_ENTRY_FULL_MESH) {
// hrm, should we swap?
full_copy_swap(bm, log, entry);
@ -2712,6 +2871,8 @@ static void bm_log_redo_intern(BMesh *bm, BMLog *log, BMLogEntry *entry, BMLogCa
if (callbacks && callbacks->on_mesh_id_restore) {
callbacks->on_mesh_id_restore(callbacks->userdata);
}
BM_idmap_check_attributes(log->idmap);
return;
}
@ -2876,9 +3037,11 @@ void BM_log_vert_before_modified(BMLog *log,
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)v);
BMLogEntry *entry = log->current_entry;
BMLogVert *lv;
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
uint v_id = (uint)bm_log_vert_id_get(log, v);
void *key = POINTER_FROM_UINT(v_id);
void **val_p;
@ -2909,9 +3072,11 @@ void BM_log_vert_before_modified(BMLog *log,
void BM_log_edge_before_modified(BMLog *log, BMEdge *e, bool log_customdata)
{
BM_idmap_check_assign(log->idmap, (BMElem *)e);
BMLogEntry *entry = log->current_entry;
BMLogEdge *le;
uint e_id = (uint)get_edge_id(log->bm, e);
uint e_id = (uint)bm_log_edge_id_get(log, e);
void *key = POINTER_FROM_UINT(e_id);
void **val_p;
@ -2931,7 +3096,7 @@ void _BM_log_edge_added(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
_BM_log_edge_topo_post(log, e BMLOG_DEBUG_ARGS_VALUES);
_BM_log_edge_post(log, e BMLOG_DEBUG_ARGS_VALUES);
bm_logstack_pop();
}
@ -2942,7 +3107,7 @@ void _BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset BML
{
bm_logstack_push();
_BM_log_vert_topo_post(log, v BMLOG_DEBUG_ARGS_VALUES);
_BM_log_vert_post(log, v BMLOG_DEBUG_ARGS_VALUES);
bm_logstack_pop();
}
@ -2953,8 +3118,10 @@ void _BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset BML
*/
void _BM_log_face_modified(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
{
BM_idmap_check_assign(log->idmap, (BMElem *)f);
BMLogFace *lf;
uint f_id = (uint)get_face_id(log->bm, f);
uint f_id = (uint)bm_log_face_id_get(log, f);
void *key = POINTER_FROM_UINT(f_id);
// LOGPRINT("key %d\n", (int)key);
@ -2972,7 +3139,9 @@ void _BM_log_face_modified(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
bool BM_log_has_vert(BMLog *log, BMVert *v)
{
int id = BM_ELEM_GET_ID(log->bm, v);
BM_idmap_check_assign(log->idmap, (BMElem *)v);
int id = bm_log_vert_id_get(log, v);
bool ret = BLI_ghash_haskey(log->current_entry->topo_modified_verts_pre, POINTER_FROM_INT(id));
ret = ret ||
@ -2984,7 +3153,8 @@ bool BM_log_has_vert(BMLog *log, BMVert *v)
bool BM_log_has_edge(BMLog *log, BMEdge *e)
{
int id = get_edge_id(log->bm, e);
BM_idmap_check_assign(log->idmap, (BMElem *)e);
int id = bm_log_edge_id_get(log, e);
bool ret = BLI_ghash_haskey(log->current_entry->topo_modified_edges_pre, POINTER_FROM_INT(id));
ret = ret ||
@ -2996,7 +3166,8 @@ bool BM_log_has_edge(BMLog *log, BMEdge *e)
bool BM_log_has_face(BMLog *log, BMFace *f)
{
int id = get_face_id(log->bm, f);
BM_idmap_check_assign(log->idmap, (BMElem *)f);
int id = bm_log_face_id_get(log, f);
bool ret = BLI_ghash_haskey(log->current_entry->modified_faces, POINTER_FROM_INT(id));
ret = ret ||
@ -3016,17 +3187,19 @@ void _BM_log_face_added(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
_BM_log_face_topo_post(log, f BMLOG_DEBUG_ARGS_VALUES);
_BM_log_face_post(log, f BMLOG_DEBUG_ARGS_VALUES);
bm_logstack_pop();
}
void _BM_log_face_topo_pre(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
void _BM_log_face_pre(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)f);
BMLogEntry *entry = log->current_entry;
uint f_id = (uint)get_face_id(log->bm, f);
uint f_id = (uint)bm_log_face_id_get(log, f);
void *key = POINTER_FROM_UINT(f_id);
if (log_ghash_remove(entry->topo_modified_faces_post, key, entry->pool_faces)) {
@ -3062,12 +3235,14 @@ void _BM_log_face_topo_pre(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
bm_logstack_pop();
}
void _BM_log_face_topo_post(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
void _BM_log_face_post(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)f);
BMLogEntry *entry = log->current_entry;
uint f_id = (uint)get_face_id(log->bm, f);
uint f_id = (uint)bm_log_face_id_get(log, f);
void *key = POINTER_FROM_UINT(f_id);
BMLogFace *lf;
@ -3102,12 +3277,14 @@ void _BM_log_face_topo_post(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
bm_logstack_pop();
}
void _BM_log_edge_topo_pre(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
void _BM_log_edge_pre(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)e);
BMLogEntry *entry = log->current_entry;
uint f_id = (uint)get_edge_id(log->bm, e);
uint f_id = (uint)bm_log_edge_id_get(log, e);
void *key = POINTER_FROM_UINT(f_id);
void **val = NULL;
@ -3148,12 +3325,14 @@ void _BM_log_edge_topo_pre(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
bm_logstack_pop();
}
void _BM_log_edge_topo_post(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
void _BM_log_edge_post(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)e);
BMLogEntry *entry = log->current_entry;
uint f_id = (uint)get_edge_id(log->bm, e);
uint f_id = (uint)bm_log_edge_id_get(log, e);
void *key = POINTER_FROM_UINT(f_id);
BMLogEdge *le;
@ -3187,12 +3366,14 @@ void _BM_log_edge_topo_post(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
bm_logstack_pop();
}
void _BM_log_vert_topo_pre(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS)
void _BM_log_vert_pre(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)v);
BMLogEntry *entry = log->current_entry;
uint f_id = (uint)get_vert_id(log->bm, v);
uint f_id = (uint)bm_log_vert_id_get(log, v);
void *key = POINTER_FROM_UINT(f_id);
void **val = NULL;
@ -3228,12 +3409,14 @@ void _BM_log_vert_topo_pre(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS)
bm_logstack_pop();
}
void _BM_log_vert_topo_post(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS)
void _BM_log_vert_post(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)v);
BMLogEntry *entry = log->current_entry;
uint f_id = (uint)get_vert_id(log->bm, v);
uint f_id = (uint)bm_log_vert_id_get(log, v);
void *key = POINTER_FROM_UINT(f_id);
BMLogVert *lv;
@ -3298,13 +3481,15 @@ void _BM_log_vert_removed(BMLog *log, BMVert *v, int UNUSED(cd_vert_mask_offset)
{
bm_logstack_push();
if (bm_log_vert_from_id(log, (uint)BM_ELEM_GET_ID(log->bm, v)) != v) {
BM_idmap_check_assign(log->idmap, (BMElem *)v);
if (bm_log_vert_from_id(log, (uint)bm_log_vert_id_get(log, v)) != v) {
fprintf(DEBUG_FILE, "%s: idmap error\n", __func__);
bm_logstack_pop();
return;
}
_BM_log_vert_topo_pre(log, v BMLOG_DEBUG_ARGS_VALUES);
_BM_log_vert_pre(log, v BMLOG_DEBUG_ARGS_VALUES);
bm_logstack_pop();
}
@ -3319,18 +3504,32 @@ BMVert *BM_log_edge_split_do(BMLog *log, BMEdge *e, BMVert *v, BMEdge **newe, fl
bm_log_message("edge split");
BM_idmap_check_assign(log->idmap, (BMElem *)e->v1);
BM_idmap_check_assign(log->idmap, (BMElem *)e->v2);
BM_idmap_check_assign(log->idmap, (BMElem *)e);
BMEdge *tmp = NULL;
if (!newe) {
newe = &tmp;
}
BM_log_edge_topo_pre(log, e);
BM_log_edge_pre(log, e);
BMVert *newv = BM_edge_split(log->bm, e, v, newe, t);
BM_idmap_alloc(log->idmap, (BMElem *)newv);
BM_idmap_alloc(log->idmap, (BMElem *)*newe);
BMIter iter;
BMLoop *l;
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
BM_idmap_check_assign(log->idmap, (BMElem *)l->e);
BM_idmap_check_assign(log->idmap, (BMElem *)l->f);
}
BM_log_vert_added(log, newv, -1);
BM_log_edge_topo_post(log, e);
BM_log_edge_topo_post(log, *newe);
BM_log_edge_post(log, e);
BM_log_edge_post(log, *newe);
bm_logstack_pop();
@ -3344,32 +3543,32 @@ BMVert *BM_log_edge_split_do(BMLog *log, BMEdge *e, BMVert *v, BMEdge **newe, fl
BMesh* bm = log->bm;
int eid0 = BM_ELEM_GET_ID(bm, e);
int eid0 = bm_log_vert_id_get(log, e);
bm_log_message("edge split");
bm_log_message(" esplit: remove edge %d", eid0);
BM_log_edge_removed(log, e);
BMVert* v1 = e->v1, * v2 = e->v2;
uint id1 = (uint)BM_ELEM_GET_ID(bm, v1);
uint id2 = (uint)BM_ELEM_GET_ID(bm, v2);
uint id1 = (uint)bm_log_vert_id_get(log, v1);
uint id2 = (uint)bm_log_vert_id_get(log, v2);
bm_log_message(" esplit: split edge %d (v1=%d v2=%d)", eid0, id1, id2);
BMVert* newv = BM_edge_split(log->bm, e, v, newe, t);
uint id3 = (uint)BM_ELEM_GET_ID(bm, newv);
uint nid = (uint)BM_ELEM_GET_ID(bm, (*newe));
uint id3 = (uint)bm_log_vert_id_get(log, newv);
uint nid = (uint)bm_log_vert_id_get(log, (*newe));
// get a new id
# ifndef WITH_BM_ID_FREELIST
uint id = range_tree_uint_take_any(log->bm->idmap.idtree);
bm_free_id(log->bm, (BMElem*)e);
bm_assign_id(log->bm, (BMElem*)e, id, true);
bm_log_free_id(log, (BMElem*)e, true);
bm_log_assign_id(log, (BMElem*)e, id, true);
# else
bm_free_id(log->bm, (BMElem*)e);
bm_alloc_id(log->bm, (BMElem*)e);
bm_log_free_id(log, (BMElem*)e, true);
bm_log_alloc_id(log, (BMElem*)e);
uint id = BM_ELEM_GET_ID(bm, e);
uint id = bm_log_vert_id_get(log, e);
# endif
bm_log_message(" esplit: add new vert %d", id3);
@ -3391,14 +3590,16 @@ void _BM_log_edge_removed(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
if (bm_log_edge_from_id(log, (uint)BM_ELEM_GET_ID(log->bm, e)) != e) {
BM_idmap_check_assign(log->idmap, (BMElem *)e);
if (bm_log_edge_from_id(log, (uint)bm_log_edge_id_get(log, e)) != e) {
fprintf(DEBUG_FILE, "%s: idmap error\n", __func__);
bm_logstack_pop();
return;
}
BMLogEntry *entry = log->current_entry;
uint e_id = (uint)get_edge_id(log->bm, e);
uint e_id = (uint)bm_log_edge_id_get(log, e);
void *key = POINTER_FROM_UINT(e_id);
bool ok = !BLI_ghash_haskey(entry->topo_modified_edges_pre, key);
@ -3409,7 +3610,7 @@ void _BM_log_edge_removed(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS)
ok = ok && ok2;
if (ok) {
_BM_log_edge_topo_pre(log, e BMLOG_DEBUG_ARGS_VALUES);
_BM_log_edge_pre(log, e BMLOG_DEBUG_ARGS_VALUES);
bm_logstack_pop();
return;
}
@ -3423,8 +3624,10 @@ void _BM_log_face_removed(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
{
bm_logstack_push();
BM_idmap_check_assign(log->idmap, (BMElem *)f);
BMLogEntry *entry = log->current_entry;
uint f_id = (uint)get_face_id(log->bm, f);
uint f_id = (uint)bm_log_face_id_get(log, f);
void *key = POINTER_FROM_UINT(f_id);
bool ok = !BLI_ghash_haskey(entry->topo_modified_faces_pre, key);
@ -3435,7 +3638,7 @@ void _BM_log_face_removed(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS)
ok = ok && ok2;
if (ok) {
_BM_log_face_topo_pre(log, f BMLOG_DEBUG_ARGS_VALUES);
_BM_log_face_pre(log, f BMLOG_DEBUG_ARGS_VALUES);
bm_logstack_pop();
return;
}
@ -3894,7 +4097,7 @@ static bool bm_log_validate_intern(
}
BM_ITER_MESH (elem, &iter, bm, iters[i]) {
uint id = BM_ELEM_GET_ID(bm, elem);
uint id = bm_log_elem_id_get(newlog, elem);
void *key = POINTER_FROM_UINT(id);
bool exist1 = BLI_ghash_haskey(ghashes1[i], POINTER_FROM_UINT(id));
@ -4003,37 +4206,37 @@ bool BM_log_validate(BMesh *inbm, BMLogEntry *entry, bool is_applied)
bool BM_log_has_vert_pre(BMLog *log, BMVert *v)
{
return BLI_ghash_haskey(log->current_entry->topo_modified_verts_pre,
POINTER_FROM_UINT(BM_ELEM_GET_ID(log->bm, v)));
POINTER_FROM_UINT(bm_log_vert_id_get(log, v)));
}
bool BM_log_has_edge_pre(BMLog *log, BMEdge *e)
{
return BLI_ghash_haskey(log->current_entry->topo_modified_edges_pre,
POINTER_FROM_UINT(BM_ELEM_GET_ID(log->bm, e)));
POINTER_FROM_UINT(bm_log_edge_id_get(log, e)));
}
bool BM_log_has_face_pre(BMLog *log, BMFace *f)
{
return BLI_ghash_haskey(log->current_entry->topo_modified_faces_pre,
POINTER_FROM_UINT(BM_ELEM_GET_ID(log->bm, f)));
POINTER_FROM_UINT(bm_log_face_id_get(log, f)));
}
bool BM_log_has_vert_post(BMLog *log, BMVert *v)
{
return BLI_ghash_haskey(log->current_entry->topo_modified_verts_post,
POINTER_FROM_UINT(BM_ELEM_GET_ID(log->bm, v)));
POINTER_FROM_UINT(bm_log_vert_id_get(log, v)));
}
bool BM_log_has_edge_post(BMLog *log, BMEdge *e)
{
return BLI_ghash_haskey(log->current_entry->topo_modified_edges_post,
POINTER_FROM_UINT(BM_ELEM_GET_ID(log->bm, e)));
POINTER_FROM_UINT(bm_log_edge_id_get(log, e)));
}
bool BM_log_has_face_post(BMLog *log, BMFace *f)
{
return BLI_ghash_haskey(log->current_entry->topo_modified_faces_post,
POINTER_FROM_UINT(BM_ELEM_GET_ID(log->bm, f)));
POINTER_FROM_UINT(bm_log_face_id_get(log, f)));
}
void BM_log_get_changed(BMesh *bm, BMLogEntry *_entry, SmallHash *sh)
void BM_log_get_changed(BMesh *bm, BMIdMap *idmap, BMLogEntry *_entry, SmallHash *sh)
{
BMLogEntry *entry = _entry;
@ -4052,9 +4255,15 @@ void BM_log_get_changed(BMesh *bm, BMLogEntry *_entry, SmallHash *sh)
uint id = POINTER_AS_UINT(key);
/* Note: elements are not guaranteed to exist */
#ifdef USE_NEW_IDMAP
if (id >= idmap->map_size) {
continue;
}
#else
if (id >= bm->idmap.map_size) {
continue;
}
#endif
BMElem *elem = BM_ELEM_FROM_ID(bm, id);
@ -4069,3 +4278,8 @@ void BM_log_get_changed(BMesh *bm, BMLogEntry *_entry, SmallHash *sh)
entry = entry->combined_next;
}
}
void BM_log_set_idmap(BMLog *log, struct BMIdMap *idmap)
{
log->idmap = idmap;
}

View File

@ -18,10 +18,12 @@ typedef struct BMLogEntry BMLogEntry;
extern "C" {
#endif
struct BMIdMap;
/**
* Allocate, initialize, and assign a new BMLog.
*/
BMLog *BM_log_create(BMesh *bm);
BMLog *BM_log_create(BMesh *bm, struct BMIdMap *idmap, int cd_sculpt_vert);
/**
* Allocate and initialize a new #BMLog using existing #BMLogEntries
@ -32,7 +34,7 @@ BMLog *BM_log_create(BMesh *bm);
* The unused IDs field of the log will be initialized by taking all
* keys from all GHashes in the log entry.
*/
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry);
BMLog *BM_log_from_existing_entries_create(BMesh *bm, struct BMIdMap *idmap, BMLogEntry *entry);
/**
* Free all the data in a BMLog including the log itself.

View File

@ -39,6 +39,7 @@ struct BMFace;
struct BMVert;
struct BMesh;
struct RangeTreeUInt;
struct BMIdMap;
typedef struct BMLog BMLog;
typedef struct BMLogEntry BMLogEntry;
@ -75,8 +76,10 @@ void _bm_logstack_push(const char *name);
# define bm_logstack_pop()
#endif
struct BMIdMap;
/* Allocate and initialize a new BMLog */
BMLog *BM_log_create(BMesh *bm, int cd_sculpt_vert);
BMLog *BM_log_create(BMesh *bm, struct BMIdMap *idmap, int cd_sculpt_vert);
void BM_log_set_cd_offsets(BMLog *log, int cd_sculpt_vert);
/* Allocate and initialize a new BMLog using existing BMLogEntries */
@ -88,7 +91,7 @@ void BM_log_set_cd_offsets(BMLog *log, int cd_sculpt_vert);
* The unused IDs field of the log will be initialized by taking all
* keys from all GHashes in the log entry.
*/
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry);
BMLog *BM_log_from_existing_entries_create(BMesh *bm, struct BMIdMap *idmap, BMLogEntry *entry);
/* Free all the data in a BMLog including the log itself */
bool BM_log_free(BMLog *log, bool safe_mode);
@ -279,6 +282,8 @@ void BM_log_redo_skip(BMesh *bm, BMLog *log);
void BM_log_undo_skip(BMesh *bm, BMLog *log);
BMVert *BM_log_edge_split_do(BMLog *log, BMEdge *e, BMVert *v, BMEdge **newe, float t);
void BM_log_set_idmap(BMLog *log, struct BMIdMap *idmap);
int BM_log_entry_size(BMLogEntry *entry);
bool BM_log_has_vert(BMLog *log, BMVert *v);
@ -294,30 +299,29 @@ bool BM_log_has_edge_pre(BMLog *log, BMEdge *e);
bool BM_log_has_face_pre(BMLog *log, BMFace *f);
/*Log an edge before changing its topological connections*/
void _BM_log_edge_topo_pre(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS);
#define BM_log_edge_topo_pre(log, e) _BM_log_edge_topo_pre(log, e BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_edge_pre(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS);
#define BM_log_edge_pre(log, e) _BM_log_edge_pre(log, e BMLOG_DEBUG_ARGS_INVOKE)
/*Log an edge after changing its topological connections*/
void _BM_log_edge_topo_post(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS);
#define BM_log_edge_topo_post(log, e) _BM_log_edge_topo_post(log, e BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_edge_post(BMLog *log, BMEdge *e BMLOG_DEBUG_ARGS);
#define BM_log_edge_post(log, e) _BM_log_edge_post(log, e BMLOG_DEBUG_ARGS_INVOKE)
/*Log a face before changing its topological connections*/
void _BM_log_face_topo_pre(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS);
#define BM_log_face_topo_pre(log, f) _BM_log_face_topo_pre(log, f BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_face_pre(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS);
#define BM_log_face_pre(log, f) _BM_log_face_pre(log, f BMLOG_DEBUG_ARGS_INVOKE)
/*Log a face after changing its topological connections*/
void _BM_log_face_topo_post(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS);
#define BM_log_face_topo_post(log, f) _BM_log_face_topo_post(log, f BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_face_post(BMLog *log, BMFace *f BMLOG_DEBUG_ARGS);
#define BM_log_face_post(log, f) _BM_log_face_post(log, f BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_vert_topo_pre(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS);
#define BM_log_vert_topo_pre(log, v) _BM_log_vert_topo_pre(log, v BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_vert_pre(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS);
#define BM_log_vert_pre(log, v) _BM_log_vert_pre(log, v BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_vert_topo_post(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS);
#define BM_log_vert_topo_post(log, v) _BM_log_vert_topo_post(log, v BMLOG_DEBUG_ARGS_INVOKE)
void _BM_log_vert_post(BMLog *log, BMVert *v BMLOG_DEBUG_ARGS);
#define BM_log_vert_post(log, v) _BM_log_vert_post(log, v BMLOG_DEBUG_ARGS_INVOKE)
bool BM_log_validate(BMesh *inbm, BMLogEntry *entry, bool is_applied);
bool BM_log_validate_cur(BMLog *log);
#ifdef __cplusplus
}
#endif

View File

@ -442,7 +442,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm,
/**
* Collapse and edge into a single vertex.
*/
BMVert *BM_edge_collapse(BMesh *bm,
ATTR_NO_OPT BMVert *BM_edge_collapse(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
const bool do_del,

View File

@ -1439,10 +1439,10 @@ void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup,
drw_sculpt_generate_calls(&scd);
}
void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups,
GPUMaterial **gpumats,
int num_shgroups,
Object *ob)
ATTR_NO_OPT void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups,
GPUMaterial **gpumats,
int num_shgroups,
Object *ob)
{
DRW_Attributes draw_attrs;
DRW_MeshCDMask cd_needed;

View File

@ -1003,6 +1003,37 @@ struct PBVHBatches {
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = face_set_color;
});
}
break;
}
case CD_PROP_INT32: {
const int cd_prop = CustomData_get_offset_named(cdata, CD_PROP_INT32, vbo.name.c_str());
foreach_bmesh([&](BMLoop *l) {
BMElem *elem;
switch (vbo.domain) {
case ATTR_DOMAIN_POINT:
elem = reinterpret_cast<BMElem *>(l->v);
break;
case ATTR_DOMAIN_EDGE:
elem = reinterpret_cast<BMElem *>(l->e);
break;
case ATTR_DOMAIN_CORNER:
elem = reinterpret_cast<BMElem *>(l);
break;
case ATTR_DOMAIN_FACE:
elem = reinterpret_cast<BMElem *>(l->f);
break;
default:
return;
}
int val = BM_ELEM_CD_GET_INT(elem, cd_prop);
*static_cast<int *>(GPU_vertbuf_raw_step(&access)) = val;
});
break;
}
}
}
@ -1022,7 +1053,10 @@ struct PBVHBatches {
}
}
void create_vbo(eAttrDomain domain, const uint32_t type, string name, PBVH_GPU_Args *args)
ATTR_NO_OPT void create_vbo(eAttrDomain domain,
const uint32_t type,
string name,
PBVH_GPU_Args *args)
{
PBVHVbo vbo(domain, type, name);
GPUVertFormat format;
@ -1061,6 +1095,16 @@ struct PBVHBatches {
GPU_vertformat_attr_add(&format, "f", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
need_aliases = true;
break;
case CD_PROP_INT32: {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
GPU_vertformat_safe_attr_name(name.c_str(), attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
/* Attributes use auto-name. */
BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_I32, 1, GPU_FETCH_INT_TO_FLOAT);
need_aliases = true;
break;
}
case CD_PROP_COLOR:
case CD_PROP_BYTE_COLOR: {
GPU_vertformat_attr_add(&format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
@ -1117,6 +1161,9 @@ struct PBVHBatches {
case CD_MLOOPUV:
prefix = "u";
break;
case CD_PROP_INT32:
prefix = "a";
break;
default:
break;
}
@ -1425,7 +1472,7 @@ struct PBVHBatches {
}
}
void create_batch(PBVHAttrReq *attrs, int attrs_num, PBVH_GPU_Args *args)
ATTR_NO_OPT void create_batch(PBVHAttrReq *attrs, int attrs_num, PBVH_GPU_Args *args)
{
check_index_buffers(args);

View File

@ -1457,6 +1457,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
sgcontext->ss->bm,
sgcontext->ss->bm_smooth_shading,
sgcontext->ss->bm_log,
sgcontext->ss->bm_idmap,
sgcontext->ss->cd_vert_node_offset,
sgcontext->ss->cd_face_node_offset,
sgcontext->ss->cd_sculpt_vert,
@ -1472,7 +1473,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
}),
sculpt_mesh);
BM_mesh_free(bm);
BKE_mesh_normals_tag_dirty(result);
BKE_mesh_nomain_to_mesh(result, sgcontext->vc.obact->data, sgcontext->vc.obact);
}

View File

@ -53,6 +53,7 @@
#include "bmesh.h"
#include "bmesh_log.h"
#include "bmesh_tools.h"
#include "../../bmesh/intern/bmesh_idmap.h"
#include <math.h>
#include <stdlib.h>
@ -567,7 +568,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
/* Also check bm_log. */
if (!ss->bm_log) {
ss->bm_log = BM_log_create(ss->bm, ss->cd_sculpt_vert);
ss->bm_log = BM_log_create(ss->bm, ss->bm_idmap, ss->cd_sculpt_vert);
}
return;
@ -676,9 +677,14 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
/* Enable dynamic topology. */
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
if (!ss->bm_idmap) {
ss->bm_idmap = BM_idmap_new(ss->bm, BM_VERT|BM_EDGE|BM_FACE);
BKE_sculptsession_update_attr_refs(ob);
}
/* Enable logging for undo/redo. */
if (!ss->bm_log) {
ss->bm_log = BM_log_create(ss->bm, ss->cd_sculpt_vert);
ss->bm_log = BM_log_create(ss->bm, ss->bm_idmap, ss->cd_sculpt_vert);
}
/* Update dependency graph, so modifiers that depend on dyntopo being enabled
@ -715,6 +721,11 @@ static void SCULPT_dynamic_topology_disable_ex(
/* Clear data. */
me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
if (ss->bm_idmap) {
BM_idmap_destroy(ss->bm_idmap);
ss->bm_idmap = NULL;
}
if (ss->bm_log) {
BM_log_free(ss->bm_log, true);
ss->bm_log = NULL;

View File

@ -84,6 +84,8 @@
#include "bmesh_log.h"
#include "bmesh_tools.h"
#include "../../bmesh/intern/bmesh_idmap.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
@ -508,11 +510,21 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
ob->sculpt->bm_log = NULL;
}
if (ob->sculpt->bm_idmap) {
BM_idmap_destroy(ob->sculpt->bm_idmap);
ob->sculpt->bm_idmap = NULL;
}
/* Recreate idmap and log. */
BKE_sculpt_ensure_idmap(ob);
/* See if we can rebuild the log from the undo stack. */
SCULPT_undo_ensure_bmlog(ob);
// SCULPT_undo_ensure_bmlog failed to find a sculpt undo step
/* Create an empty log if reconstruction failed. */
if (!ob->sculpt->bm_log) {
ob->sculpt->bm_log = BM_log_create(ob->sculpt->bm, ob->sculpt->cd_sculpt_vert);
ob->sculpt->bm_log = BM_log_create(ob->sculpt->bm, ob->sculpt->bm_idmap, ob->sculpt->cd_sculpt_vert);
}
}
}

View File

@ -909,7 +909,7 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode, bool is_
if (!ss->bm_log) {
/* Restore the BMLog using saved entries. */
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, ss->bm_idmap, unode->bm_entry);
BMLogEntry *entry = is_redo ? BM_log_entry_prev(unode->bm_entry) : unode->bm_entry;
BM_log_set_current_entry(ss->bm_log, entry);
@ -1118,7 +1118,7 @@ static int sculpt_undo_bmesh_restore(
#ifdef WHEN_GLOBAL_UNDO_WORKS
if (!ss->bm_log && ss->bm && unode->bm_entry) { // && BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, ss->bm_idmap, unode->bm_entry);
}
#endif
@ -2013,14 +2013,16 @@ void SCULPT_undo_ensure_bmlog(Object *ob)
SculptUndoNode *unode = usculpt->nodes.first;
BKE_sculpt_ensure_idmap(ob);
/*when transition between undo step types the log might simply
have been freed, look for entries to rebuild it with*/
if (!ss->bm_log) {
if (unode && unode->bm_entry) {
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, ss->bm_idmap, unode->bm_entry);
}
else {
ss->bm_log = BM_log_create(ss->bm, ss->cd_sculpt_vert);
ss->bm_log = BM_log_create(ss->bm, ss->bm_idmap, ss->cd_sculpt_vert);
}
if (ss->pbvh) {
@ -2040,7 +2042,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
SCULPT_undo_ensure_bmlog(ob);
if (!ss->bm_log) {
ss->bm_log = BM_log_create(ss->bm, ss->cd_sculpt_vert);
ss->bm_log = BM_log_create(ss->bm, ss->bm_idmap, ss->cd_sculpt_vert);
}
bool new_node = false;
@ -2465,7 +2467,10 @@ static void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_firs
if (ss && ss->bm && ss->bm_log && BM_log_is_dead(ss->bm_log)) {
// forcibly destroy all entries? the 'true' parameter
BM_log_free(ss->bm_log, true);
ss->bm_log = BM_log_create(ss->bm, ss->cd_sculpt_vert);
BKE_sculpt_ensure_idmap(ob);
ss->bm_log = BM_log_create(ss->bm, ss->bm_idmap, ss->cd_sculpt_vert);
if (ss->pbvh) {
BKE_pbvh_set_bm_log(ss->pbvh, ss->bm_log);
@ -3105,7 +3110,7 @@ void SCULPT_substep_undo(bContext *C, int dir)
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
}
void BM_log_get_changed(BMesh *bm, BMLogEntry *_entry, SmallHash *sh);
void BM_log_get_changed(BMesh *bm, struct BMIdMap *idmap, BMLogEntry *_entry, SmallHash *sh);
void ED_sculpt_fast_save_bmesh(Object *ob)
{
@ -3153,7 +3158,7 @@ void ED_sculpt_fast_save_bmesh(Object *ob)
LISTBASE_FOREACH (SculptUndoNode *, unode, &usculpt->data.nodes) {
if (unode->bm_entry) {
BM_log_get_changed(bm, unode->bm_entry, &elems);
BM_log_get_changed(bm, ss->bm_idmap, unode->bm_entry, &elems);
}
}