Sculpt dyntopo: undo bugfixes
* Fixed nasty undo bug related to now rewinding BMLogEntry subchains properly. * Fixed bug in dyntopo collapse
This commit is contained in:
parent
31d2b04411
commit
019700583b
|
@ -159,6 +159,7 @@ static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v);
|
|||
static void pbvh_split_edges(
|
||||
PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge, bool ignore_isolated_edges);
|
||||
void bm_log_message(const char *fmt, ...);
|
||||
void pbvh_bmesh_check_nodes_simple(PBVH *pbvh);
|
||||
|
||||
static BMEdge *bmesh_edge_create_log(PBVH *pbvh, BMVert *v1, BMVert *v2, BMEdge *e_example)
|
||||
{
|
||||
|
@ -804,7 +805,7 @@ static void pbvh_bmesh_face_remove(
|
|||
else if (ensure_ownership_transfer && !BM_vert_face_count_is_equal(v, 1)) {
|
||||
pbvh_bmesh_vert_remove(pbvh, v);
|
||||
|
||||
f_node->flag |= PBVH_RebuildNodeVerts;
|
||||
f_node->flag |= PBVH_RebuildNodeVerts | PBVH_UpdateOtherVerts;
|
||||
// printf("failed to find new_node\n");
|
||||
}
|
||||
}
|
||||
|
@ -2391,6 +2392,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
check_vert_fan_are_tris(pbvh, e->v1);
|
||||
check_vert_fan_are_tris(pbvh, e->v2);
|
||||
|
||||
// pbvh_bmesh_check_nodes_simple(pbvh);
|
||||
|
||||
bm_log_message(" == collapse == ");
|
||||
|
||||
// make sure origdata is up to date prior to interpolation
|
||||
|
@ -2440,6 +2443,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
/* Remove the merge vertex from the PBVH */
|
||||
pbvh_bmesh_vert_remove(pbvh, v_del);
|
||||
|
||||
// pbvh_bmesh_check_nodes_simple(pbvh);
|
||||
|
||||
/* Remove all faces adjacent to the edge */
|
||||
BMLoop *l_adj;
|
||||
while ((l_adj = e->l)) {
|
||||
|
@ -2473,6 +2478,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
BM_face_kill(pbvh->bm, f_adj);
|
||||
}
|
||||
|
||||
// pbvh_bmesh_check_nodes_simple(pbvh);
|
||||
|
||||
/* Kill the edge */
|
||||
BLI_assert(BM_edge_is_wire(e));
|
||||
|
||||
|
@ -2553,6 +2560,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
//*/
|
||||
}
|
||||
|
||||
// pbvh_bmesh_check_nodes_simple(pbvh);
|
||||
|
||||
#if 1
|
||||
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_del) {
|
||||
BMFace *existing_face;
|
||||
|
@ -2601,6 +2610,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
PBVHNode *n = pbvh_bmesh_node_from_face(pbvh, f);
|
||||
int ni = n - pbvh->nodes;
|
||||
|
||||
n->flag |= PBVH_UpdateOtherVerts;
|
||||
|
||||
bm_edges_from_tri(pbvh, old_tri, e_tri);
|
||||
bm_edges_from_tri_example(pbvh, v_tri, e_tri);
|
||||
|
||||
|
@ -2633,6 +2644,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
BM_LOOPS_OF_VERT_ITER_END;
|
||||
#endif
|
||||
|
||||
// pbvh_bmesh_check_nodes_simple(pbvh);
|
||||
|
||||
/* Delete the tagged faces */
|
||||
for (int i = 0; i < (int)deleted_faces->count; i++) {
|
||||
BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i);
|
||||
|
@ -2729,12 +2742,41 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
mv_conn->flag |= DYNVERT_NEED_DISK_SORT | DYNVERT_NEED_VALENCE | DYNVERT_NEED_BOUNDARY;
|
||||
}
|
||||
|
||||
if (v_del->e) {
|
||||
BMEdge *e = v_del->e;
|
||||
|
||||
do {
|
||||
if (e->l) {
|
||||
BMLoop *l = e->l;
|
||||
do {
|
||||
printf("error in collapse_edge\n");
|
||||
int ni = BM_ELEM_CD_GET_INT(l->f, pbvh->cd_face_node_offset);
|
||||
|
||||
BM_log_face_removed(pbvh->bm_log, l->f);
|
||||
|
||||
if (ni >= 0) {
|
||||
PBVHNode *node = pbvh->nodes + ni;
|
||||
BLI_table_gset_remove(node->bm_faces, l->f, NULL);
|
||||
BM_ELEM_CD_SET_INT(l->f, pbvh->cd_face_node_offset, DYNTOPO_NODE_NONE);
|
||||
}
|
||||
else {
|
||||
printf("face did not have a node ref\n");
|
||||
}
|
||||
} while ((l = l->radial_next) != e->l);
|
||||
}
|
||||
|
||||
e = BM_DISK_EDGE_NEXT(e, v_del);
|
||||
} while (e != v_del->e);
|
||||
}
|
||||
|
||||
/* Delete v_del */
|
||||
pbvh_kill_vert(pbvh, v_del);
|
||||
|
||||
BLI_array_free(ws);
|
||||
BLI_array_free(blocks);
|
||||
BLI_array_free(ls);
|
||||
|
||||
// pbvh_bmesh_check_nodes_simple(pbvh);
|
||||
}
|
||||
|
||||
static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
|
||||
|
|
|
@ -79,9 +79,11 @@
|
|||
|
||||
#include "bmesh.h"
|
||||
|
||||
// XXX todo: work our bad module cross ref
|
||||
// XXX todo: figure out bad cross module refs
|
||||
void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me);
|
||||
void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
|
||||
void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
|
||||
BMesh *SCULPT_dyntopo_empty_bmesh();
|
||||
|
||||
static void palette_init_data(ID *id)
|
||||
{
|
||||
|
@ -1383,17 +1385,29 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
|
|||
|
||||
if (ss->bm) {
|
||||
if (ob->data) {
|
||||
if (reorder && ss->bm_log) {
|
||||
BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
|
||||
}
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
BM_mesh_bm_to_me(NULL,
|
||||
NULL,
|
||||
ss->bm,
|
||||
ob->data,
|
||||
(&(struct BMeshToMeshParams){
|
||||
.calc_object_remap = false,
|
||||
}));
|
||||
BM_mesh_bm_to_me(
|
||||
NULL,
|
||||
NULL,
|
||||
ss->bm,
|
||||
ob->data,
|
||||
(&(struct BMeshToMeshParams){.calc_object_remap = false,
|
||||
#ifdef WHEN_GLOBAL_UNDO_WORKS
|
||||
|
||||
/*
|
||||
for memfile undo steps we need to
|
||||
save id and temporary layers
|
||||
*/
|
||||
.copy_temp_cdlayers = true,
|
||||
.copy_mesh_id_layers = true,
|
||||
.cd_mask_extra = CD_MASK_MESH_ID | CD_MASK_DYNTOPO_VERT
|
||||
#else
|
||||
.copy_temp_cdlayers = false,
|
||||
.copy_mesh_id_layers = false
|
||||
#endif
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2254,6 +2268,46 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
ob->sculpt->pbvh = pbvh;
|
||||
}
|
||||
else {
|
||||
#ifdef WHEN_GLOBAL_UNDO_WORKS
|
||||
/*detect if we are loading from an undo memfile step*/
|
||||
Mesh *mesh_orig = BKE_object_get_original_mesh(ob);
|
||||
bool is_dyntopo = (mesh_orig->flag & ME_SCULPT_DYNAMIC_TOPOLOGY);
|
||||
|
||||
is_dyntopo = is_dyntopo && CustomData_has_layer(&mesh_orig->vdata, CD_MESH_ID);
|
||||
is_dyntopo = is_dyntopo && CustomData_has_layer(&mesh_orig->edata, CD_MESH_ID);
|
||||
is_dyntopo = is_dyntopo && CustomData_has_layer(&mesh_orig->pdata, CD_MESH_ID);
|
||||
|
||||
if (is_dyntopo) {
|
||||
BMesh *bm = SCULPT_dyntopo_empty_bmesh();
|
||||
|
||||
ob->sculpt->bm = bm;
|
||||
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
bm,
|
||||
mesh_orig,
|
||||
(&(struct BMeshFromMeshParams){.calc_face_normal = true,
|
||||
.use_shapekey = true,
|
||||
.active_shapekey = ob->shapenr,
|
||||
.copy_id_layers = true,
|
||||
.copy_temp_cdlayers = true,
|
||||
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
|
||||
|
||||
SCULPT_dyntopo_node_layers_add(ob->sculpt);
|
||||
|
||||
pbvh = build_pbvh_for_dynamic_topology(ob);
|
||||
}
|
||||
else {
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *mesh_eval = object_eval->data;
|
||||
if (mesh_eval->runtime.subdiv_ccg != NULL) {
|
||||
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime.subdiv_ccg, respect_hide);
|
||||
}
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
|
||||
}
|
||||
}
|
||||
#else
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *mesh_eval = object_eval->data;
|
||||
if (mesh_eval->runtime.subdiv_ccg != NULL) {
|
||||
|
@ -2263,6 +2317,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ob->sculpt->pbvh = pbvh;
|
||||
|
|
|
@ -1418,7 +1418,9 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
|||
|
||||
for (int i = 0; i < node->tot_mat_draw_buffers; i++) {
|
||||
if (i >= node->tot_tri_buffers) {
|
||||
printf("pbvh corruption!\n");
|
||||
printf("node->tot_mat_draw_buffers >= node->tot_tri_buffers! %d %d\n",
|
||||
node->tot_mat_draw_buffers,
|
||||
node->tot_tri_buffers);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,42 @@ Topology rake:
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void _debugprint(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void pbvh_bmesh_check_nodes_simple(PBVH *pbvh)
|
||||
{
|
||||
#if 0
|
||||
for (int i = 0; i < pbvh->totnode; i++) {
|
||||
PBVHNode *node = pbvh->nodes + i;
|
||||
BMFace *f;
|
||||
|
||||
if (!(node->flag & PBVH_Leaf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
if (!f || f->head.htype != BM_FACE) {
|
||||
_debugprint("Corrupted (freed?) face in node->bm_faces\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset) != i) {
|
||||
_debugprint("Face in more then one node\n");
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void pbvh_bmesh_check_nodes(PBVH *pbvh)
|
||||
{
|
||||
#if 0
|
||||
|
@ -88,11 +124,12 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
|
|||
int ni = BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset);
|
||||
|
||||
if (ni >= 0 && !v->e || !v->e->l) {
|
||||
printf("wire vert had node reference\n");
|
||||
_debugprint("wire vert had node reference\n");
|
||||
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
|
||||
}
|
||||
|
||||
if (ni < -1 || ni >= pbvh->totnode) {
|
||||
printf("vert node ref was invalid");
|
||||
_debugprint("vert node ref was invalid");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -102,25 +139,25 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
|
|||
|
||||
PBVHNode *node = pbvh->nodes + ni;
|
||||
if (!(node->flag & PBVH_Leaf) || !node->bm_unique_verts) {
|
||||
printf("vert node ref was in non leaf node");
|
||||
_debugprint("vert node ref was in non leaf node");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!BLI_table_gset_haskey(node->bm_unique_verts, v)) {
|
||||
printf("vert not in node->bm_unique_verts\n");
|
||||
_debugprint("vert not in node->bm_unique_verts\n");
|
||||
}
|
||||
|
||||
if (BLI_table_gset_haskey(node->bm_other_verts, v)) {
|
||||
printf("vert in node->bm_other_verts");
|
||||
_debugprint("vert in node->bm_other_verts");
|
||||
}
|
||||
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
|
||||
BKE_pbvh_bmesh_check_valence(pbvh, (SculptVertRef){.i = (intptr_t)v});
|
||||
|
||||
if (BM_vert_edge_count(v) != mv->valence) {
|
||||
printf("cached vertex valence mismatch; old: %d, should be: %d\n",
|
||||
mv->valence,
|
||||
BM_vert_edge_count(v));
|
||||
_debugprint("cached vertex valence mismatch; old: %d, should be: %d\n",
|
||||
mv->valence,
|
||||
BM_vert_edge_count(v));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,12 +168,12 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
|
|||
|
||||
// delete nodes should
|
||||
if (node->flag & PBVH_Delete) {
|
||||
printf("orphaned delete node\n");
|
||||
_debugprint("orphaned delete node\n");
|
||||
}
|
||||
|
||||
if (!(node->flag & PBVH_Leaf)) {
|
||||
if (node->bm_unique_verts || node->bm_other_verts || node->bm_faces) {
|
||||
printf("dangling leaf pointers in non-leaf node\n");
|
||||
_debugprint("dangling leaf pointers in non-leaf node\n");
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -148,42 +185,43 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
|
|||
if (ni != i) {
|
||||
if (ni >= 0 && ni < pbvh->totnode) {
|
||||
PBVHNode *node2 = pbvh->nodes + ni;
|
||||
printf("v node offset is wrong, %d\n",
|
||||
!node2->bm_unique_verts ? 0 : BLI_table_gset_haskey(node2->bm_unique_verts, v));
|
||||
_debugprint("v node offset is wrong, %d\n",
|
||||
!node2->bm_unique_verts ? 0 :
|
||||
BLI_table_gset_haskey(node2->bm_unique_verts, v));
|
||||
}
|
||||
else {
|
||||
printf("v node offset is wrong\n");
|
||||
_debugprint("v node offset is wrong\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!v || v->head.htype != BM_VERT) {
|
||||
printf("corruption in pbvh! bm_unique_verts\n");
|
||||
_debugprint("corruption in pbvh! bm_unique_verts\n");
|
||||
}
|
||||
else if (BLI_table_gset_haskey(node->bm_other_verts, v)) {
|
||||
printf("v in both unique and other verts\n");
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
|
||||
TGSET_ITER (v, node->bm_other_verts) {
|
||||
if (!v || v->head.htype != BM_VERT) {
|
||||
printf("corruption in pbvh! bm_other_verts\n");
|
||||
}
|
||||
else if (BLI_table_gset_haskey(node->bm_unique_verts, v)) {
|
||||
printf("v in both unique and other verts\n");
|
||||
_debugprint("v in both unique and other verts\n");
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
if (!f || f->head.htype != BM_FACE) {
|
||||
printf("corruption in pbvh! bm_faces\n");
|
||||
_debugprint("corruption in pbvh! bm_faces\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int ni = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
|
||||
if (pbvh->nodes + ni != node) {
|
||||
printf("face in multiple nodes!\n");
|
||||
_debugprint("face in multiple nodes!\n");
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
|
||||
TGSET_ITER (v, node->bm_other_verts) {
|
||||
if (!v || v->head.htype != BM_VERT) {
|
||||
_debugprint("corruption in pbvh! bm_other_verts\n");
|
||||
}
|
||||
else if (BLI_table_gset_haskey(node->bm_unique_verts, v)) {
|
||||
_debugprint("v in both unique and other verts\n");
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
|
@ -489,7 +527,7 @@ void bke_pbvh_insert_face_finalize(PBVH *pbvh, BMFace *f, const int ni)
|
|||
BLI_table_gset_add(node->bm_faces, f);
|
||||
|
||||
int updateflag = PBVH_UpdateTris | PBVH_UpdateBB | PBVH_UpdateDrawBuffers |
|
||||
PBVH_UpdateCurvatureDir;
|
||||
PBVH_UpdateCurvatureDir | PBVH_UpdateOtherVerts;
|
||||
updateflag |= PBVH_UpdateColor | PBVH_UpdateMask | PBVH_UpdateNormals | PBVH_UpdateOriginalBB;
|
||||
updateflag |= PBVH_UpdateVisibility | PBVH_UpdateRedraw;
|
||||
|
||||
|
|
|
@ -867,13 +867,19 @@ static void bm_log_faces_restore(
|
|||
}
|
||||
|
||||
if (v->head.htype != BM_VERT) {
|
||||
printf("bm_log corruption!\n");
|
||||
printf("vert %d in face %d was not a vertex\n", (int)lf->v_ids[i], POINTER_AS_INT(key));
|
||||
continue;
|
||||
}
|
||||
BLI_array_append(vs_tmp, v);
|
||||
}
|
||||
|
||||
BMFace *f = BM_face_create_verts(bm, vs_tmp, (int)lf->len, NULL, BM_CREATE_SKIP_ID, true);
|
||||
if ((int)BLI_array_len(vs_tmp) < 2) {
|
||||
printf("severely malformed face %d in %s\n", POINTER_AS_INT(key), __func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
BMFace *f = BM_face_create_verts(
|
||||
bm, vs_tmp, (int)BLI_array_len(vs_tmp), NULL, BM_CREATE_SKIP_ID, true);
|
||||
f->head.hflag = lf->hflag;
|
||||
|
||||
copy_v3_v3(f->no, lf->no);
|
||||
|
@ -917,6 +923,11 @@ static void bm_log_vert_values_swap(
|
|||
uint id = POINTER_AS_UINT(key);
|
||||
BMVert *v = bm_log_vert_from_id(log, id);
|
||||
|
||||
if (!v) {
|
||||
printf("missing vert in bmlog! %d", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
swap_v3_v3(v->co, lv->co);
|
||||
swap_v3_v3(v->no, lv->no);
|
||||
|
||||
|
@ -1370,25 +1381,23 @@ void BM_log_print_entry(BMLog *log, BMLogEntry *entry)
|
|||
printf("==element IDs snapshot\n");
|
||||
break;
|
||||
case LOG_ENTRY_PARTIAL:
|
||||
printf(" ==entry==\n");
|
||||
printf(" modified:\n");
|
||||
printf(" verts: %d\n", BLI_ghash_len(first->modified_verts));
|
||||
printf(" edges: %d\n", BLI_ghash_len(first->modified_edges));
|
||||
printf(" faces: %d\n", BLI_ghash_len(first->modified_faces));
|
||||
printf(" new:\n");
|
||||
printf(" verts: %d\n", BLI_ghash_len(first->added_verts));
|
||||
printf(" edges: %d\n", BLI_ghash_len(first->added_edges));
|
||||
printf(" faces: %d\n", BLI_ghash_len(first->added_faces));
|
||||
printf(" deleted:\n");
|
||||
printf(" verts: %d\n", BLI_ghash_len(first->deleted_verts));
|
||||
printf(" edges: %d\n", BLI_ghash_len(first->deleted_edges));
|
||||
printf("post edges: %d\n", BLI_ghash_len(first->deleted_edges_post));
|
||||
printf(" faces: %d\n", BLI_ghash_len(first->deleted_faces));
|
||||
printf("==modified: ");
|
||||
printf("v: %d ", BLI_ghash_len(first->modified_verts));
|
||||
printf("e: %d ", BLI_ghash_len(first->modified_edges));
|
||||
printf("f: %d ", BLI_ghash_len(first->modified_faces));
|
||||
printf(" new: ");
|
||||
printf("v: %d ", BLI_ghash_len(first->added_verts));
|
||||
printf("e: %d ", BLI_ghash_len(first->added_edges));
|
||||
printf("f: %d ", BLI_ghash_len(first->added_faces));
|
||||
printf(" deleted: ");
|
||||
printf("v: %d ", BLI_ghash_len(first->deleted_verts));
|
||||
printf("e: %d ", BLI_ghash_len(first->deleted_edges));
|
||||
printf("pe: %d ", BLI_ghash_len(first->deleted_edges_post));
|
||||
printf("f: %d ", BLI_ghash_len(first->deleted_faces));
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
first = first->combined_next;
|
||||
}
|
||||
}
|
||||
|
@ -1585,6 +1594,11 @@ void BM_log_entry_drop(BMLogEntry *entry)
|
|||
{
|
||||
BMLog *log = entry->log;
|
||||
|
||||
// go to head of entry subgroup
|
||||
while (entry->combined_next) {
|
||||
entry = entry->combined_next;
|
||||
}
|
||||
|
||||
if (!log) {
|
||||
/* Unlink */
|
||||
BLI_assert(!(entry->prev && entry->next));
|
||||
|
@ -2469,14 +2483,31 @@ void BM_log_face_removed(BMLog *log, BMFace *f)
|
|||
!!log_ghash_haskey(log, entry->added_faces, key));
|
||||
|
||||
if (!log_ghash_remove(log, entry->added_faces, key, NULL, NULL)) {
|
||||
BMLogFace *lf;
|
||||
BMLogFace *lf = bm_log_face_alloc(log, f);
|
||||
|
||||
lf = bm_log_face_alloc(log, f);
|
||||
log_ghash_insert(log, entry->deleted_faces, key, lf);
|
||||
void **val;
|
||||
if (BLI_ghash_ensure_p(entry->deleted_faces, key, &val)) {
|
||||
BMLogFace *lf2 = (BMLogFace *)*val;
|
||||
|
||||
if (lf2->customdata_f) {
|
||||
// BLI_mempool_free(entry->pdata.pool, lf2->customdata_f);
|
||||
CustomData_bmesh_free_block(&entry->pdata, &lf2->customdata_f);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < lf2->len; i++) {
|
||||
if (lf2->customdata[i]) {
|
||||
CustomData_bmesh_free_block(&entry->ldata, &lf2->customdata[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_mempool_free(entry->pool_faces, (void *)lf2);
|
||||
}
|
||||
|
||||
if (lf) {
|
||||
bm_log_face_customdata(log->bm, log, f, lf);
|
||||
}
|
||||
|
||||
*val = lf;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -229,25 +229,10 @@ void BM_enter_multires_space(Object *ob, BMesh *bm, int space)
|
|||
* \warning This function doesn't calculate face normals.
|
||||
*/
|
||||
|
||||
/* joeedh:
|
||||
GCC under linux is doing something very weird. In the line below:
|
||||
|
||||
MultiresModifierData *mmd = ob ? get_multires_modifier(NULL, ob, true) : NULL;
|
||||
|
||||
ob is evaulating to true when optimizations are on. The following code:
|
||||
|
||||
printf("ob: %p, %s\n", ob, ob ? "true" : "false");
|
||||
|
||||
will print (nil), true. Very strange!
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
__attribute__((optimize("O0")))
|
||||
#endif
|
||||
void BM_mesh_bm_from_me(Object *ob,
|
||||
BMesh *bm,
|
||||
const Mesh *me,
|
||||
const struct BMeshFromMeshParams *params)
|
||||
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));
|
||||
|
@ -413,6 +398,7 @@ void BM_mesh_bm_from_me(Object *ob,
|
|||
BM_mesh_cd_flag_apply(bm, me->cd_flag);
|
||||
}
|
||||
|
||||
int *existing_id_layers[4] = {NULL, NULL, NULL, NULL};
|
||||
int use_exist_ids = 0;
|
||||
int has_ids = bm->idmap.flag & BM_HAS_IDS ?
|
||||
(bm->idmap.flag & (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)) :
|
||||
|
@ -423,9 +409,9 @@ void BM_mesh_bm_from_me(Object *ob,
|
|||
const CustomData *cdatas[] = {&me->vdata, &me->edata, &me->ldata, &me->pdata};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int idx = CustomData_get_layer_index(cdatas[i], CD_MESH_ID);
|
||||
existing_id_layers[i] = (int *)CustomData_get_layer(cdatas[i], CD_MESH_ID);
|
||||
|
||||
if (idx >= 0) {
|
||||
if (existing_id_layers[i]) {
|
||||
use_exist_ids |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
@ -467,7 +453,7 @@ void BM_mesh_bm_from_me(Object *ob,
|
|||
|
||||
if (has_ids & BM_VERT) {
|
||||
if (use_exist_ids & BM_VERT) {
|
||||
bm_assign_id(bm, (BMElem *)v, BM_ELEM_GET_ID(bm, v));
|
||||
bm_assign_id(bm, (BMElem *)v, existing_id_layers[0][i]);
|
||||
}
|
||||
else {
|
||||
bm_alloc_id(bm, (BMElem *)v);
|
||||
|
@ -516,7 +502,7 @@ void BM_mesh_bm_from_me(Object *ob,
|
|||
|
||||
if (has_ids & BM_EDGE) {
|
||||
if (use_exist_ids & BM_EDGE) {
|
||||
bm_assign_id(bm, (BMElem *)e, BM_ELEM_GET_ID(bm, e));
|
||||
bm_assign_id(bm, (BMElem *)e, existing_id_layers[1][i]);
|
||||
}
|
||||
else {
|
||||
bm_alloc_id(bm, (BMElem *)e);
|
||||
|
@ -587,7 +573,7 @@ void BM_mesh_bm_from_me(Object *ob,
|
|||
|
||||
if (has_ids & BM_LOOP) {
|
||||
if (use_exist_ids & BM_LOOP) {
|
||||
bm_assign_id(bm, (BMElem *)l_iter, BM_ELEM_GET_ID(bm, l_iter));
|
||||
bm_assign_id(bm, (BMElem *)l_iter, existing_id_layers[2][j - 1]);
|
||||
}
|
||||
else {
|
||||
bm_alloc_id(bm, (BMElem *)l_iter);
|
||||
|
@ -600,7 +586,7 @@ void BM_mesh_bm_from_me(Object *ob,
|
|||
|
||||
if (has_ids & BM_FACE) {
|
||||
if (use_exist_ids & BM_FACE) {
|
||||
bm_assign_id(bm, (BMElem *)f, BM_ELEM_GET_ID(bm, f));
|
||||
bm_assign_id(bm, (BMElem *)f, existing_id_layers[3][i]);
|
||||
}
|
||||
else {
|
||||
bm_alloc_id(bm, (BMElem *)f);
|
||||
|
|
|
@ -50,7 +50,7 @@ struct Object;
|
|||
void BM_mesh_bm_from_me(struct Object *ob,
|
||||
BMesh *bm,
|
||||
const struct Mesh *me,
|
||||
const struct BMeshFromMeshParams *params) ATTR_NONNULL(2, 3);
|
||||
const struct BMeshFromMeshParams *params) ATTR_NONNULL(2, 4);
|
||||
|
||||
struct BMeshToMeshParams {
|
||||
/** Update object hook indices & vertex parents. */
|
||||
|
|
|
@ -83,6 +83,18 @@
|
|||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
BMesh *SCULPT_dyntopo_empty_bmesh()
|
||||
{
|
||||
BMesh *bm = BM_mesh_create(
|
||||
&bm_mesh_allocsize_default,
|
||||
&((struct BMeshCreateParams){.use_toolflags = false,
|
||||
.use_unique_ids = true,
|
||||
.use_id_elem_mask = BM_VERT | BM_EDGE | BM_FACE,
|
||||
.use_id_map = true,
|
||||
.no_reuse_ids = false}));
|
||||
|
||||
return bm;
|
||||
}
|
||||
// TODO: check if (mathematically speaking) is it really necassary
|
||||
// to sort the edge lists around verts
|
||||
|
||||
|
|
|
@ -521,10 +521,28 @@ static void bmesh_undo_on_edge_change(BMEdge *v, void *userdata, void *old_custo
|
|||
|
||||
static void bmesh_undo_on_edge_kill(BMEdge *e, void *userdata)
|
||||
{
|
||||
BmeshUndoData *data = (BmeshUndoData *)userdata;
|
||||
|
||||
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(data->cd_dyn_vert, e->v1);
|
||||
MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(data->cd_dyn_vert, e->v2);
|
||||
|
||||
mv1->flag |= DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_TRIANGULATE | DYNVERT_NEED_DISK_SORT |
|
||||
DYNVERT_NEED_VALENCE;
|
||||
mv2->flag |= DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_TRIANGULATE | DYNVERT_NEED_DISK_SORT |
|
||||
DYNVERT_NEED_VALENCE;
|
||||
}
|
||||
|
||||
static void bmesh_undo_on_edge_add(BMEdge *e, void *userdata)
|
||||
{
|
||||
BmeshUndoData *data = (BmeshUndoData *)userdata;
|
||||
|
||||
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(data->cd_dyn_vert, e->v1);
|
||||
MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(data->cd_dyn_vert, e->v2);
|
||||
|
||||
mv1->flag |= DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_TRIANGULATE | DYNVERT_NEED_DISK_SORT |
|
||||
DYNVERT_NEED_VALENCE;
|
||||
mv2->flag |= DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_TRIANGULATE | DYNVERT_NEED_DISK_SORT |
|
||||
DYNVERT_NEED_VALENCE;
|
||||
}
|
||||
|
||||
static void bmesh_undo_on_vert_change(BMVert *v, void *userdata, void *old_customdata)
|
||||
|
@ -884,6 +902,14 @@ static void sculpt_undo_geometry_restore(SculptUndoNode *unode, Object *object)
|
|||
static int sculpt_undo_bmesh_restore(
|
||||
bContext *C, SculptUndoNode *unode, Object *ob, SculptSession *ss, int dir)
|
||||
{
|
||||
// handle transition from another undo type
|
||||
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ss->bm_log && ss->bm &&
|
||||
!ELEM(unode->type, SCULPT_UNDO_DYNTOPO_BEGIN, SCULPT_UNDO_DYNTOPO_END)) {
|
||||
SCULPT_dyntopo_node_layers_update_offsets(ss);
|
||||
|
@ -2149,9 +2175,12 @@ static void sculpt_undosys_step_decode(
|
|||
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
|
||||
|
||||
Mesh *me = ob->data;
|
||||
|
||||
#ifndef WHEN_GLOBAL_UNDO_WORKS
|
||||
/* Don't add sculpt topology undo steps when reading back undo state.
|
||||
* The undo steps must enter/exit for us. */
|
||||
me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
|
||||
#endif
|
||||
ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, NULL);
|
||||
}
|
||||
|
||||
|
@ -2376,6 +2405,12 @@ static void print_sculpt_undo_step(UndoStep *us, UndoStep *active, int i)
|
|||
SculptUndoNode *node;
|
||||
|
||||
if (us->type != BKE_UNDOSYS_TYPE_SCULPT) {
|
||||
printf("%d %s (non-sculpt): '%s', type:%s, use_memfile_step:%s\n",
|
||||
i,
|
||||
us == active ? "->" : " ",
|
||||
us->name,
|
||||
us->type->name,
|
||||
us->use_memfile_step ? "true" : "false");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2388,7 +2423,12 @@ static void print_sculpt_undo_step(UndoStep *us, UndoStep *active, int i)
|
|||
|
||||
id = su->id;
|
||||
|
||||
printf("id=%d %s %d %s\n", id, us == active ? "->" : " ", i, us->name);
|
||||
printf("id=%d %s %d %s (use_memfile_step=%s)\n",
|
||||
id,
|
||||
us == active ? "->" : " ",
|
||||
i,
|
||||
us->name,
|
||||
us->use_memfile_step ? "true" : "false");
|
||||
|
||||
if (us->type == BKE_UNDOSYS_TYPE_SCULPT) {
|
||||
UndoSculpt *usculpt = sculpt_undosys_step_get_nodes(us);
|
||||
|
|
Loading…
Reference in New Issue