Sculpt: BMLog stuff
* BMLog now has a more fine-grained logging facility to track the call chains that produce specific log elements. * Wrote a new function in bmesh_core.c to dump local geometry around an element to stdout in .obj format. * Edge collapse now properly handles the fact that bmesh handles sharp flags inversely, i.e. edges *not* marked with BM_ELEM_SMOOTH are sharp. * Wrote a new BMLog API that handles elements undergoing topological changes a bit better. - BM_log_[edge/face]_[pre/post] - Idea is to call the _pre before calling collapse or split edge, then _post afterwards. - No longer need to assign new IDs in certain cases to avoid confusing BMLog. - Other parts of BMLog may now be redundant; need to check. * Deleted some #if 0'd code * Fixed a bug in BLI_smallhash_ensure_p, it didn't properly set up state for when smallhash is used as a very simple set.
This commit is contained in:
parent
ffa62ecb60
commit
b8fb46ab20
File diff suppressed because it is too large
Load Diff
|
@ -19,12 +19,12 @@
|
|||
|
||||
#ifdef __GNUC__
|
||||
/* I can't even *cast* signed ints in gcc's sign-conversion warning? gcc 10.3.0 -joeedh */
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* I can't even *cast* signed ints in gcc's sign-conversion warning? gcc 10.3.0 -joeedh */
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
/** \file
|
||||
|
@ -335,13 +335,16 @@ bool BLI_smallhash_ensure_p(SmallHash *sh, uintptr_t key, void ***item)
|
|||
if (e->val == SMHASH_CELL_FREE || e->val == SMHASH_CELL_UNUSED) {
|
||||
sh->nentries++;
|
||||
sh->nfreecells--;
|
||||
|
||||
ret = false;
|
||||
e->val = NULL;
|
||||
}
|
||||
else {
|
||||
ret = true;
|
||||
}
|
||||
|
||||
e->key = key;
|
||||
|
||||
*item = &e->val;
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "BLI_asan.h"
|
||||
#include "BLI_linklist_stack.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_smallhash.h"
|
||||
#include "BLI_utildefines_stack.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
@ -40,6 +41,8 @@
|
|||
#include "intern/bmesh_private.h"
|
||||
#include "range_tree.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* use so valgrinds memcheck alerts us when undefined index is used.
|
||||
* TESTING ONLY! */
|
||||
// #define USE_DEBUG_INDEX_MEMCHECK
|
||||
|
@ -581,6 +584,41 @@ BMFace *BM_face_create_verts(BMesh *bm,
|
|||
return BM_face_create(bm, vert_arr, edge_arr, len, f_example, create_flag);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
IS_OK = 0,
|
||||
IS_NULL = (1 << 0),
|
||||
IS_WRONG_TYPE = (1 << 1),
|
||||
|
||||
IS_VERT_WRONG_EDGE_TYPE = (1 << 2),
|
||||
|
||||
IS_EDGE_NULL_DISK_LINK = (1 << 3),
|
||||
IS_EDGE_WRONG_LOOP_TYPE = (1 << 4),
|
||||
IS_EDGE_WRONG_FACE_TYPE = (1 << 5),
|
||||
IS_EDGE_NULL_RADIAL_LINK = (1 << 6),
|
||||
IS_EDGE_ZERO_FACE_LENGTH = (1 << 7),
|
||||
|
||||
IS_LOOP_WRONG_FACE_TYPE = (1 << 8),
|
||||
IS_LOOP_WRONG_EDGE_TYPE = (1 << 9),
|
||||
IS_LOOP_WRONG_VERT_TYPE = (1 << 10),
|
||||
IS_LOOP_VERT_NOT_IN_EDGE = (1 << 11),
|
||||
IS_LOOP_NULL_CYCLE_LINK = (1 << 12),
|
||||
IS_LOOP_ZERO_FACE_LENGTH = (1 << 13),
|
||||
IS_LOOP_WRONG_FACE_LENGTH = (1 << 14),
|
||||
IS_LOOP_WRONG_RADIAL_LENGTH = (1 << 15),
|
||||
|
||||
IS_FACE_NULL_LOOP = (1 << 16),
|
||||
IS_FACE_WRONG_LOOP_FACE = (1 << 17),
|
||||
IS_FACE_NULL_EDGE = (1 << 18),
|
||||
IS_FACE_NULL_VERT = (1 << 19),
|
||||
IS_FACE_LOOP_VERT_NOT_IN_EDGE = (1 << 20),
|
||||
IS_FACE_LOOP_WRONG_RADIAL_LENGTH = (1 << 21),
|
||||
IS_FACE_LOOP_WRONG_DISK_LENGTH = (1 << 22),
|
||||
IS_FACE_LOOP_DUPE_LOOP = (1 << 23),
|
||||
IS_FACE_LOOP_DUPE_VERT = (1 << 24),
|
||||
IS_FACE_LOOP_DUPE_EDGE = (1 << 25),
|
||||
IS_FACE_WRONG_LENGTH = (1 << 26),
|
||||
} BMeshInternalError;
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
/**
|
||||
|
@ -592,39 +630,7 @@ BMFace *BM_face_create_verts(BMesh *bm,
|
|||
int bmesh_elem_check(void *element, const char htype)
|
||||
{
|
||||
BMHeader *head = element;
|
||||
enum {
|
||||
IS_NULL = (1 << 0),
|
||||
IS_WRONG_TYPE = (1 << 1),
|
||||
|
||||
IS_VERT_WRONG_EDGE_TYPE = (1 << 2),
|
||||
|
||||
IS_EDGE_NULL_DISK_LINK = (1 << 3),
|
||||
IS_EDGE_WRONG_LOOP_TYPE = (1 << 4),
|
||||
IS_EDGE_WRONG_FACE_TYPE = (1 << 5),
|
||||
IS_EDGE_NULL_RADIAL_LINK = (1 << 6),
|
||||
IS_EDGE_ZERO_FACE_LENGTH = (1 << 7),
|
||||
|
||||
IS_LOOP_WRONG_FACE_TYPE = (1 << 8),
|
||||
IS_LOOP_WRONG_EDGE_TYPE = (1 << 9),
|
||||
IS_LOOP_WRONG_VERT_TYPE = (1 << 10),
|
||||
IS_LOOP_VERT_NOT_IN_EDGE = (1 << 11),
|
||||
IS_LOOP_NULL_CYCLE_LINK = (1 << 12),
|
||||
IS_LOOP_ZERO_FACE_LENGTH = (1 << 13),
|
||||
IS_LOOP_WRONG_FACE_LENGTH = (1 << 14),
|
||||
IS_LOOP_WRONG_RADIAL_LENGTH = (1 << 15),
|
||||
|
||||
IS_FACE_NULL_LOOP = (1 << 16),
|
||||
IS_FACE_WRONG_LOOP_FACE = (1 << 17),
|
||||
IS_FACE_NULL_EDGE = (1 << 18),
|
||||
IS_FACE_NULL_VERT = (1 << 19),
|
||||
IS_FACE_LOOP_VERT_NOT_IN_EDGE = (1 << 20),
|
||||
IS_FACE_LOOP_WRONG_RADIAL_LENGTH = (1 << 21),
|
||||
IS_FACE_LOOP_WRONG_DISK_LENGTH = (1 << 22),
|
||||
IS_FACE_LOOP_DUPE_LOOP = (1 << 23),
|
||||
IS_FACE_LOOP_DUPE_VERT = (1 << 24),
|
||||
IS_FACE_LOOP_DUPE_EDGE = (1 << 25),
|
||||
IS_FACE_WRONG_LENGTH = (1 << 26),
|
||||
} err = 0;
|
||||
BMeshInternalError err = IS_OK;
|
||||
|
||||
if (!element) {
|
||||
return IS_NULL;
|
||||
|
@ -799,7 +805,7 @@ int bmesh_elem_check(void *element, const char htype)
|
|||
break;
|
||||
}
|
||||
|
||||
BMESH_ASSERT(err == 0);
|
||||
// BMESH_ASSERT(err == 0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -2150,6 +2156,331 @@ static void check_vert_faces(BMVert *v_target)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _
|
||||
# undef _
|
||||
#endif
|
||||
|
||||
#define _(s) \
|
||||
case s: \
|
||||
return #s;
|
||||
|
||||
static const char *get_err_code_str(BMeshInternalError code)
|
||||
{
|
||||
switch (code) {
|
||||
_(IS_OK)
|
||||
_(IS_NULL)
|
||||
_(IS_WRONG_TYPE)
|
||||
|
||||
_(IS_VERT_WRONG_EDGE_TYPE)
|
||||
|
||||
_(IS_EDGE_NULL_DISK_LINK)
|
||||
_(IS_EDGE_WRONG_LOOP_TYPE)
|
||||
_(IS_EDGE_WRONG_FACE_TYPE)
|
||||
_(IS_EDGE_NULL_RADIAL_LINK)
|
||||
_(IS_EDGE_ZERO_FACE_LENGTH)
|
||||
|
||||
_(IS_LOOP_WRONG_FACE_TYPE)
|
||||
_(IS_LOOP_WRONG_EDGE_TYPE)
|
||||
_(IS_LOOP_WRONG_VERT_TYPE)
|
||||
_(IS_LOOP_VERT_NOT_IN_EDGE)
|
||||
_(IS_LOOP_NULL_CYCLE_LINK)
|
||||
_(IS_LOOP_ZERO_FACE_LENGTH)
|
||||
_(IS_LOOP_WRONG_FACE_LENGTH)
|
||||
_(IS_LOOP_WRONG_RADIAL_LENGTH)
|
||||
|
||||
_(IS_FACE_NULL_LOOP)
|
||||
_(IS_FACE_WRONG_LOOP_FACE)
|
||||
_(IS_FACE_NULL_EDGE)
|
||||
_(IS_FACE_NULL_VERT)
|
||||
_(IS_FACE_LOOP_VERT_NOT_IN_EDGE)
|
||||
_(IS_FACE_LOOP_WRONG_RADIAL_LENGTH)
|
||||
_(IS_FACE_LOOP_WRONG_DISK_LENGTH)
|
||||
_(IS_FACE_LOOP_DUPE_LOOP)
|
||||
_(IS_FACE_LOOP_DUPE_VERT)
|
||||
_(IS_FACE_LOOP_DUPE_EDGE)
|
||||
_(IS_FACE_WRONG_LENGTH)
|
||||
}
|
||||
|
||||
return "(unknown-code)";
|
||||
}
|
||||
#undef _
|
||||
|
||||
static char *get_err_str(int err)
|
||||
{
|
||||
static char buf[1024];
|
||||
buf[0] = 0;
|
||||
|
||||
for (int i = 0; i < 27; i++) {
|
||||
if (err & (1 << i)) {
|
||||
strcat(buf, get_err_code_str(1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void bm_local_obj_free(char *str, char *fixed)
|
||||
{
|
||||
if (str != fixed) {
|
||||
MEM_freeN(str);
|
||||
}
|
||||
}
|
||||
|
||||
#define LOCAL_OBJ_SIZE 512
|
||||
|
||||
static char *obj_append_line(char *line, char *str, char *fixed, int *size, int *i)
|
||||
{
|
||||
int len = (int)strlen(line);
|
||||
|
||||
if (*i + len >= *size) {
|
||||
*size += *size >> 1;
|
||||
|
||||
if (str == fixed) {
|
||||
str = MEM_mallocN(*size, "buf");
|
||||
memcpy(str, fixed, LOCAL_OBJ_SIZE);
|
||||
}
|
||||
else {
|
||||
str = MEM_reallocN(str, *size);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(str + *i, line, len);
|
||||
str[*i + len] = 0;
|
||||
|
||||
*i += len;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *bm_save_local_obj_text(
|
||||
BMesh *bm, int depth, char buf[LOCAL_OBJ_SIZE], const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
BMVert **vs = NULL;
|
||||
BMEdge **es = NULL;
|
||||
BMFace **fs = NULL;
|
||||
|
||||
BLI_array_staticdeclare(vs, 64);
|
||||
BLI_array_staticdeclare(es, 64);
|
||||
BLI_array_staticdeclare(fs, 64);
|
||||
|
||||
SmallHash visit;
|
||||
BLI_smallhash_init(&visit);
|
||||
|
||||
const char *c = fmt;
|
||||
while (*c) {
|
||||
if (*c == ' ' || *c == '\t') {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
||||
void *ptr = va_arg(vl, void *);
|
||||
|
||||
switch (*c) {
|
||||
case 'v':
|
||||
BLI_array_append(vs, (BMVert *)ptr);
|
||||
break;
|
||||
case 'e':
|
||||
BLI_array_append(es, (BMEdge *)ptr);
|
||||
break;
|
||||
case 'f':
|
||||
BLI_array_append(fs, (BMFace *)ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
va_end(vl);
|
||||
|
||||
int tag = 4;
|
||||
for (int i = 0; i < BLI_array_len(fs); i++) {
|
||||
BMFace *f = fs[i];
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
do {
|
||||
l->v->head.api_flag &= ~tag;
|
||||
l->e->head.api_flag &= ~tag;
|
||||
} while ((l = l->next) != f->l_first);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(es); i++) {
|
||||
BMEdge *e = es[i];
|
||||
|
||||
e->v1->head.api_flag &= ~tag;
|
||||
e->v2->head.api_flag &= ~tag;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(vs); i++) {
|
||||
vs[i]->head.api_flag |= tag;
|
||||
}
|
||||
for (int i = 0; i < BLI_array_len(es); i++) {
|
||||
BMEdge *e = es[i];
|
||||
|
||||
if (!(e->v1->head.api_flag & tag)) {
|
||||
BLI_array_append(vs, e->v1);
|
||||
e->v1->head.api_flag |= tag;
|
||||
}
|
||||
|
||||
if (!(e->v2->head.api_flag & tag)) {
|
||||
BLI_array_append(vs, e->v2);
|
||||
e->v2->head.api_flag |= tag;
|
||||
}
|
||||
|
||||
e->head.api_flag |= tag;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(fs); i++) {
|
||||
BMFace *f = fs[i];
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
do {
|
||||
if (!(l->v->head.api_flag & tag)) {
|
||||
BLI_array_append(vs, l->v);
|
||||
l->v->head.api_flag |= tag;
|
||||
}
|
||||
|
||||
if (!(l->e->head.api_flag & tag)) {
|
||||
BLI_array_append(es, l->e);
|
||||
l->e->head.api_flag |= tag;
|
||||
}
|
||||
} while ((l = l->next) != f->l_first);
|
||||
}
|
||||
|
||||
struct {
|
||||
BMVert *v;
|
||||
int depth;
|
||||
} stack[256];
|
||||
|
||||
SmallHash elemset;
|
||||
BLI_smallhash_init(&elemset);
|
||||
|
||||
for (int i = 0; i < BLI_array_len(vs); i++) {
|
||||
BLI_smallhash_insert(&elemset, (uintptr_t)vs[i], NULL);
|
||||
}
|
||||
for (int i = 0; i < BLI_array_len(es); i++) {
|
||||
BLI_smallhash_insert(&elemset, (uintptr_t)es[i], NULL);
|
||||
}
|
||||
for (int i = 0; i < BLI_array_len(fs); i++) {
|
||||
BLI_smallhash_insert(&elemset, (uintptr_t)fs[i], NULL);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(vs); i++) {
|
||||
int si = 0;
|
||||
|
||||
// connected islands only
|
||||
if (i > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
stack[si].v = vs[i];
|
||||
stack[si].depth = 0;
|
||||
si++;
|
||||
|
||||
while (si > 0) {
|
||||
si--;
|
||||
|
||||
BMVert *v = stack[si].v;
|
||||
int startdepth = stack[si].depth;
|
||||
|
||||
void **val;
|
||||
|
||||
if (!BLI_smallhash_ensure_p(&elemset, (uintptr_t)v, &val)) {
|
||||
*val = NULL;
|
||||
BLI_array_append(vs, v);
|
||||
}
|
||||
|
||||
if (!v->e || stack[si].depth > depth) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BMEdge *e = v->e;
|
||||
do {
|
||||
if (!BLI_smallhash_ensure_p(&visit, (uintptr_t)e, &val)) {
|
||||
*val = NULL;
|
||||
stack[si].v = e->v1;
|
||||
stack[si].depth = startdepth + 1;
|
||||
si++;
|
||||
|
||||
stack[si].v = e->v2;
|
||||
stack[si].depth = startdepth + 1;
|
||||
si++;
|
||||
}
|
||||
|
||||
if (!e->l) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BMLoop *l = e->l;
|
||||
do {
|
||||
if (!BLI_smallhash_ensure_p(&visit, (uintptr_t)l->f, &val)) {
|
||||
if (!BLI_smallhash_ensure_p(&elemset, (uintptr_t)l->f, &val)) {
|
||||
*val = NULL;
|
||||
BLI_array_append(fs, l->f);
|
||||
}
|
||||
|
||||
BMLoop *l2 = l;
|
||||
do {
|
||||
if (!BLI_smallhash_ensure_p(&visit, (uintptr_t)l->v, &val)) {
|
||||
*val = NULL;
|
||||
stack[si].v = l->v;
|
||||
stack[si].depth = startdepth + 1;
|
||||
si++;
|
||||
}
|
||||
} while ((l2 = l2->next) != l);
|
||||
}
|
||||
} while ((l = l->radial_next) != e->l);
|
||||
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
|
||||
}
|
||||
}
|
||||
|
||||
char *str = buf;
|
||||
int size = LOCAL_OBJ_SIZE - 1;
|
||||
int stri = 0;
|
||||
|
||||
for (int i = 0; i < BLI_array_len(es); i++) {
|
||||
es[i]->head.api_flag &= ~tag;
|
||||
}
|
||||
|
||||
char line[256];
|
||||
|
||||
for (int i = 0; i < BLI_array_len(vs); i++) {
|
||||
BMVert *v = vs[i];
|
||||
|
||||
v->head.index = i + 1;
|
||||
sprintf(line, "v %.4f %.4f %.4f\n", v->co[0], v->co[1], v->co[2]);
|
||||
|
||||
str = obj_append_line(line, str, buf, &size, &stri);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(fs); i++) {
|
||||
BMFace *f = fs[i];
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
sprintf(line, "f");
|
||||
str = obj_append_line(line, str, buf, &size, &stri);
|
||||
|
||||
do {
|
||||
sprintf(line, " %d", l->v->head.index);
|
||||
str = obj_append_line(line, str, buf, &size, &stri);
|
||||
} while ((l = l->next) != f->l_first);
|
||||
|
||||
str = obj_append_line("\n", str, buf, &size, &stri);
|
||||
}
|
||||
|
||||
BLI_smallhash_release(&visit);
|
||||
BLI_smallhash_release(&elemset);
|
||||
|
||||
BLI_array_free(vs);
|
||||
BLI_array_free(es);
|
||||
BLI_array_free(fs);
|
||||
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* \brief Join Vert Kill Edge (JVKE)
|
||||
*
|
||||
|
@ -2168,11 +2499,33 @@ static void check_vert_faces(BMVert *v_target)
|
|||
* +-+-+-+ +-+-+-+
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
static void trigger_jvke_error(int err, char *obj_text)
|
||||
{
|
||||
printf("========= ERROR %s============\n\n%s\n\n", get_err_str(err), obj_text);
|
||||
}
|
||||
|
||||
#if 0
|
||||
# define JVKE_CHECK_ELEMENT(elem) \
|
||||
{ \
|
||||
int err = 0; \
|
||||
if ((err = bmesh_elem_check(elem, (elem)->head.htype))) { \
|
||||
trigger_jvke_error(err, saved_obj); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
# define JVKE_CHECK_ELEMENT(elem)
|
||||
#endif
|
||||
|
||||
BMVert *bmesh_kernel_join_vert_kill_edge(
|
||||
BMesh *bm, BMEdge *e, BMVert *v_kill, const bool do_del, const bool combine_flags)
|
||||
{
|
||||
BMVert *v_conn = BM_edge_other_vert(e, v_kill);
|
||||
|
||||
char buf[LOCAL_OBJ_SIZE];
|
||||
char *saved_obj = bm_save_local_obj_text(bm, 2, buf, "e", e);
|
||||
bm_local_obj_free(saved_obj, buf);
|
||||
|
||||
BMFace **fs = NULL;
|
||||
BMEdge **deles = NULL;
|
||||
BLI_array_staticdeclare(fs, 32);
|
||||
|
@ -2181,6 +2534,9 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
|
|||
BMVert *v_del = BM_edge_other_vert(e, v_conn);
|
||||
const int tag = _FLAG_WALK_ALT; // using bmhead.api_flag here
|
||||
|
||||
JVKE_CHECK_ELEMENT(v_conn);
|
||||
JVKE_CHECK_ELEMENT(v_del);
|
||||
|
||||
/* first clear tags */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
BMVert *v = i ? v_del : v_conn;
|
||||
|
@ -2284,7 +2640,15 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
|
|||
|
||||
if ((e3 = BM_edge_exists(v_conn, v_other))) {
|
||||
if (combine_flags) {
|
||||
/* TODO: stop flagging sharp edges by the abscene of the BM_ELEM_SMOOTH flag*/
|
||||
bool remove_smooth = !BM_elem_flag_test(l->e, BM_ELEM_SMOOTH);
|
||||
remove_smooth = remove_smooth || !BM_elem_flag_test(e3, BM_ELEM_SMOOTH);
|
||||
|
||||
e3->head.hflag |= l->e->head.hflag;
|
||||
|
||||
if (remove_smooth) {
|
||||
BM_elem_flag_disable(e3, BM_ELEM_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
/* flag for later deletion */
|
||||
|
@ -2305,7 +2669,12 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
|
|||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(deles); i++) {
|
||||
deles[i]->l = NULL;
|
||||
BMEdge *e2 = deles[i];
|
||||
|
||||
if (e2->l != NULL) {
|
||||
printf("%s: eek!\n", __func__);
|
||||
}
|
||||
e2->l = NULL;
|
||||
BM_edge_kill(bm, deles[i]);
|
||||
}
|
||||
|
||||
|
@ -2316,7 +2685,7 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
|
|||
/* validate */
|
||||
l = f->l_first;
|
||||
do {
|
||||
lnext = l->next;
|
||||
lnext = l == l->next ? NULL : l->next;
|
||||
|
||||
if (l->v == l->next->v) {
|
||||
l->prev->next = l->next;
|
||||
|
@ -2327,9 +2696,14 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
|
|||
}
|
||||
|
||||
l->f->len--;
|
||||
|
||||
if (l == l->f->l_first) {
|
||||
l->f->l_first = NULL;
|
||||
}
|
||||
|
||||
bm_kill_only_loop(bm, l);
|
||||
}
|
||||
} while ((l = lnext) != f->l_first);
|
||||
} while (lnext && (l = lnext) != f->l_first);
|
||||
|
||||
if (f->len <= 2) {
|
||||
/* kill face */
|
||||
|
@ -2375,8 +2749,34 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
|
|||
} while ((l = l->next) != f->l_first);
|
||||
}
|
||||
|
||||
JVKE_CHECK_ELEMENT(v_conn);
|
||||
|
||||
for (int step = 0; step < 2; step++) {
|
||||
BMVert *v = step ? v_conn : v_del;
|
||||
BMEdge *e1 = v->e;
|
||||
|
||||
if (e1) {
|
||||
do {
|
||||
JVKE_CHECK_ELEMENT(e1);
|
||||
|
||||
BMLoop *l = e1->l;
|
||||
if (!l) {
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
JVKE_CHECK_ELEMENT(l);
|
||||
JVKE_CHECK_ELEMENT(l->v);
|
||||
JVKE_CHECK_ELEMENT(l->e);
|
||||
JVKE_CHECK_ELEMENT(l->f);
|
||||
} while ((l = l->radial_next) != e1->l);
|
||||
} while ((e1 = BM_DISK_EDGE_NEXT(e1, v)) != v->e);
|
||||
}
|
||||
}
|
||||
|
||||
// printf("v_del: %p, v_conn: %p\n", v_del->e, v_conn->e);
|
||||
if (do_del) {
|
||||
JVKE_CHECK_ELEMENT(v_del);
|
||||
BM_vert_kill(bm, v_del);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "BLI_array.h"
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_hash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
|
@ -131,6 +132,58 @@ typedef struct myiter {
|
|||
//#define DEBUG_LOG_REFCOUNTNG
|
||||
//#define PRINT_LOG_REF_COUNTING
|
||||
|
||||
#ifdef DEBUG_LOG_CALL_STACKS
|
||||
static struct {
|
||||
char tag[1024];
|
||||
} fine_namestack[256] = {0};
|
||||
static int fine_namestack_i = 0;
|
||||
static SmallHash *small_str_hash = NULL;
|
||||
|
||||
# define bm_logstack_head _bm_logstack_head
|
||||
|
||||
# define SET_TRACE(le) (le)->tag = bm_logstack_head()
|
||||
# define GET_TRACE(le) ((le)->tag)
|
||||
|
||||
const char *small_str_get(const char *str)
|
||||
{
|
||||
void **val;
|
||||
uint hash = BLI_hash_string(str);
|
||||
|
||||
if (!small_str_hash) {
|
||||
small_str_hash = MEM_callocN(sizeof(*small_str_hash), "small_str_hash");
|
||||
BLI_smallhash_init(small_str_hash);
|
||||
}
|
||||
|
||||
if (!BLI_smallhash_ensure_p(small_str_hash, (uintptr_t)hash, &val)) {
|
||||
*val = strdup(str);
|
||||
}
|
||||
|
||||
return (const char *)*val;
|
||||
}
|
||||
|
||||
void _bm_logstack_push(const char *name)
|
||||
{
|
||||
fine_namestack_i++;
|
||||
|
||||
strcpy(fine_namestack[fine_namestack_i].tag, fine_namestack[fine_namestack_i - 1].tag);
|
||||
strcat(fine_namestack[fine_namestack_i].tag, ".");
|
||||
strcat(fine_namestack[fine_namestack_i].tag, name);
|
||||
}
|
||||
|
||||
const char *_bm_logstack_head()
|
||||
{
|
||||
return small_str_get(fine_namestack[fine_namestack_i].tag);
|
||||
}
|
||||
|
||||
void _bm_logstack_pop()
|
||||
{
|
||||
fine_namestack_i--;
|
||||
}
|
||||
#else
|
||||
# define SET_TRACE(le)
|
||||
# define GET_TRACE(le) (((void *)le) ? __func__ : __func__)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_LOG_REFCOUNTNG
|
||||
static struct {
|
||||
char tag[4192];
|
||||
|
@ -217,6 +270,12 @@ struct BMLogEntry {
|
|||
GHash *deleted_edges_post; // used for split edges
|
||||
GHash *deleted_faces;
|
||||
|
||||
GHash *topo_modified_edges_pre;
|
||||
GHash *topo_modified_faces_pre;
|
||||
|
||||
GHash *topo_modified_edges_post;
|
||||
GHash *topo_modified_faces_post;
|
||||
|
||||
/* Elements that were not in the previous entry, but are in the
|
||||
* result of this entry */
|
||||
GHash *added_verts;
|
||||
|
@ -316,6 +375,10 @@ typedef struct BMLogVert {
|
|||
char msg[64];
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_LOG_CALL_STACKS
|
||||
const char *tag;
|
||||
#endif
|
||||
|
||||
float co[3];
|
||||
float no[3];
|
||||
char hflag;
|
||||
|
@ -327,6 +390,10 @@ typedef struct BMLogEdge {
|
|||
char msg[64];
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_LOG_CALL_STACKS
|
||||
const char *tag;
|
||||
#endif
|
||||
|
||||
uint v1, v2;
|
||||
char hflag;
|
||||
void *customdata;
|
||||
|
@ -340,6 +407,10 @@ typedef struct {
|
|||
char msg[64];
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_LOG_CALL_STACKS
|
||||
const char *tag;
|
||||
#endif
|
||||
|
||||
uint *v_ids;
|
||||
uint *l_ids;
|
||||
void **customdata;
|
||||
|
@ -353,10 +424,48 @@ typedef struct {
|
|||
void *customdata_res[MAX_FACE_RESERVED];
|
||||
uint v_ids_res[MAX_FACE_RESERVED];
|
||||
uint l_ids_res[MAX_FACE_RESERVED];
|
||||
|
||||
uint id;
|
||||
} BMLogFace;
|
||||
|
||||
/************************* Get/set element IDs ************************/
|
||||
|
||||
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
|
||||
#define logkey_cmp BLI_ghashutil_intcmp
|
||||
|
@ -477,7 +586,7 @@ BMVert *BM_log_id_vert_get(BMLog *log, uint id)
|
|||
/* Get the vertex's unique ID from the log */
|
||||
static uint bm_log_edge_id_get(BMLog *log, BMEdge *e)
|
||||
{
|
||||
return (uint)BM_ELEM_GET_ID(log->bm, e);
|
||||
return (uint)get_edge_id(log->bm, e);
|
||||
}
|
||||
|
||||
/* Get a vertex from its unique ID */
|
||||
|
@ -494,7 +603,7 @@ BMEdge *BM_log_id_edge_get(BMLog *log, uint id)
|
|||
/* Get the face's unique ID from the log */
|
||||
static uint bm_log_face_id_get(BMLog *log, BMFace *f)
|
||||
{
|
||||
return (uint)BM_ELEM_GET_ID(log->bm, f);
|
||||
return (uint)get_face_id(log->bm, f);
|
||||
}
|
||||
|
||||
uint BM_log_vert_id_get(BMLog *log, BMVert *v)
|
||||
|
@ -557,7 +666,7 @@ static void bm_log_face_customdata(BMesh *bm, BMLog *log, BMFace *f, BMLogFace *
|
|||
BMLogEntry *entry = log->current_entry;
|
||||
|
||||
if (!entry || !lf) {
|
||||
printf("bmlog error\n");
|
||||
printf("%s: bmlog error\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -611,6 +720,8 @@ static BMLogVert *bm_log_vert_alloc(BMLog *log,
|
|||
BMLogVert *lv = BLI_mempool_alloc(entry->pool_verts);
|
||||
lv->customdata = NULL;
|
||||
|
||||
SET_TRACE(lv);
|
||||
|
||||
bm_log_vert_bmvert_copy(log, entry, lv, v, -1, log_customdata);
|
||||
|
||||
return lv;
|
||||
|
@ -620,7 +731,7 @@ static void bm_log_edge_bmedge_copy(
|
|||
BMLog *log, BMLogEntry *entry, BMLogEdge *le, BMEdge *e, bool copy_customdata)
|
||||
{
|
||||
if (e->head.htype != BM_EDGE) {
|
||||
printf("%s: e is not an edge; htype: %d\n", __func__, (int)e->head.htype);
|
||||
printf("%s: e is not an edge; htype: %d\n", GET_TRACE(le), (int)e->head.htype);
|
||||
}
|
||||
|
||||
le->v1 = (uint)BM_ELEM_GET_ID(log->bm, e->v1);
|
||||
|
@ -641,6 +752,8 @@ static BMLogEdge *bm_log_edge_alloc(BMLog *log, BMEdge *e, bool log_customdata)
|
|||
BMLogEdge *le = BLI_mempool_alloc(entry->pool_edges);
|
||||
le->customdata = NULL;
|
||||
|
||||
SET_TRACE(le);
|
||||
|
||||
#ifdef DO_LOG_PRINT
|
||||
le->msg[0] = 0;
|
||||
#endif
|
||||
|
@ -657,6 +770,9 @@ 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->id = (uint)BM_ELEM_GET_ID(log->bm, f);
|
||||
|
||||
SET_TRACE(lf);
|
||||
|
||||
bool have_loop_ids = (log->bm->idmap.flag & BM_LOOP);
|
||||
|
||||
|
@ -708,12 +824,12 @@ static void bm_log_verts_unmake_pre(
|
|||
BMVert *v = bm_log_vert_from_id(log, id);
|
||||
|
||||
if (!v) {
|
||||
printf("bm_log error; vertex id: %p\n", key);
|
||||
printf("%s: vertex id: %p\n", GET_TRACE(lv), key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v->head.htype != BM_VERT) {
|
||||
printf("bm_log error; vertex id: %p, type was: %d\n", key, v->head.htype);
|
||||
printf("%s: vertex id: %p, type was: %d\n", GET_TRACE(lv), key, v->head.htype);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -733,20 +849,18 @@ static void bm_log_edges_unmake_pre(
|
|||
{
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, edges) {
|
||||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BMLogEdge *le = BLI_ghashIterator_getValue(&gh_iter);
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
BMEdge *e = bm_log_edge_from_id(log, id);
|
||||
BMEdge *e = bm_log_edge_from_id(log, le->id);
|
||||
|
||||
if (!e) {
|
||||
printf("%s: missing edge; id: %d [%s]\n", __func__, id, GET_MSG(le));
|
||||
printf("%s: missing edge; id: %d [%s]\n", GET_TRACE(le), le->id, GET_MSG(le));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->head.htype != BM_EDGE) {
|
||||
printf("%s: not an edge; edge id: %d, type was: %d [%s]\n",
|
||||
__func__,
|
||||
id,
|
||||
GET_TRACE(le),
|
||||
le->id,
|
||||
e->head.htype,
|
||||
GET_MSG(le));
|
||||
continue;
|
||||
|
@ -767,20 +881,18 @@ static void bm_log_edges_unmake(
|
|||
{
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, edges) {
|
||||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
BMLogEdge *le = BLI_ghashIterator_getValue(&gh_iter);
|
||||
BMEdge *e = bm_log_edge_from_id(log, id);
|
||||
BMEdge *e = bm_log_edge_from_id(log, le->id);
|
||||
|
||||
if (!e) {
|
||||
printf("%s: missing edge; edge id: %d [%s]\n", __func__, id, GET_MSG(le));
|
||||
printf("%s: missing edge; edge id: %d [%s]\n", GET_TRACE(le), le->id, GET_MSG(le));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->head.htype != BM_EDGE) {
|
||||
printf("%s: not an edge; edge id: %d, type: %d [%s]\n",
|
||||
__func__,
|
||||
id,
|
||||
GET_TRACE(le),
|
||||
le->id,
|
||||
e->head.htype,
|
||||
GET_MSG(le));
|
||||
continue;
|
||||
|
@ -798,9 +910,10 @@ static void bm_log_verts_unmake(
|
|||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
BMVert *v = bm_log_vert_from_id(log, id);
|
||||
BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
|
||||
|
||||
if (!v || v->head.htype != BM_VERT) {
|
||||
printf("bmlog error. vertex id: %p\n", key);
|
||||
printf("%s: error, vertex id: %p\n", GET_TRACE(lv), key);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -816,18 +929,16 @@ static void bm_log_faces_unmake(
|
|||
BLI_array_staticdeclare(e_tri, 32);
|
||||
|
||||
GHASH_ITER (gh_iter, faces) {
|
||||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
BMFace *f = bm_log_face_from_id(log, id);
|
||||
BMFace *f = bm_log_face_from_id(log, lf->id);
|
||||
|
||||
if (!f) {
|
||||
printf("bmlog error in %s: missing face %d\n", __func__, id);
|
||||
printf("%s: missing face %d\n", GET_TRACE(lf), lf->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f->head.htype != BM_FACE) {
|
||||
printf("bmlog error in %s: f was not a face, type was: %d\n", __func__, f->head.htype);
|
||||
printf("%s: f was not a face, type was: %d\n", GET_TRACE(lf), f->head.htype);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -906,30 +1017,25 @@ static void bm_log_edges_restore(
|
|||
{
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, edges) {
|
||||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BMLogEdge *le = BLI_ghashIterator_getValue(&gh_iter);
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
|
||||
if (id != le->id) {
|
||||
printf("%s: id differs from stored id in BMLogEdge!\n", __func__);
|
||||
}
|
||||
|
||||
BMVert *v1 = bm_log_vert_from_id(log, le->v1);
|
||||
BMVert *v2 = bm_log_vert_from_id(log, le->v2);
|
||||
|
||||
if (!v1 || !v2) {
|
||||
printf("%s: missing edge verts: %p %p\n", __func__, v1, v2);
|
||||
printf("%s: missing edge verts: %p %p\n", GET_TRACE(le), v1, v2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v1->head.htype != BM_VERT || v2->head.htype != BM_VERT) {
|
||||
printf("%s: edge verts were not verts: %d %d\n", __func__, v1->head.htype, v2->head.htype);
|
||||
printf(
|
||||
"%s: edge verts were not verts: %d %d\n", GET_TRACE(le), v1->head.htype, v2->head.htype);
|
||||
continue;
|
||||
}
|
||||
|
||||
BMEdge *e = BM_edge_exists(v1, v2);
|
||||
if (e) {
|
||||
printf("%s: edge already %d existed\n", __func__, (int)id);
|
||||
printf("%s: edge already %d existed\n", GET_TRACE(le), (int)le->id);
|
||||
bm_free_id(bm, (BMElem *)e);
|
||||
}
|
||||
else {
|
||||
|
@ -944,10 +1050,10 @@ static void bm_log_edges_restore(
|
|||
}
|
||||
#endif
|
||||
|
||||
bm_assign_id(bm, (BMElem *)e, POINTER_AS_UINT(key), false);
|
||||
bm_assign_id(bm, (BMElem *)e, le->id, false);
|
||||
|
||||
if ((uint)BM_ELEM_GET_ID(bm, e) != id) {
|
||||
printf("%s: error assigning id\n", __func__);
|
||||
if ((uint)BM_ELEM_GET_ID(bm, e) != le->id) {
|
||||
printf("%s: error assigning id\n", GET_TRACE(le));
|
||||
}
|
||||
|
||||
if (callbacks) {
|
||||
|
@ -966,7 +1072,6 @@ static void bm_log_faces_restore(
|
|||
bool have_loop_ids = (log->bm->idmap.flag & BM_LOOP);
|
||||
|
||||
GHASH_ITER (gh_iter, faces) {
|
||||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
|
||||
|
||||
BLI_array_clear(vs_tmp);
|
||||
|
@ -994,7 +1099,7 @@ static void bm_log_faces_restore(
|
|||
}
|
||||
|
||||
if (bad) {
|
||||
printf("Undo error! %p\n", v);
|
||||
printf("%s: Undo error! %p\n", GET_TRACE(lf), v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1004,14 +1109,15 @@ static void bm_log_faces_restore(
|
|||
}
|
||||
|
||||
if (v->head.htype != BM_VERT) {
|
||||
printf("vert %d in face %d was not a vertex\n", (int)lf->v_ids[i], POINTER_AS_INT(key));
|
||||
printf(
|
||||
"%s: vert %d in face %d was not a vertex\n", GET_TRACE(lf), (int)lf->v_ids[i], lf->id);
|
||||
continue;
|
||||
}
|
||||
BLI_array_append(vs_tmp, v);
|
||||
}
|
||||
|
||||
if ((int)BLI_array_len(vs_tmp) < 2) {
|
||||
printf("severely malformed face %d in %s\n", POINTER_AS_INT(key), __func__);
|
||||
printf("%s: severely malformed face %d in %s\n", GET_TRACE(lf), lf->id, __func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1041,7 +1147,7 @@ static void bm_log_faces_restore(
|
|||
CustomData_bmesh_copy_data(&entry->pdata, &bm->pdata, lf->customdata_f, &f->head.data);
|
||||
}
|
||||
|
||||
bm_assign_id(bm, (BMElem *)f, POINTER_AS_UINT(key), false);
|
||||
bm_assign_id(bm, (BMElem *)f, lf->id, false);
|
||||
|
||||
BMLoop *l = f->l_first;
|
||||
int j = 0;
|
||||
|
@ -1077,12 +1183,12 @@ static void bm_log_vert_values_swap(
|
|||
BMVert *v = bm_log_vert_from_id(log, id);
|
||||
|
||||
if (!v) {
|
||||
printf("missing vert in bmlog! %d", id);
|
||||
printf("%s: missing vert in bmlog! %d", GET_TRACE(lv), id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v->head.htype != BM_VERT) {
|
||||
printf("not a vertex: %d\n", v->head.htype);
|
||||
printf("%s: not a vertex: %d\n", GET_TRACE(lv), v->head.htype);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1119,10 +1225,8 @@ static void bm_log_edge_values_swap(
|
|||
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, edges) {
|
||||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BMLogEdge *le = BLI_ghashIterator_getValue(&gh_iter);
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
BMEdge *e = bm_log_edge_from_id(log, id);
|
||||
BMEdge *e = bm_log_edge_from_id(log, le->id);
|
||||
|
||||
SWAP(char, e->head.hflag, le->hflag);
|
||||
|
||||
|
@ -1156,10 +1260,8 @@ static void bm_log_face_values_swap(BMLog *log,
|
|||
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, faces) {
|
||||
void *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
BMFace *f = bm_log_face_from_id(log, id);
|
||||
BMFace *f = bm_log_face_from_id(log, lf->id);
|
||||
|
||||
swap_v3_v3(f->no, lf->no);
|
||||
SWAP(char, f->head.hflag, lf->hflag);
|
||||
|
@ -1226,6 +1328,11 @@ static BMLogEntry *bm_log_entry_create(BMLogEntryType type)
|
|||
entry->deleted_edges_post = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
entry->deleted_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
|
||||
entry->topo_modified_edges_pre = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
entry->topo_modified_edges_post = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
entry->topo_modified_faces_pre = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
entry->topo_modified_faces_post = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
|
||||
entry->added_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
entry->added_edges = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
entry->added_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
|
||||
|
@ -1263,6 +1370,11 @@ static void bm_log_entry_free_direct(BMLogEntry *entry)
|
|||
BLI_ghash_free(entry->deleted_edges_post, NULL, NULL);
|
||||
BLI_ghash_free(entry->deleted_faces, NULL, NULL);
|
||||
|
||||
BLI_ghash_free(entry->topo_modified_edges_pre, NULL, NULL);
|
||||
BLI_ghash_free(entry->topo_modified_edges_post, NULL, NULL);
|
||||
BLI_ghash_free(entry->topo_modified_faces_pre, NULL, NULL);
|
||||
BLI_ghash_free(entry->topo_modified_faces_post, NULL, NULL);
|
||||
|
||||
BLI_ghash_free(entry->added_verts, NULL, NULL);
|
||||
BLI_ghash_free(entry->added_edges, NULL, NULL);
|
||||
BLI_ghash_free(entry->added_faces, NULL, NULL);
|
||||
|
@ -2203,13 +2315,17 @@ static void bm_log_undo_intern(
|
|||
bm_log_verts_unmake_pre(bm, log, entry->added_verts, entry, callbacks);
|
||||
|
||||
bm_log_faces_unmake(bm, log, entry->added_faces, entry, callbacks);
|
||||
bm_log_faces_unmake(bm, log, entry->topo_modified_faces_post, entry, callbacks);
|
||||
bm_log_edges_unmake(bm, log, entry->topo_modified_edges_post, entry, callbacks);
|
||||
bm_log_edges_unmake(bm, log, entry->added_edges, entry, callbacks);
|
||||
bm_log_verts_unmake(bm, log, entry->added_verts, entry, callbacks);
|
||||
|
||||
/* Restore deleted verts and faces */
|
||||
bm_log_verts_restore(bm, log, entry->deleted_verts, entry, callbacks);
|
||||
bm_log_edges_restore(bm, log, entry->deleted_edges, entry, callbacks);
|
||||
bm_log_edges_restore(bm, log, entry->topo_modified_edges_pre, entry, callbacks);
|
||||
bm_log_faces_restore(bm, log, entry->deleted_faces, entry, callbacks);
|
||||
bm_log_faces_restore(bm, log, entry->topo_modified_faces_pre, entry, callbacks);
|
||||
|
||||
/* Restore vertex coordinates, mask, and hflag */
|
||||
bm_log_vert_values_swap(bm, log, entry->modified_verts, entry, callbacks);
|
||||
|
@ -2306,13 +2422,17 @@ static void bm_log_redo_intern(
|
|||
bm_log_verts_unmake_pre(bm, log, entry->deleted_verts, entry, callbacks);
|
||||
|
||||
bm_log_faces_unmake(bm, log, entry->deleted_faces, entry, callbacks);
|
||||
bm_log_faces_unmake(bm, log, entry->topo_modified_faces_pre, entry, callbacks);
|
||||
bm_log_edges_unmake(bm, log, entry->topo_modified_edges_pre, entry, callbacks);
|
||||
bm_log_edges_unmake(bm, log, entry->deleted_edges, entry, callbacks);
|
||||
bm_log_verts_unmake(bm, log, entry->deleted_verts, entry, callbacks);
|
||||
|
||||
/* Restore previously added verts and faces */
|
||||
bm_log_verts_restore(bm, log, entry->added_verts, entry, callbacks);
|
||||
bm_log_edges_restore(bm, log, entry->added_edges, entry, callbacks);
|
||||
bm_log_edges_restore(bm, log, entry->topo_modified_edges_post, entry, callbacks);
|
||||
bm_log_faces_restore(bm, log, entry->added_faces, entry, callbacks);
|
||||
bm_log_faces_restore(bm, log, entry->topo_modified_faces_post, entry, callbacks);
|
||||
|
||||
bm_log_edges_unmake(bm, log, entry->deleted_edges_post, entry, callbacks);
|
||||
|
||||
|
@ -2415,7 +2535,7 @@ void BM_log_edge_before_modified(BMLog *log, BMEdge *e, bool log_customdata)
|
|||
{
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
BMLogEdge *le;
|
||||
uint e_id = (uint)BM_ELEM_GET_ID(log->bm, e);
|
||||
uint e_id = (uint)get_edge_id(log->bm, e);
|
||||
void *key = POINTER_FROM_UINT(e_id);
|
||||
void **val_p;
|
||||
|
||||
|
@ -2433,9 +2553,10 @@ void BM_log_edge_before_modified(BMLog *log, BMEdge *e, bool log_customdata)
|
|||
*/
|
||||
void BM_log_edge_added(BMLog *log, BMEdge *e)
|
||||
{
|
||||
// return; // XXX
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogEdge *le;
|
||||
uint e_id = (uint)BM_ELEM_GET_ID(log->bm, e);
|
||||
uint e_id = (uint)get_edge_id(log->bm, e);
|
||||
void *key = POINTER_FROM_UINT(e_id);
|
||||
void **val = NULL;
|
||||
|
||||
|
@ -2449,12 +2570,16 @@ void BM_log_edge_added(BMLog *log, BMEdge *e)
|
|||
}
|
||||
|
||||
*val = le;
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
/* Log a new vertex as added to the BMesh
|
||||
*/
|
||||
void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogVert *lv;
|
||||
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
|
||||
void *key = POINTER_FROM_UINT(v_id);
|
||||
|
@ -2463,6 +2588,8 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
|
|||
|
||||
lv = bm_log_vert_alloc(log, v, -1, true);
|
||||
log_ghash_insert(log, log->current_entry->added_verts, key, lv);
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
/* Log a face before it is modified
|
||||
|
@ -2472,7 +2599,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 = (uint)BM_ELEM_GET_ID(log->bm, f);
|
||||
uint f_id = (uint)get_face_id(log->bm, f);
|
||||
void *key = POINTER_FROM_UINT(f_id);
|
||||
|
||||
// LOGPRINT("key %d\n", (int)key);
|
||||
|
@ -2496,7 +2623,7 @@ bool BM_log_has_vert(BMLog *log, BMVert *v)
|
|||
|
||||
bool BM_log_has_edge(BMLog *log, BMEdge *e)
|
||||
{
|
||||
int id = BM_ELEM_GET_ID(log->bm, e);
|
||||
int id = get_edge_id(log->bm, e);
|
||||
|
||||
bool ret = BLI_ghash_haskey(log->current_entry->added_edges, POINTER_FROM_INT(id));
|
||||
ret = ret || BLI_ghash_haskey(log->current_entry->deleted_edges, POINTER_FROM_INT(id));
|
||||
|
@ -2508,7 +2635,7 @@ bool BM_log_has_edge(BMLog *log, BMEdge *e)
|
|||
|
||||
bool BM_log_has_face(BMLog *log, BMFace *f)
|
||||
{
|
||||
int id = BM_ELEM_GET_ID(log->bm, f);
|
||||
int id = get_face_id(log->bm, f);
|
||||
|
||||
bool ret = BLI_ghash_haskey(log->current_entry->added_faces, POINTER_FROM_INT(id));
|
||||
ret = ret || BLI_ghash_haskey(log->current_entry->deleted_faces, POINTER_FROM_INT(id));
|
||||
|
@ -2525,8 +2652,10 @@ bool BM_log_has_face(BMLog *log, BMFace *f)
|
|||
*/
|
||||
void BM_log_face_added(BMLog *log, BMFace *f)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogFace *lf;
|
||||
uint f_id = (uint)BM_ELEM_GET_ID(log->bm, f);
|
||||
uint f_id = (uint)get_face_id(log->bm, f);
|
||||
void *key = POINTER_FROM_UINT(f_id);
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
@ -2535,8 +2664,115 @@ void BM_log_face_added(BMLog *log, BMFace *f)
|
|||
log_ghash_insert(log, log->current_entry->added_faces, key, lf);
|
||||
|
||||
bm_log_face_customdata(log->bm, log, f, lf);
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
void BM_log_face_topo_pre(BMLog *log, BMFace *f)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint f_id = (uint)get_face_id(log->bm, f);
|
||||
void *key = POINTER_FROM_UINT(f_id);
|
||||
|
||||
void **val = NULL;
|
||||
|
||||
BLI_ghash_remove(entry->topo_modified_faces_post, key, NULL, NULL);
|
||||
|
||||
if (!BLI_ghash_ensure_p(entry->topo_modified_faces_pre, key, &val)) {
|
||||
BMLogFace *lf;
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
||||
lf = bm_log_face_alloc(log, f);
|
||||
bm_log_face_customdata(log->bm, log, f, lf);
|
||||
|
||||
*val = (void *)lf;
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
void BM_log_face_topo_post(BMLog *log, BMFace *f)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint f_id = (uint)get_face_id(log->bm, f);
|
||||
void *key = POINTER_FROM_UINT(f_id);
|
||||
BMLogFace *lf;
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
||||
lf = bm_log_face_alloc(log, f);
|
||||
bm_log_face_customdata(log->bm, log, f, lf);
|
||||
|
||||
void **val = NULL;
|
||||
|
||||
if (BLI_ghash_ensure_p(entry->topo_modified_faces_post, key, &val)) {
|
||||
BMLogFace *lf_old = (BMLogFace *)*val;
|
||||
*lf_old = *lf;
|
||||
BLI_mempool_free(entry->pool_faces, lf);
|
||||
}
|
||||
else {
|
||||
*val = (void *)lf;
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
void BM_log_edge_topo_pre(BMLog *log, BMEdge *e)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint f_id = (uint)get_edge_id(log->bm, e);
|
||||
void *key = POINTER_FROM_UINT(f_id);
|
||||
|
||||
void **val = NULL;
|
||||
|
||||
BLI_ghash_remove(entry->topo_modified_edges_post, key, NULL, NULL);
|
||||
|
||||
if (!BLI_ghash_ensure_p(entry->topo_modified_edges_pre, key, &val)) {
|
||||
BMLogEdge *le;
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
||||
le = bm_log_edge_alloc(log, e, true);
|
||||
|
||||
*val = (void *)le;
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
void BM_log_edge_topo_post(BMLog *log, BMEdge *e)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint f_id = (uint)get_edge_id(log->bm, e);
|
||||
void *key = POINTER_FROM_UINT(f_id);
|
||||
BMLogEdge *le;
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
||||
le = bm_log_edge_alloc(log, e, true);
|
||||
|
||||
void **val = NULL;
|
||||
|
||||
if (BLI_ghash_ensure_p(entry->topo_modified_edges_post, key, &val)) {
|
||||
BMLogEdge *le_old = (BMLogEdge *)*val;
|
||||
*le_old = *le;
|
||||
BLI_mempool_free(entry->pool_edges, le);
|
||||
}
|
||||
else {
|
||||
*val = (void *)le;
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
/* Log a vertex as removed from the BMesh
|
||||
*
|
||||
* A couple things can happen here:
|
||||
|
@ -2555,6 +2791,8 @@ void BM_log_face_added(BMLog *log, BMFace *f)
|
|||
*/
|
||||
void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint v_id = (uint)BM_ELEM_GET_ID(log->bm, v);
|
||||
void *key = POINTER_FROM_UINT(v_id);
|
||||
|
@ -2584,16 +2822,25 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
void BM_log_edge_removed_post(BMLog *log, BMEdge *e)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint e_id = (uint)BM_ELEM_GET_ID(log->bm, e);
|
||||
uint e_id = (uint)get_edge_id(log->bm, e);
|
||||
void *key = POINTER_FROM_UINT(e_id);
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
||||
BLI_ghash_remove(entry->topo_modified_edges_post, key, NULL, NULL);
|
||||
if (BLI_ghash_haskey(entry->topo_modified_edges_pre, key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (1) { //! log_ghash_remove(log, entry->added_edges, key, NULL, NULL)) {
|
||||
BMLogEdge *le, *le_mod;
|
||||
void **val;
|
||||
|
@ -2630,6 +2877,8 @@ void BM_log_edge_removed_post(BMLog *log, BMEdge *e)
|
|||
bm_log_edge_customdata(log->bm, log, entry, e, le);
|
||||
#endif
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2638,13 +2887,28 @@ e is assigned a new ID.
|
|||
*/
|
||||
BMVert *BM_log_edge_split_do(BMLog *log, BMEdge *e, BMVert *v, BMEdge **newe, float t)
|
||||
{
|
||||
#if 0
|
||||
bm_logstack_push();
|
||||
|
||||
bm_log_message("edge split");
|
||||
|
||||
BMEdge *tmp = NULL;
|
||||
if (!newe) {
|
||||
newe = &tmp;
|
||||
}
|
||||
|
||||
BM_log_edge_topo_pre(log, e);
|
||||
BMVert *newv = BM_edge_split(log->bm, e, v, newe, t);
|
||||
|
||||
BM_log_edge_topo_post(log, e);
|
||||
BM_log_edge_added(log, *newe);
|
||||
|
||||
BM_log_vert_added(log, newv, -1);
|
||||
|
||||
bm_logstack_pop();
|
||||
|
||||
return newv;
|
||||
|
||||
#else
|
||||
#if 0
|
||||
BMEdge *tmp = NULL;
|
||||
if (!newe) {
|
||||
newe = &tmp;
|
||||
|
@ -2689,22 +2953,33 @@ BMVert *BM_log_edge_split_do(BMLog *log, BMEdge *e, BMVert *v, BMEdge **newe, fl
|
|||
bm_log_message(" esplit: add new edge %d", nid);
|
||||
BM_log_edge_added(log, *newe);
|
||||
|
||||
bm_logstack_pop();
|
||||
|
||||
return newv;
|
||||
#endif
|
||||
}
|
||||
|
||||
void BM_log_edge_removed(BMLog *log, BMEdge *e)
|
||||
{
|
||||
bm_logstack_push();
|
||||
|
||||
if (e->head.htype != BM_EDGE) {
|
||||
bm_logstack_pop();
|
||||
printf("%s: e is not an edge; htype: %d\n", __func__, (int)e->head.htype);
|
||||
return;
|
||||
}
|
||||
|
||||
// return; // XXX
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint e_id = (uint)BM_ELEM_GET_ID(log->bm, e);
|
||||
uint e_id = (uint)get_edge_id(log->bm, e);
|
||||
void *key = POINTER_FROM_UINT(e_id);
|
||||
|
||||
BLI_ghash_remove(entry->topo_modified_edges_post, key, NULL, NULL);
|
||||
if (BLI_ghash_haskey(entry->topo_modified_edges_pre, key)) {
|
||||
bm_logstack_pop();
|
||||
return;
|
||||
}
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
||||
if (!log_ghash_remove(log, entry->added_edges, key, NULL, NULL)) {
|
||||
|
@ -2742,6 +3017,8 @@ void BM_log_edge_removed(BMLog *log, BMEdge *e)
|
|||
bm_log_edge_customdata(log->bm, log, entry, e, le);
|
||||
#endif
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
/* Log a face as removed from the BMesh
|
||||
|
@ -2760,11 +3037,19 @@ void BM_log_edge_removed(BMLog *log, BMEdge *e)
|
|||
void BM_log_face_removed(BMLog *log, BMFace *f)
|
||||
{
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
uint f_id = (uint)BM_ELEM_GET_ID(log->bm, f);
|
||||
uint f_id = (uint)get_face_id(log->bm, f);
|
||||
void *key = POINTER_FROM_UINT(f_id);
|
||||
|
||||
bm_logstack_push();
|
||||
|
||||
LOGPRINT("key %d\n", (int)key);
|
||||
|
||||
BLI_ghash_remove(entry->topo_modified_faces_post, key, NULL, NULL);
|
||||
if (BLI_ghash_haskey(entry->topo_modified_faces_pre, key)) {
|
||||
bm_logstack_pop();
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
|
@ -2796,6 +3081,8 @@ void BM_log_face_removed(BMLog *log, BMFace *f)
|
|||
|
||||
*val = lf;
|
||||
}
|
||||
|
||||
bm_logstack_pop();
|
||||
}
|
||||
|
||||
/* Log all vertices/faces in the BMesh as added */
|
||||
|
|
|
@ -46,6 +46,20 @@ typedef struct BMLogCallbacks {
|
|||
void *userdata;
|
||||
} BMLogCallbacks;
|
||||
|
||||
//#define DEBUG_LOG_CALL_STACKS
|
||||
|
||||
#ifdef DEBUG_LOG_CALL_STACKS
|
||||
void _bm_logstack_pop();
|
||||
const char *_bm_logstack_head();
|
||||
void _bm_logstack_push(const char *name);
|
||||
# define bm_logstack_push() _bm_logstack_push(__func__)
|
||||
# define bm_logstack_pop() _bm_logstack_pop()
|
||||
#else
|
||||
# define bm_logstack_push()
|
||||
# define bm_logstack_head ""
|
||||
# define bm_logstack_pop()
|
||||
#endif
|
||||
|
||||
/* Allocate and initialize a new BMLog */
|
||||
BMLog *BM_log_create(BMesh *bm, int cd_sculpt_vert);
|
||||
void BM_log_set_cd_offsets(BMLog *log, int cd_sculpt_vert);
|
||||
|
@ -160,3 +174,15 @@ int BM_log_entry_size(BMLogEntry *entry);
|
|||
bool BM_log_has_vert(BMLog *log, BMVert *v);
|
||||
bool BM_log_has_edge(BMLog *log, BMEdge *e);
|
||||
bool BM_log_has_face(BMLog *log, BMFace *f);
|
||||
|
||||
/*Log an edge before changing its topological connections*/
|
||||
void BM_log_edge_topo_pre(BMLog *log, BMEdge *f);
|
||||
|
||||
/*Log an edge after changing its topological connections*/
|
||||
void BM_log_edge_topo_post(BMLog *log, BMEdge *f);
|
||||
|
||||
/*Log a face before changing its topological connections*/
|
||||
void BM_log_face_topo_pre(BMLog *log, BMFace *f);
|
||||
|
||||
/*Log a face after changing its topological connections*/
|
||||
void BM_log_face_topo_post(BMLog *log, BMFace *f);
|
||||
|
|
Loading…
Reference in New Issue