Sculpt: Add operator to store a limit surface manually

This commit is contained in:
Pablo Dobarro 2021-04-27 23:54:04 +02:00
parent d0407b0ed5
commit d1cf59e547
4 changed files with 55 additions and 0 deletions

View File

@ -879,6 +879,9 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
col.separator()
col.operator("sculpt.set_limit_surface")
class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel):
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)

View File

@ -581,6 +581,9 @@ typedef struct SculptSession {
/* This is freed with the PBVH, so it is always in sync with the mesh. */
SculptPersistentBase *persistent_base;
float (*limit_surface)[3];
SculptVertexInfo vertex_info;
SculptFakeNeighbors fake_neighbors;

View File

@ -1429,6 +1429,7 @@ static void sculptsession_free_pbvh(Object *object)
MEM_SAFE_FREE(ss->vemap_mem);
MEM_SAFE_FREE(ss->persistent_base);
MEM_SAFE_FREE(ss->limit_surface);
MEM_SAFE_FREE(ss->preview_vert_index_list);
ss->preview_vert_index_count = 0;
@ -1499,6 +1500,8 @@ void BKE_sculptsession_free(Object *ob)
MEM_SAFE_FREE(ss->deform_cos);
MEM_SAFE_FREE(ss->deform_imats);
MEM_SAFE_FREE(ss->limit_surface);
if (ss->pose_ik_chain_preview) {
for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights);

View File

@ -237,6 +237,10 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3]
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_BMESH:
if (ss->limit_surface) {
copy_v3_v3(r_co, ss->limit_surface[index]);
break;
}
copy_v3_v3(r_co, SCULPT_vertex_co_get(ss, index));
break;
case PBVH_GRIDS: {
@ -10038,11 +10042,53 @@ static void SCULPT_OT_reset_brushes(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
static int sculpt_set_limit_surface_exec(bContext *C, wmOperator *UNUSED(op))
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
SculptSession *ss = ob->sculpt;
if (!ss) {
return OPERATOR_FINISHED;
}
SCULPT_vertex_random_access_ensure(ss);
MEM_SAFE_FREE(ss->limit_surface);
const int totvert = SCULPT_vertex_count_get(ss);
ss->limit_surface = MEM_mallocN(sizeof(float) * 3 * totvert,
"limit surface");
for (int i = 0; i < totvert; i++) {
SCULPT_neighbor_coords_average(ss, ss->limit_surface[i], i);
}
return OPERATOR_FINISHED;
}
static void SCULPT_OT_set_limit_surface(wmOperatorType *ot)
{
/* Identifiers. */
ot->name = "Set Limit Surface";
ot->idname = "SCULPT_OT_set_limit_surface";
ot->description = "Calculates and stores a limit surface from the current mesh";
/* API callbacks. */
ot->exec = sculpt_set_limit_surface_exec;
ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void ED_operatortypes_sculpt(void)
{
WM_operatortype_append(SCULPT_OT_brush_stroke);
WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
WM_operatortype_append(SCULPT_OT_set_persistent_base);
WM_operatortype_append(SCULPT_OT_set_limit_surface);
WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle);
WM_operatortype_append(SCULPT_OT_optimize);
WM_operatortype_append(SCULPT_OT_symmetrize);