Sculpt dyntopo: BMLog now uses the new bmesh unique id system

A few notes:

* MESH_ID layers are not saved on conversion to Mesh unless
  you ask for it in BM_mesh_bm_to_me's params.
* Still need to test the box/lasso trim tools.
* Need to find some way to test loop/edge ids, which aren't
  used by dyntopo.
This commit is contained in:
Joseph Eagar 2021-06-26 21:26:33 -07:00
parent 27986e9b56
commit 7562ad5777
9 changed files with 115 additions and 279 deletions

View File

@ -4319,12 +4319,12 @@ void CustomData_bmesh_interp_n(CustomData *data,
typeInfo->interp(src_blocks_ofs, weights, sub_weights, count, dst_block_ofs);
}
ATTR_NO_OPT void CustomData_bmesh_interp(CustomData *data,
const void **src_blocks,
const float *weights,
const float *sub_weights,
int count,
void *dst_block)
void CustomData_bmesh_interp(CustomData *data,
const void **src_blocks,
const float *weights,
const float *sub_weights,
int count,
void *dst_block)
{
if (count <= 0) {
return;

View File

@ -40,7 +40,7 @@
#define SELECT 1
void bm_assign_id(BMesh *bm, BMElem *elem, uint id)
static void bm_assign_id_intern(BMesh *bm, BMElem *elem, uint id)
{
BM_ELEM_CD_SET_INT(elem, bm->idmap.cd_id_off[elem->head.htype], id);
@ -65,6 +65,12 @@ void bm_assign_id(BMesh *bm, BMElem *elem, uint id)
}
}
void bm_assign_id(BMesh *bm, BMElem *elem, uint id)
{
range_tree_uint_retake(bm->idmap.idtree, id);
bm_assign_id_intern(bm, elem, id);
}
void bm_alloc_id(BMesh *bm, BMElem *elem)
{
if ((bm->idmap.flag & (elem->head.htype | BM_HAS_IDS)) != (elem->head.htype | BM_HAS_IDS)) {
@ -72,7 +78,7 @@ void bm_alloc_id(BMesh *bm, BMElem *elem)
}
uint id = range_tree_uint_take_any(bm->idmap.idtree);
bm_assign_id(bm, elem, id);
bm_assign_id_intern(bm, elem, id);
}
void bm_free_id(BMesh *bm, BMElem *elem)

View File

@ -1336,10 +1336,7 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
}
}
ATTR_NO_OPT void BM_data_layers_ensure(BMesh *bm,
CustomData *data,
BMCustomLayerReq *layers,
int totlayer)
void BM_data_layers_ensure(BMesh *bm, CustomData *data, BMCustomLayerReq *layers, int totlayer)
{
bool modified = false;
CustomData old = *data;

View File

@ -47,12 +47,12 @@
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BLI_strict_flags.h"
#include "bmesh.h"
#include "bmesh_log.h"
#include "bmesh_private.h"
#include "range_tree.h"
#include "BLI_strict_flags.h"
#define CUSTOMDATA
struct Mesh;
@ -95,13 +95,9 @@ struct BMLogEntry {
bool fully_copy; // has full copy
struct Mesh
*full_copy_mesh; // avoid excessive memory use by saving a Mesh instead of copying the bmesh
GHash *full_copy_idmap; // maps ids to indices (with the elem-type in the high order bits)
};
struct BMLog {
/* Tree of free IDs */
struct RangeTreeUInt *unused_ids;
BMLogEntry *frozen_full_mesh;
int refcount;
@ -115,8 +111,6 @@ struct BMLog {
* The ID is needed because element pointers will change as they
* are created and deleted.
*/
GHash *id_to_elem;
GHash *elem_to_id;
ThreadRWMutex lock;
@ -149,6 +143,7 @@ typedef struct {
typedef struct {
uint v_ids[3];
uint l_ids[3];
float no[3];
void *customdata[3];
void *customdata_f;
@ -233,32 +228,19 @@ static bool log_ghash_ensure_p(BMLog *log, GHash *gh, void *key, void ***val)
/* Get the vertex's unique ID from the log */
static uint bm_log_vert_id_get(BMLog *log, BMVert *v)
{
BLI_assert(log_ghash_haskey(log, log->elem_to_id, v));
return POINTER_AS_UINT(log_ghash_lookup(log, log->elem_to_id, v));
}
/* Set the vertex's unique ID in the log */
static void bm_log_vert_id_set(BMLog *log, BMVert *v, uint id)
{
void *vid = POINTER_FROM_UINT(id);
log_ghash_reinsert(log, log->id_to_elem, vid, v, NULL, NULL);
log_ghash_reinsert(log, log->elem_to_id, v, vid, NULL, NULL);
return (uint)BM_ELEM_GET_ID(log->bm, v);
}
/* Get a vertex from its unique ID */
static BMVert *bm_log_vert_from_id(BMLog *log, uint id)
{
void *key = POINTER_FROM_UINT(id);
BLI_assert(log_ghash_haskey(log, log->id_to_elem, key));
return log_ghash_lookup(log, log->id_to_elem, key);
return (BMVert *)log->bm->idmap.map[id];
}
/* Get the face's unique ID from the log */
static uint bm_log_face_id_get(BMLog *log, BMFace *f)
{
BLI_assert(log_ghash_haskey(log, log->elem_to_id, f));
return POINTER_AS_UINT(log_ghash_lookup(log, log->elem_to_id, f));
return (uint)BM_ELEM_GET_ID(log->bm, f);
}
uint BM_log_vert_id_get(BMLog *log, BMVert *v)
@ -268,7 +250,7 @@ uint BM_log_vert_id_get(BMLog *log, BMVert *v)
BMVert *BM_log_id_vert_get(BMLog *log, uint id)
{
return log_ghash_lookup(log, log->id_to_elem, POINTER_FROM_UINT(id));
return (BMVert *)log->bm->idmap.map[id];
}
uint BM_log_face_id_get(BMLog *log, BMFace *f)
@ -278,24 +260,13 @@ uint BM_log_face_id_get(BMLog *log, BMFace *f)
BMFace *BM_log_id_face_get(BMLog *log, uint id)
{
return log_ghash_lookup(log, log->id_to_elem, POINTER_FROM_UINT(id));
}
/* Set the face's unique ID in the log */
static void bm_log_face_id_set(BMLog *log, BMFace *f, uint id)
{
void *fid = POINTER_FROM_UINT(id);
log_ghash_reinsert(log, log->id_to_elem, fid, f, NULL, NULL);
log_ghash_reinsert(log, log->elem_to_id, f, fid, NULL, NULL);
return (BMFace *)log->bm->idmap.map[id];
}
/* Get a face from its unique ID */
static BMFace *bm_log_face_from_id(BMLog *log, uint id)
{
void *key = POINTER_FROM_UINT(id);
BLI_assert(log_ghash_haskey(log, log->id_to_elem, key));
return log_ghash_lookup(log, log->id_to_elem, key);
return (BMFace *)log->bm->idmap.map[id];
}
/************************ BMLogVert / BMLogFace ***********************/
@ -419,6 +390,15 @@ static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
copy_v3_v3(lf->no, f->no);
if (log->bm->idmap.flag & BM_LOOP) {
lf->l_ids[0] = (uint)BM_ELEM_GET_ID(log->bm, f->l_first);
lf->l_ids[1] = (uint)BM_ELEM_GET_ID(log->bm, f->l_first->next);
lf->l_ids[2] = (uint)BM_ELEM_GET_ID(log->bm, f->l_first->prev);
}
else {
lf->l_ids[0] = lf->l_ids[1] = lf->l_ids[2] = (uint)-1;
}
lf->v_ids[0] = bm_log_vert_id_get(log, v[0]);
lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);
lf->v_ids[2] = bm_log_vert_id_get(log, v[2]);
@ -517,11 +497,10 @@ static void bm_log_verts_restore(
GHASH_ITER (gh_iter, verts) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP);
BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_SKIP_ID);
vert_mask_set(v, lv->mask, cd_vert_mask_offset);
v->head.hflag = lv->hflag;
normal_short_to_float_v3(v->no, lv->no);
bm_log_vert_id_set(log, v, POINTER_AS_UINT(key));
#ifdef CUSTOMDATA
if (lv->customdata) {
@ -529,6 +508,8 @@ static void bm_log_verts_restore(
}
#endif
bm_assign_id(bm, (BMElem *)v, POINTER_AS_UINT(key));
if (callbacks) {
callbacks->on_vert_add(v, callbacks->userdata);
}
@ -549,11 +530,11 @@ static void bm_log_faces_restore(
};
BMFace *f;
f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_NOP, true);
f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_SKIP_ID, true);
f->head.hflag = lf->hflag;
copy_v3_v3(f->no, lf->no);
bm_log_face_id_set(log, f, POINTER_AS_UINT(key));
bm_assign_id(bm, (BMElem *)f, POINTER_AS_UINT(key));
#ifdef CUSTOMDATA
if (lf->customdata_f) {
@ -563,6 +544,10 @@ static void bm_log_faces_restore(
BMLoop *ls[3] = {f->l_first, f->l_first->next, f->l_first->prev};
for (int i = 0; i < 3; i++) {
if (lf->l_ids[i] != (uint)-1) {
bm_assign_id(bm, (BMElem *)ls[i], lf->l_ids[i]);
}
if (lf->customdata[i]) {
CustomData_bmesh_copy_data(
&entry->ldata, &bm->ldata, lf->customdata[i], &ls[i]->head.data);
@ -674,53 +659,12 @@ static void bm_log_face_values_swap(BMLog *log,
/**********************************************************************/
/* Assign unique IDs to all vertices and faces already in the BMesh */
static void bm_log_assign_ids(BMesh *bm, BMLog *log)
{
BMIter iter;
BMVert *v;
BMFace *f;
/* Generate vertex IDs */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
uint id = range_tree_uint_take_any(log->unused_ids);
bm_log_vert_id_set(log, v, id);
}
/* Generate face IDs */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
uint id = range_tree_uint_take_any(log->unused_ids);
bm_log_face_id_set(log, f, id);
}
}
static void bm_log_full_mesh_intern(BMesh *bm, BMLog *log, BMLogEntry *entry)
{
CustomData_MeshMasks cd_mask_extra = {CD_MASK_DYNTOPO_VERT, 0, 0, 0, 0};
entry->full_copy_idmap = BLI_ghash_ptr_new_ex("bmlog",
(unsigned int)(bm->totvert + bm->totface));
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE | BM_FACE);
for (int step = 0; step < 2; step++) {
BMIter iter;
BMHeader *elem;
BM_ITER_MESH (elem, &iter, bm, step ? BM_FACES_OF_MESH : BM_VERTS_OF_MESH) {
void **val = log_ghash_lookup_p(log, log->elem_to_id, (void *)elem);
if (!val) {
continue;
}
uint id = POINTER_AS_UINT(*val);
uintptr_t key = (size_t)elem->index;
key |= ((uintptr_t)elem->htype) << 31L;
BLI_ghash_insert(entry->full_copy_idmap, POINTER_FROM_UINT(id), (void *)key);
}
}
entry->full_copy_mesh = BKE_mesh_from_bmesh_nomain(
bm,
(&(struct BMeshToMeshParams){.update_shapekey_indices = false,
@ -770,10 +714,6 @@ static void bm_log_entry_free(BMLogEntry *entry)
if (entry->full_copy_mesh) {
BKE_mesh_free(entry->full_copy_mesh);
if (entry->full_copy_idmap) {
BLI_ghash_free(entry->full_copy_idmap, NULL, NULL);
}
}
BLI_ghash_free(entry->deleted_verts, NULL, NULL);
@ -809,18 +749,6 @@ static void bm_log_entry_free(BMLogEntry *entry)
}
}
static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
{
GHashIterator gh_iter;
GHASH_ITER (gh_iter, id_ghash) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
uint id = POINTER_AS_UINT(key);
range_tree_uint_retake(unused_ids, id);
}
}
static int uint_compare(const void *a_v, const void *b_v)
{
const uint *a = a_v;
@ -852,18 +780,6 @@ static GHash *bm_log_compress_ids_to_indices(uint *ids, uint totid)
return map;
}
/* Release all ID keys in id_ghash */
static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
{
GHashIterator gh_iter;
GHASH_ITER (gh_iter, id_ghash) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
uint id = POINTER_AS_UINT(key);
range_tree_uint_release(log->unused_ids, id);
}
}
/***************************** Public API *****************************/
void BM_log_set_cd_offsets(BMLog *log, int cd_dyn_vert)
@ -884,15 +800,8 @@ BMLog *BM_log_create(BMesh *bm, int cd_dyn_vert)
BLI_rw_mutex_init(&log->lock);
log->unused_ids = range_tree_uint_alloc(0, (uint)-1);
log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num);
BM_log_set_cd_offsets(log, cd_dyn_vert);
/* Assign IDs to all existing vertices and faces */
bm_log_assign_ids(bm, log);
return log;
}
@ -901,14 +810,6 @@ void BM_log_cleanup_entry(BMLogEntry *entry)
BMLog *log = entry->log;
if (log) {
/* Take all used IDs */
bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces);
/* delete entries to avoid releasing ids in node cleanup */
BLI_ghash_clear(entry->deleted_verts, NULL, NULL);
BLI_ghash_clear(entry->deleted_faces, NULL, NULL);
@ -947,14 +848,6 @@ BMLog *bm_log_from_existing_entries_create(BMesh *bm,
for (entry = log->entries.first; entry; entry = entry->next) {
entry->log = log;
/* Take all used IDs */
bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces);
}
return log;
@ -1028,18 +921,6 @@ static bool bm_log_free_direct(BMLog *log, bool safe_mode)
BLI_rw_mutex_end(&log->lock);
if (log->unused_ids) {
range_tree_uint_free(log->unused_ids);
}
if (log->id_to_elem) {
BLI_ghash_free(log->id_to_elem, NULL, NULL);
}
if (log->elem_to_id) {
BLI_ghash_free(log->elem_to_id, NULL, NULL);
}
/* Clear the BMLog references within each entry, but do not free
* the entries themselves */
for (entry = log->entries.first; entry; entry = entry->next) {
@ -1285,8 +1166,6 @@ void BM_log_entry_drop(BMLogEntry *entry)
* the entry is at the end of the undo stack, and it's being
* deleted, those elements can never be restored. Their IDs
* can go back into the pool. */
bm_log_id_ghash_release(log, entry->added_faces);
bm_log_id_ghash_release(log, entry->added_verts);
}
else {
BLI_assert(!"Cannot drop BMLogEntry from middle");
@ -1322,37 +1201,6 @@ static void full_copy_load(BMesh *bm, BMLog *log, BMLogEntry *entry)
BM_mesh_elem_table_ensure(bm, BM_VERT | BM_FACE);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
// restores ids
GHashIterator gi;
GHASH_ITER (gi, entry->full_copy_idmap) {
// uint id = POINTER_AS_UINT(BLI_ghashIterator_getKey(&gi));
uintptr_t id = (uintptr_t)BLI_ghashIterator_getKey(&gi);
uintptr_t key = (uintptr_t)BLI_ghashIterator_getValue(&gi);
uintptr_t idx = (key & ((1LL << 31LL) - 1LL));
uintptr_t type = key >> 31LL;
BMHeader *elem = NULL;
switch (type) {
case BM_VERT:
elem = &bm->vtable[idx]->head;
break;
case BM_FACE:
elem = &bm->ftable[idx]->head;
break;
}
if (elem) {
log_ghash_reinsert(log, log->id_to_elem, POINTER_FROM_UINT(id), elem, NULL, NULL);
log_ghash_reinsert(log, log->elem_to_id, elem, POINTER_FROM_UINT(id), NULL, NULL);
}
else {
// eek, error!
printf("bmlog error!\n");
log_ghash_remove(log, log->id_to_elem, (void *)id, NULL, NULL);
}
}
bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
bm->elem_table_dirty |= BM_VERT | BM_EDGE | BM_FACE;
}
@ -1375,48 +1223,17 @@ static void full_copy_swap(BMesh *bm, BMLog *log, BMLogEntry *entry)
.active_shapekey = -1,
.cd_mask_extra = cd_mask_extra,
.copy_temp_cdlayers = true}));
.copy_temp_cdlayers = true,
.copy_id_layers = true}));
bm->elem_index_dirty |= BM_VERT | BM_FACE;
bm->elem_table_dirty |= BM_VERT | BM_FACE;
BM_mesh_elem_table_ensure(bm, BM_VERT | BM_FACE);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
// restores ids
GHashIterator gi;
GHASH_ITER (gi, entry->full_copy_idmap) {
// uint id = POINTER_AS_UINT(BLI_ghashIterator_getKey(&gi));
uintptr_t id = (uintptr_t)BLI_ghashIterator_getKey(&gi);
uintptr_t key = (uintptr_t)BLI_ghashIterator_getValue(&gi);
uintptr_t idx = (key & ((1LL << 31LL) - 1LL));
uintptr_t type = key >> 31LL;
BMHeader *elem = NULL;
switch (type) {
case BM_VERT:
elem = &bm->vtable[idx]->head;
break;
case BM_FACE:
elem = &bm->ftable[idx]->head;
break;
}
if (elem) {
log_ghash_reinsert(log, log->id_to_elem, POINTER_FROM_UINT(id), elem, NULL, NULL);
log_ghash_reinsert(log, log->elem_to_id, elem, POINTER_FROM_UINT(id), NULL, NULL);
}
else {
// eek, error!
printf("bmlog error!\n");
log_ghash_remove(log, log->id_to_elem, (void *)id, NULL, NULL);
}
}
BKE_mesh_free(entry->full_copy_mesh);
BLI_ghash_free(entry->full_copy_idmap, NULL, NULL);
entry->full_copy_idmap = tmp.full_copy_idmap;
entry->full_copy_mesh = tmp.full_copy_mesh;
bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
@ -1567,7 +1384,7 @@ void BM_log_vert_before_modified(BMLog *log,
{
BMLogEntry *entry = log->current_entry;
BMLogVert *lv;
uint v_id = bm_log_vert_id_get(log, v);
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
void *key = POINTER_FROM_UINT(v_id);
void **val_p;
@ -1590,10 +1407,9 @@ void BM_log_vert_before_modified(BMLog *log,
void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
BMLogVert *lv;
uint v_id = range_tree_uint_take_any(log->unused_ids);
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
void *key = POINTER_FROM_UINT(v_id);
bm_log_vert_id_set(log, v, v_id);
lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset, true);
log_ghash_insert(log, log->current_entry->added_verts, key, lv);
}
@ -1605,7 +1421,7 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
void BM_log_face_modified(BMLog *log, BMFace *f)
{
BMLogFace *lf;
uint f_id = bm_log_face_id_get(log, f);
uint f_id = (uint)BM_ELEM_GET_ID(log->bm, f);
void *key = POINTER_FROM_UINT(f_id);
lf = bm_log_face_alloc(log, f);
@ -1623,14 +1439,12 @@ void BM_log_face_modified(BMLog *log, BMFace *f)
void BM_log_face_added(BMLog *log, BMFace *f)
{
BMLogFace *lf;
uint f_id = range_tree_uint_take_any(log->unused_ids);
uint f_id = (uint)BM_ELEM_GET_ID(log->bm, f);
void *key = POINTER_FROM_UINT(f_id);
/* Only triangles are supported for now */
BLI_assert(f->len == 3);
bm_log_face_id_set(log, f, f_id);
lf = bm_log_face_alloc(log, f);
log_ghash_insert(log, log->current_entry->added_faces, key, lf);
@ -1656,17 +1470,14 @@ void BM_log_face_added(BMLog *log, BMFace *f)
void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
BMLogEntry *entry = log->current_entry;
uint v_id = bm_log_vert_id_get(log, v);
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
void *key = POINTER_FROM_UINT(v_id);
/* if it has a key, it shouldn't be NULL */
BLI_assert(!!log_ghash_lookup(log, entry->added_verts, key) ==
!!log_ghash_haskey(log, entry->added_verts, key));
if (log_ghash_remove(log, entry->added_verts, key, NULL, NULL)) {
range_tree_uint_release(log->unused_ids, v_id);
}
else {
if (!log_ghash_remove(log, entry->added_verts, key, NULL, NULL)) {
BMLogVert *lv, *lv_mod;
lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset, false);
@ -1689,8 +1500,6 @@ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
bm_log_vert_customdata(log->bm, log, entry, v, lv);
}
}
log_ghash_remove(log, log->id_to_elem, key, NULL, NULL);
}
/* Log a face as removed from the BMesh
@ -1709,17 +1518,14 @@ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
void BM_log_face_removed(BMLog *log, BMFace *f)
{
BMLogEntry *entry = log->current_entry;
uint f_id = bm_log_face_id_get(log, f);
uint f_id = (uint)BM_ELEM_GET_ID(log->bm, f);
void *key = POINTER_FROM_UINT(f_id);
/* if it has a key, it shouldn't be NULL */
BLI_assert(!!log_ghash_lookup(log, entry->added_faces, key) ==
!!log_ghash_haskey(log, entry->added_faces, key));
if (log_ghash_remove(log, entry->added_faces, key, NULL, NULL)) {
range_tree_uint_release(log->unused_ids, f_id);
}
else {
if (!log_ghash_remove(log, entry->added_faces, key, NULL, NULL)) {
BMLogFace *lf;
lf = bm_log_face_alloc(log, f);
@ -1729,8 +1535,6 @@ void BM_log_face_removed(BMLog *log, BMFace *f)
bm_log_face_customdata(log->bm, log, f, lf);
}
}
log_ghash_remove(log, log->id_to_elem, key, NULL, NULL);
}
/* Log all vertices/faces in the BMesh as added */
@ -1821,7 +1625,7 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
uint v_id = bm_log_vert_id_get(log, v);
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
@ -1839,7 +1643,7 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
uint v_id = bm_log_vert_id_get(log, v);
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
@ -1857,7 +1661,7 @@ float BM_log_original_mask(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
uint v_id = bm_log_vert_id_get(log, v);
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
@ -1872,7 +1676,7 @@ void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
uint v_id = bm_log_vert_id_get(log, v);
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
@ -1892,12 +1696,6 @@ BMLogEntry *BM_log_current_entry(BMLog *log)
return log->current_entry;
}
/* For internal use only (unit testing) */
RangeTreeUInt *BM_log_unused_ids(BMLog *log)
{
return log->unused_ids;
}
#if 0
/* Print the list of entries, marking the current one
*

View File

@ -123,7 +123,6 @@ void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const
/* For internal use only (unit testing) */
BMLogEntry *BM_log_current_entry(BMLog *log);
struct RangeTreeUInt *BM_log_unused_ids(BMLog *log);
uint BM_log_vert_id_get(BMLog *log, BMVert *v);
BMVert *BM_log_id_vert_get(BMLog *log, uint id);

View File

@ -299,6 +299,7 @@ void BM_mesh_data_free(BMesh *bm)
void BM_mesh_clear(BMesh *bm)
{
const bool use_toolflags = bm->use_toolflags;
const int idmap_flags = bm->idmap.flag;
/* free old mesh */
BM_mesh_data_free(bm);
@ -316,7 +317,10 @@ void BM_mesh_clear(BMesh *bm)
CustomData_reset(&bm->ldata);
CustomData_reset(&bm->pdata);
bm->idmap.flag = idmap_flags;
if (bm->idmap.flag & BM_HAS_IDS) {
bm->idmap.idtree = range_tree_uint_alloc(0, (uint)-1);
bm_init_idmap_cdlayers(bm);
}
}

View File

@ -227,10 +227,10 @@ void BM_enter_multires_space(Object *ob, BMesh *bm, int space)
*
* \warning This function doesn't calculate face normals.
*/
ATTR_NO_OPT void BM_mesh_bm_from_me(Object *ob,
BMesh *bm,
const Mesh *me,
const struct BMeshFromMeshParams *params)
void BM_mesh_bm_from_me(Object *ob,
BMesh *bm,
const Mesh *me,
const struct BMeshFromMeshParams *params)
{
const bool is_new = !(bm->totvert || (bm->vdata.totlayer || bm->edata.totlayer ||
bm->pdata.totlayer || bm->ldata.totlayer));
@ -783,7 +783,7 @@ void BM_mesh_bm_to_me(
{
CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
int extra2 = params->copy_mesh_id_layers ? CD_MESH_ID : 0;
CustomDataMask extra2 = params->copy_mesh_id_layers ? CD_MASK_MESH_ID : 0;
// clear mesh id layer flags
if (params->copy_mesh_id_layers) {
@ -802,20 +802,6 @@ void BM_mesh_bm_to_me(
CustomData_copy(&bm->edata, &me->edata, mask.emask | extra2, CD_CALLOC, me->totedge);
CustomData_copy(&bm->ldata, &me->ldata, mask.lmask | extra2, CD_CALLOC, me->totloop);
CustomData_copy(&bm->pdata, &me->pdata, mask.pmask | extra2, CD_CALLOC, me->totpoly);
// restore mesh id layer flags in bm
if (params->copy_mesh_id_layers) {
CustomData *srcdatas[] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
CustomData *dstdatas[] = {&me->vdata, &me->edata, &me->ldata, &me->pdata};
for (int i = 0; i < 4; i++) {
int idx = CustomData_get_layer_index(srcdatas[i], CD_MESH_ID);
if (idx >= 0) {
srcdatas[i]->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_ELEM_NOCOPY;
}
}
}
}
MVert *mvert = bm->totvert ? MEM_callocN(sizeof(MVert) * bm->totvert, "bm_to_me.vert") : NULL;
@ -1179,6 +1165,20 @@ void BM_mesh_bm_to_me(
/* To be removed as soon as COW is enabled by default. */
BKE_mesh_runtime_clear_geometry(me);
if (params->copy_mesh_id_layers) {
// restore mesh id layer flags in bm
CustomData *srcdatas[] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
CustomData *dstdatas[] = {&me->vdata, &me->edata, &me->ldata, &me->pdata};
for (int i = 0; i < 4; i++) {
int idx = CustomData_get_layer_index(srcdatas[i], CD_MESH_ID);
if (idx >= 0) {
srcdatas[i]->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_ELEM_NOCOPY;
}
}
}
if (params && params->copy_temp_cdlayers) {
bm_mark_temp_cdlayers(bm);
}

View File

@ -257,6 +257,9 @@ void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss)
BKE_pbvh_update_offsets(
ss->pbvh, ss->cd_vert_node_offset, ss->cd_face_node_offset, ss->cd_dyn_vert);
}
if (ss->bm_log) {
BM_log_set_cd_offsets(ss->bm_log, ss->cd_dyn_vert);
}
}
bool SCULPT_dyntopo_has_templayer(SculptSession *ss, int type, const char *name)
@ -732,6 +735,8 @@ void sculpt_dynamic_topology_disable_with_undo(Main *bmain,
if (use_undo) {
SCULPT_undo_push_end();
}
ss->active_vertex_index.i = ss->active_face_index.i = 0;
}
}
@ -741,6 +746,7 @@ static void sculpt_dynamic_topology_enable_with_undo(Main *bmain,
Object *ob)
{
SculptSession *ss = ob->sculpt;
if (ss->bm == NULL) {
/* May be false in background mode. */
const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true;
@ -752,6 +758,8 @@ static void sculpt_dynamic_topology_enable_with_undo(Main *bmain,
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
SCULPT_undo_push_end();
}
ss->active_vertex_index.i = ss->active_face_index.i = 0;
}
}

View File

@ -562,6 +562,8 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
MEM_freeN(nodes);
}
SCULPT_dyntopo_node_layers_update_offsets(ss);
if (data.balance_pbvh) {
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
}
@ -625,6 +627,7 @@ static void sculpt_undo_bmesh_restore_end(bContext *C,
Object *ob,
SculptSession *ss)
{
if (unode->applied) {
sculpt_undo_bmesh_enable(ob, unode);
@ -733,11 +736,12 @@ static int sculpt_undo_bmesh_restore(bContext *C,
Object *ob,
SculptSession *ss)
{
if (ss->bm_log && ss->bm) {
if (ss->bm_log && ss->bm &&
!ELEM(unode->type, SCULPT_UNDO_DYNTOPO_BEGIN, SCULPT_UNDO_DYNTOPO_END)) {
SCULPT_dyntopo_node_layers_update_offsets(ss);
BM_log_set_cd_offsets(ss->bm_log, ss->cd_dyn_vert);
if (ss->active_face_index.i) {
if (ss->active_face_index.i && ss->active_face_index.i != -1LL) {
ss->active_face_index.i = (intptr_t)BM_log_face_id_get(ss->bm_log,
(BMFace *)ss->active_face_index.i);
}
@ -745,7 +749,7 @@ static int sculpt_undo_bmesh_restore(bContext *C,
ss->active_face_index.i = -1;
}
if (ss->active_vertex_index.i) {
if (ss->active_vertex_index.i && ss->active_vertex_index.i != -1LL) {
ss->active_vertex_index.i = (intptr_t)BM_log_vert_id_get(
ss->bm_log, (BMVert *)ss->active_vertex_index.i);
}
@ -753,6 +757,9 @@ static int sculpt_undo_bmesh_restore(bContext *C,
ss->active_vertex_index.i = -1;
}
}
else {
ss->active_face_index.i = ss->active_vertex_index.i = -1;
}
bool ret = false;
@ -760,6 +767,7 @@ static int sculpt_undo_bmesh_restore(bContext *C,
case SCULPT_UNDO_DYNTOPO_BEGIN:
sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
SCULPT_vertex_random_access_ensure(ss);
ss->active_face_index.i = ss->active_vertex_index.i = 0;
ret = true;
break;
case SCULPT_UNDO_DYNTOPO_END:
@ -783,11 +791,20 @@ static int sculpt_undo_bmesh_restore(bContext *C,
ss->active_face_index.i = (intptr_t)BM_log_id_face_get(ss->bm_log,
(uint)ss->active_face_index.i);
}
else {
ss->active_face_index.i = 0;
}
if (ss->active_vertex_index.i != -1) {
ss->active_vertex_index.i = (intptr_t)BM_log_id_vert_get(ss->bm_log,
(uint)ss->active_vertex_index.i);
}
else {
ss->active_vertex_index.i = 0;
}
}
else {
ss->active_face_index.i = ss->active_vertex_index.i = 0;
}
return ret;
@ -831,12 +848,16 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
bool update = false, rebuild = false, update_mask = false, update_visibility = false;
bool need_mask = false;
bool need_refine_subdiv = false;
bool did_first_hack = false;
for (unode = lb->first; unode; unode = unode->next) {
if (unode->bm_entry && !ss->bm) {
// file loading breaks undo because the stack isn't initialized
// detect that case and try to fix it
did_first_hack = true;
ss->active_face_index.i = ss->active_vertex_index.i = 0;
SCULPT_dynamic_topology_enable_ex(CTX_data_main(C), depsgraph, scene, ob);
// see if we have a saved log in the entry
@ -854,6 +875,9 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
}
// PBVH is corrupted at this point, destroy it
SCULPT_pbvh_clear(ob);
/* Restore pivot. */
copy_v3_v3(ss->pivot_pos, unode->pivot_pos);
copy_v3_v3(ss->pivot_rot, unode->pivot_rot);