Sculpt: shapekey fixes

* Fixed the completely broken shapekey conversion
  in BM_mesh_bm_from_me; this bug is most likely
  in master as well.
* Note that, while shapekeys now work in dyntopo
  it does not represent a complete sculpt layers
  implementation; the layers are still stored in
  world space.
* The motivation for fixing this was to keep
  dyntopo from destroying shapekey data, which
  was the only form of custom attributes it didn't
  support.
* That was because shapekeys were never being converted
  to custom attributes for bmesh to begin with, the
  conversion code was quite broken.

In addition to all this, this commit also has
a fix dyntopo collapse fixes.
This commit is contained in:
Joseph Eagar 2021-10-12 15:18:59 -07:00
parent fe03543e8d
commit ffa62ecb60
12 changed files with 182 additions and 64 deletions

View File

@ -207,7 +207,7 @@ places in rna_engine_codebase are relevent:
"used for DynTopo", 1.0f, 0.001f, 5.0f, 0.01f, 2.0f, false, BRUSH_CHANNEL_INHERIT)
MAKE_BOOL(dyntopo_disable_smooth, "Disable Dyntopo Smooth", "Disable the small amount of smoothing dyntopo applies to improve numerical stability", false)
MAKE_FLOAT_EX(projection, "Projection", "Amount of volume preserving projection", 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, false)
MAKE_FLOAT_EX(autosmooth_projection, "Auto-Smooth Projection", "Amount of volume preserving projection", 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, false)
MAKE_FLOAT_EX(autosmooth_projection, "Auto-Smooth Projection", "Amount of volume preserving projection for autosmooth", 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, false)
MAKE_FLOAT_EX(topology_rake_projection, "Rake Projection", "Amount of volume preserving projection", 0.975f, 0.0f, 1.0f, 0.0f, 1.0f, false)
MAKE_FLOAT(fset_slide, "Face Set Projection", "Stick face set boundaries to surface of mesh", 1.0f, 0.0f, 1.0f)
MAKE_FLOAT(boundary_smooth, "Boundary Smooth", "Smooth hard boundaries", 0.0f, 0.0f, 1.0f)

View File

@ -41,12 +41,13 @@
#define USE_NEW_SPLIT
#define SCULPTVERT_SMOOTH_BOUNDARY \
(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY)
(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY | \
SCULPTVERT_SEAM_BOUNDARY)
#define SCULPTVERT_ALL_BOUNDARY \
(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY | \
SCULPTVERT_SEAM_BOUNDARY)
#define SCULPTVERT_SMOOTH_CORNER \
(SCULPTVERT_CORNER | SCULPTVERT_FSET_CORNER | SCULPTVERT_SHARP_CORNER)
(SCULPTVERT_CORNER | SCULPTVERT_FSET_CORNER | SCULPTVERT_SHARP_CORNER | SCULPTVERT_SEAM_CORNER)
#define SCULPTVERT_ALL_CORNER \
(SCULPTVERT_CORNER | SCULPTVERT_FSET_CORNER | SCULPTVERT_SHARP_CORNER | SCULPTVERT_SEAM_CORNER)
@ -175,7 +176,7 @@ static void pbvh_split_edges(struct EdgeQueueContext *eq_ctx,
int totedge,
bool ignore_isolated_edges);
void bm_log_message(const char *fmt, ...);
void pbvh_bmesh_check_nodes_simple(PBVH *pbvh);
static void edge_queue_create_local(struct EdgeQueueContext *eq_ctx,
PBVH *pbvh,
const float center[3],
@ -288,7 +289,7 @@ static void fix_mesh(PBVH *pbvh, BMesh *bm)
printf("done fixing mesh.\n");
}
//#define CHECKMESH
#define CHECKMESH
//#define TEST_INVALID_NORMALS
#ifndef CHECKMESH
@ -3963,6 +3964,15 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
#endif
BMEdge *e2;
for (int step = 0; step < 2; step++) {
BMVert *v_step = step ? v_del : v_conn;
e2 = v_step->e;
do {
e2->head.hflag &= ~tag;
} while ((e2 = BM_DISK_EDGE_NEXT(e2, v_step)) != v_step->e);
}
for (int step = 0; step < 2; step++) {
BMVert *v_step = step ? v_del : v_conn;
@ -3972,12 +3982,12 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
do {
BMLoop *l = e2->l;
e2->head.hflag |= tag;
if (e2 != e) {
if (e2 != e && !(e2->head.hflag & tag)) {
BM_log_edge_removed(pbvh->bm_log, e2);
}
e2->head.hflag |= tag;
if (!l) {
continue; // edge will be killed later
}
@ -3997,6 +4007,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
BLI_ghash_insert(deleted_verts, (void *)v_del, NULL);
pbvh_bmesh_check_nodes(pbvh);
if (!snap) {
float co[3];
@ -4019,6 +4031,25 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
copy_v3_v3(v_conn->co, co);
}
e2 = v_conn->e;
do {
BMLoop *l = e2->l;
if (!l) {
continue;
}
do {
BMLoop *l2 = l->f->l_first;
do {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l2->v);
mv->flag |= mupdateflag;
} while ((l2 = l2->next) != l->f->l_first);
} while ((l = l->radial_next) != e2->l);
} while ((e2 = BM_DISK_EDGE_NEXT(e2, v_conn)) != v_conn->e);
pbvh_bmesh_check_nodes(pbvh);
for (int i = 0; i < BLI_array_len(delvs); i++) {
BMVert *v = delvs[i];
BMEdge *e = v->e;

View File

@ -1148,6 +1148,7 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me,
.calc_face_normal = false,
.add_key_index = add_key_index,
.use_shapekey = true,
.create_shapekey_layers = true,
.active_shapekey = ob->shapenr,
});
}

View File

@ -28,6 +28,7 @@
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@ -85,6 +86,7 @@ void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
BMesh *SCULPT_dyntopo_empty_bmesh();
void SCULPT_undo_ensure_bmlog(Object *ob);
void SCULPT_update_customdata_refs(SculptSession *ss);
static void init_mdyntopo_layer(SculptSession *ss, PBVH *pbvh, int totvert);
@ -1401,7 +1403,7 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
if (ss->bm) {
if (ob->data) {
Mesh *me = BKE_object_get_original_mesh(ob);
// Mesh *me = BKE_object_get_original_mesh(ob);
BM_mesh_bm_to_me(
NULL,
@ -1415,6 +1417,7 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
*/
.copy_temp_cdlayers = false,
.ignore_mesh_id_layers = false,
.update_shapekey_indices = true,
.cd_mask_extra = CD_MASK_MESH_ID | CD_MASK_DYNTOPO_VERT
}));
@ -1852,6 +1855,58 @@ static void sculpt_update_object(Depsgraph *depsgraph,
}
BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, totvert);
if (ss->bm && me->key && ob->shapenr != ss->bm->shapenr) {
KeyBlock *actkey = BLI_findlink(&me->key->block, ss->bm->shapenr - 1);
KeyBlock *newkey = BLI_findlink(&me->key->block, ob->shapenr - 1);
if (!actkey) {
printf("%s: failed to find active shapekey\n", __func__);
}
if (!newkey) {
printf("%s: failed to find new active shapekey\n", __func__);
}
if (actkey && newkey) {
int cd_co1 = CustomData_get_named_layer_index(&ss->bm->vdata, CD_SHAPEKEY, actkey->name);
int cd_co2 = CustomData_get_named_layer_index(&ss->bm->vdata, CD_SHAPEKEY, newkey->name);
if (cd_co1 == -1) { // non-recoverable error
printf("%s: failed to find active shapekey in customdata.\n", __func__);
return;
}
else if (cd_co2 == -1) {
BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_SHAPEKEY, newkey->name);
cd_co2 = CustomData_get_named_layer_index(&ss->bm->vdata, CD_SHAPEKEY, newkey->name);
SCULPT_update_customdata_refs(ss);
}
cd_co1 = ss->bm->vdata.layers[cd_co1].offset;
cd_co2 = ss->bm->vdata.layers[cd_co2].offset;
BMVert *v;
BMIter iter;
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
float *co1 = BM_ELEM_CD_GET_VOID_P(v, cd_co1);
float *co2 = BM_ELEM_CD_GET_VOID_P(v, cd_co2);
copy_v3_v3(co1, v->co);
copy_v3_v3(v->co, co2);
}
ss->bm->shapenr = ob->shapenr;
if (ss->pbvh) {
PBVHNode **nodes;
int totnode;
BKE_pbvh_get_nodes(ss->pbvh, PBVH_Leaf, &nodes, &totnode);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update(nodes[i]);
BKE_pbvh_node_mark_update_tri_area(nodes[i]);
}
}
}
}
}
void BKE_sculpt_update_object_before_eval(Object *ob)
@ -2433,7 +2488,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
}
}
else if (BKE_pbvh_type(pbvh) == PBVH_BMESH) {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
// Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
SCULPT_dynamic_topology_sync_layers(ob, BKE_object_get_original_mesh(ob));
}
@ -2452,8 +2507,6 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
Mesh *mesh_orig = BKE_object_get_original_mesh(ob);
bool is_dyntopo = (mesh_orig->flag & ME_SCULPT_DYNAMIC_TOPOLOGY);
void SCULPT_update_customdata_refs(SculptSession * ss);
if (is_dyntopo) {
BMesh *bm = SCULPT_dyntopo_empty_bmesh();
@ -2467,6 +2520,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
.active_shapekey = ob->shapenr,
.ignore_id_layers = false,
.copy_temp_cdlayers = true,
.create_shapekey_layers = true,
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
SCULPT_dyntopo_node_layers_add(ob->sculpt);

View File

@ -83,9 +83,9 @@ static void _debugprint(const char *fmt, ...)
va_end(args);
}
#ifdef PBVH_BMESH_DEBUG
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;
@ -94,24 +94,22 @@ void pbvh_bmesh_check_nodes_simple(PBVH *pbvh)
continue;
}
TGSET_ITER (f,node->bm_faces) {
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) {
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
for (int i = 0; i < pbvh->totnode; i++) {
PBVHNode *node = pbvh->nodes + i;
@ -123,12 +121,12 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
BMVert *v;
BMIter iter;
BM_ITER_MESH (v,&iter,pbvh->bm,BM_VERTS_OF_MESH) {
int ni = BM_ELEM_CD_GET_INT(v,pbvh->cd_vert_node_offset);
BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) {
int ni = BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset);
if (ni >= 0 && !v->e || !v->e->l) {
if (ni >= 0 && (!v->e || !v->e->l)) {
_debugprint("wire vert had node reference\n");
BM_ELEM_CD_SET_INT(v,pbvh->cd_vert_node_offset,DYNTOPO_NODE_NONE);
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
}
if (ni < -1 || ni >= pbvh->totnode) {
@ -146,21 +144,21 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
continue;
}
if (!BLI_table_gset_haskey(node->bm_unique_verts,v)) {
if (!BLI_table_gset_haskey(node->bm_unique_verts, v)) {
_debugprint("vert not in node->bm_unique_verts\n");
}
if (BLI_table_gset_haskey(node->bm_other_verts,v)) {
if (BLI_table_gset_haskey(node->bm_other_verts, v)) {
_debugprint("vert in node->bm_other_verts");
}
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert,v);
BKE_pbvh_bmesh_check_valence(pbvh,(SculptVertRef) { .i = (intptr_t)v });
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
BKE_pbvh_bmesh_check_valence(pbvh, (SculptVertRef){.i = (intptr_t)v});
if (BM_vert_edge_count(v) != mv->valence) {
_debugprint("cached vertex valence mismatch; old: %d, should be: %d\n",
mv->valence,
BM_vert_edge_count(v));
mv->valence,
BM_vert_edge_count(v));
}
}
@ -182,57 +180,60 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
continue;
}
TGSET_ITER (v,node->bm_unique_verts) {
int ni = BM_ELEM_CD_GET_INT(v,pbvh->cd_vert_node_offset);
TGSET_ITER (v, node->bm_unique_verts) {
int ni = BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset);
if (ni != i) {
if (ni >= 0 && ni < pbvh->totnode) {
PBVHNode *node2 = pbvh->nodes + ni;
_debugprint("v node offset is wrong, %d\n",
!node2->bm_unique_verts ? 0 :
BLI_table_gset_haskey(node2->bm_unique_verts,v));
} else {
!node2->bm_unique_verts ? 0 :
BLI_table_gset_haskey(node2->bm_unique_verts, v));
}
else {
_debugprint("v node offset is wrong\n");
}
}
if (!v || v->head.htype != BM_VERT) {
_debugprint("corruption in pbvh! bm_unique_verts\n");
} else if (BLI_table_gset_haskey(node->bm_other_verts,v)) {
}
else if (BLI_table_gset_haskey(node->bm_other_verts, v)) {
_debugprint("v in both unique and other verts\n");
}
}
TGSET_ITER_END;
TGSET_ITER (f,node->bm_faces) {
TGSET_ITER (f, node->bm_faces) {
if (!f || f->head.htype != BM_FACE) {
_debugprint("corruption in pbvh! bm_faces\n");
continue;
}
int ni = BM_ELEM_CD_GET_INT(f,pbvh->cd_face_node_offset);
int ni = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
if (pbvh->nodes + ni != node) {
_debugprint("face in multiple nodes!\n");
}
}
TGSET_ITER_END;
TGSET_ITER (v,node->bm_other_verts) {
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)) {
}
else if (BLI_table_gset_haskey(node->bm_unique_verts, v)) {
_debugprint("v in both unique and other verts\n");
}
}
TGSET_ITER_END;
}
#endif
}
void pbvh_bmesh_pbvh_bmesh_check_nodes(PBVH *pbvh)
{
pbvh_bmesh_check_nodes(pbvh);
}
#endif
/** \} */

View File

@ -332,8 +332,17 @@ BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *pbvh, const BMFace *key)
return ni >= 0 ? pbvh->nodes + ni : NULL;
// return &pbvh->nodes[pbvh_bmesh_node_index_from_face(pbvh, key)];
}
bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index);
#ifdef PBVH_BMESH_DEBUG
void pbvh_bmesh_check_nodes(PBVH *pbvh);
void pbvh_bmesh_check_nodes_simple(PBVH *pbvh);
#else
# define pbvh_bmesh_check_nodes(pbvh)
# define pbvh_bmesh_check_nodes_simple(pbvh)
#endif
void bke_pbvh_insert_face_finalize(PBVH *pbvh, BMFace *f, const int ni);
void bke_pbvh_insert_face(PBVH *pbvh, struct BMFace *f);
void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,

View File

@ -2208,6 +2208,11 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
do {
BMLoop *l = e2->l;
if (!l) {
continue;
}
do {
if (!BM_ELEM_API_FLAG_TEST(l->f, tag)) {
BM_ELEM_API_FLAG_ENABLE(l->f, tag);

View File

@ -799,7 +799,7 @@ static void bm_log_verts_unmake(
uint id = POINTER_AS_UINT(key);
BMVert *v = bm_log_vert_from_id(log, id);
if (!v) {
if (!v || v->head.htype != BM_VERT) {
printf("bmlog error. vertex id: %p\n", key);
continue;
}
@ -1205,7 +1205,7 @@ static void bm_log_full_mesh_intern(BMesh *bm, BMLog *log, BMLogEntry *entry)
entry->full_copy_mesh = BKE_mesh_from_bmesh_nomain(
bm,
(&(struct BMeshToMeshParams){.update_shapekey_indices = false,
(&(struct BMeshToMeshParams){.update_shapekey_indices = true,
.calc_object_remap = false,
.cd_mask_extra = cd_mask_extra,
.copy_temp_cdlayers = true,
@ -1866,9 +1866,9 @@ static void full_copy_load(BMesh *bm, BMLog *log, BMLogEntry *entry)
entry->full_copy_mesh,
(&(struct BMeshFromMeshParams){.calc_face_normal = false,
.add_key_index = false,
.use_shapekey = false,
.active_shapekey = -1,
.use_shapekey = true,
.active_shapekey = bm->shapenr,
.create_shapekey_layers = true,
.cd_mask_extra = cd_mask_extra,
.copy_temp_cdlayers = true,
.ignore_id_layers = false}));
@ -2150,9 +2150,9 @@ static void full_copy_swap(BMesh *bm, BMLog *log, BMLogEntry *entry)
entry->full_copy_mesh,
(&(struct BMeshFromMeshParams){.calc_face_normal = false,
.add_key_index = false,
.use_shapekey = false,
.active_shapekey = -1,
.use_shapekey = true,
.active_shapekey = bm->shapenr,
.create_shapekey_layers = true,
.cd_mask_extra = cd_mask_extra,
.copy_temp_cdlayers = true,
.ignore_id_layers = false}));

View File

@ -280,9 +280,9 @@ void BM_enter_multires_space(Object *ob, BMesh *bm, int space)
*/
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));
@ -418,7 +418,7 @@ void BM_mesh_bm_from_me(Object *ob,
*/
BLI_assert(!CustomData_has_layer(&me->vdata, CD_SHAPEKEY));
}
if (is_new == false) {
if (is_new == false && CustomData_has_layer(&me->vdata, CD_SHAPEKEY)) {
tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY));
}
const float(**shape_key_table)[3] = tot_shape_keys ?
@ -439,7 +439,7 @@ void BM_mesh_bm_from_me(Object *ob,
}
if (tot_shape_keys) {
if (is_new) {
if (is_new || params->create_shapekey_layers) {
/* Check if we need to generate unique ids for the shape-keys.
* This also exists in the file reading code, but is here for a sanity check. */
if (!me->key->uidgen) {
@ -457,7 +457,7 @@ void BM_mesh_bm_from_me(Object *ob,
if (actkey && actkey->totelem == me->totvert) {
keyco = params->use_shapekey ? actkey->data : NULL;
if (is_new) {
if (is_new || params->create_shapekey_layers) {
bm->shapenr = params->active_shapekey;
}
}
@ -465,9 +465,13 @@ void BM_mesh_bm_from_me(Object *ob,
for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) {
if (is_new) {
CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, CD_ASSIGN, NULL, 0, block->name);
int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
bm->vdata.layers[j].uid = block->uid;
}
else {
BM_data_layer_add_named(bm, &bm->vdata, CD_SHAPEKEY, block->name);
}
int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
bm->vdata.layers[j].uid = block->uid;
shape_key_table[i] = (const float(*)[3])block->data;
}
}
@ -521,12 +525,18 @@ void BM_mesh_bm_from_me(Object *ob,
const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
const int cd_shape_key_offset = tot_shape_keys ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) :
-1;
int *cd_shape_key_offset = tot_shape_keys ?
MEM_mallocN(sizeof(int) * tot_shape_keys, "cd_shape_key_offset") :
NULL;
const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ?
CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) :
-1;
for (int i = 0; i < tot_shape_keys; i++) {
int idx = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
cd_shape_key_offset[i] = bm->vdata.layers[idx].offset;
}
vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__);
for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
@ -569,9 +579,9 @@ void BM_mesh_bm_from_me(Object *ob,
/* Set shape-key data. */
if (tot_shape_keys) {
float(*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset);
for (int j = 0; j < tot_shape_keys; j++, co_dst++) {
copy_v3_v3(*co_dst, shape_key_table[j][i]);
for (int j = 0; j < tot_shape_keys; j++) {
float *co_dst = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset[j]);
copy_v3_v3(co_dst, shape_key_table[j][i]);
}
}
}
@ -911,6 +921,8 @@ void BM_mesh_bm_from_me(Object *ob,
}
}
}
MEM_SAFE_FREE(cd_shape_key_offset);
}
/**

View File

@ -34,6 +34,9 @@ void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag);
char BM_mesh_cd_flag_from_bmesh(BMesh *bm);
struct BMeshFromMeshParams {
/* automatically create shapekey layers */
uint create_shapekey_layers : 1;
uint calc_face_normal : 1;
/* add a vertex CD_SHAPE_KEYINDEX layer */
uint add_key_index : 1;

View File

@ -822,6 +822,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
.use_shapekey = true,
.create_shapekey_layers = true,
.active_shapekey = ob->shapenr,
}));
}

View File

@ -186,7 +186,7 @@ static bool test_swap_v3_v3(float a[3], float b[3])
return false;
}
void pbvh_bmesh_check_nodes(PBVH *pbvh);
// void pbvh_bmesh_check_nodes(PBVH *pbvh);
static bool sculpt_undo_restore_deformed(
const SculptSession *ss, SculptUndoNode *unode, int uindex, int oindex, float coord[3])
@ -667,7 +667,7 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
SCULPT_update_customdata_refs(ss);
pbvh_bmesh_check_nodes(ss->pbvh);
// pbvh_bmesh_check_nodes(ss->pbvh);
if (unode->applied) {
BM_log_undo(ss->bm, ss->bm_log, &callbacks, dyntopop_node_idx_layer_id);
@ -692,9 +692,9 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
}
}
pbvh_bmesh_check_nodes(ss->pbvh);
// pbvh_bmesh_check_nodes(ss->pbvh);
BKE_pbvh_bmesh_regen_node_verts(ss->pbvh);
pbvh_bmesh_check_nodes(ss->pbvh);
// pbvh_bmesh_check_nodes(ss->pbvh);
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw);
@ -706,7 +706,7 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
BKE_pbvh_bmesh_after_stroke(ss->pbvh, true);
}
pbvh_bmesh_check_nodes(ss->pbvh);
// pbvh_bmesh_check_nodes(ss->pbvh);
}
else {
SCULPT_pbvh_clear(ob);
@ -742,6 +742,7 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode, bool is_
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
.use_shapekey = true,
.create_shapekey_layers = true,
.active_shapekey = ob->shapenr,
}));