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:
parent
e53a8f9c51
commit
bb764e418a
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
} \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue