diff options
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/include/ED_sculpt.h | 3 | ||||
-rw-r--r-- | source/blender/editors/object/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/object/object_intern.h | 3 | ||||
-rw-r--r-- | source/blender/editors/object/object_ops.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_remesh.c | 159 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 36 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_intern.h | 19 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_undo.c | 131 |
8 files changed, 305 insertions, 49 deletions
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index 86e108a26c6..034e002f86a 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -45,4 +45,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C, /* sculpt_undo.c */ void ED_sculpt_undosys_type(struct UndoType *ut); +void ED_sculpt_undo_geometry_begin(struct Object *ob); +void ED_sculpt_undo_geometry_end(struct Object *ob); + #endif /* __ED_SCULPT_H__ */ diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index eaef9313431..2490f88b5eb 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -57,6 +57,7 @@ set(SRC object_ops.c object_random.c object_relations.c + object_remesh.c object_select.c object_shader_fx.c object_shapekey.c diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index e697c25b37f..4b369c10e4d 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -279,6 +279,9 @@ void OBJECT_OT_bake(wmOperatorType *ot); /* object_random.c */ void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot); +/* object_remesh.c */ +void OBJECT_OT_voxel_remesh(struct wmOperatorType *ot); + /* object_transfer_data.c */ void OBJECT_OT_data_transfer(struct wmOperatorType *ot); void OBJECT_OT_datalayout_transfer(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index b653c7fa70c..38c06319450 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -257,6 +257,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_hide_view_clear); WM_operatortype_append(OBJECT_OT_hide_view_set); WM_operatortype_append(OBJECT_OT_hide_collection); + + WM_operatortype_append(OBJECT_OT_voxel_remesh); } void ED_operatormacros_object(void) diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c new file mode 100644 index 00000000000..a7e7256757d --- /dev/null +++ b/source/blender/editors/object/object_remesh.c @@ -0,0 +1,159 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation + * All rights reserved. + */ + +/** \file + * \ingroup edobj + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <float.h> +#include <ctype.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_mesh_types.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_customdata.h" +#include "BKE_remesh.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + +#include "ED_mesh.h" +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_sculpt.h" +#include "ED_undo.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "WM_message.h" +#include "WM_toolsystem.h" + +#include "object_intern.h" // own include + +static bool object_remesh_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + + if (BKE_object_is_in_editmode(ob)) { + CTX_wm_operator_poll_msg_set(C, "The voxel remesher cannot run from edit mode."); + return false; + } + + if (ob->mode == OB_MODE_SCULPT && ob->sculpt->bm) { + CTX_wm_operator_poll_msg_set(C, "The voxel remesher cannot run with dyntopo activated."); + } + + return ED_operator_object_active_editable_mesh(C); +} + +static int voxel_remesh_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + Main *bmain = CTX_data_main(C); + + Mesh *mesh = ob->data; + Mesh *new_mesh; + + if (mesh->remesh_voxel_size <= 0.0f) { + BKE_report(op->reports, RPT_ERROR, "Voxel remesher cannot run with a voxel size of 0.0."); + return OPERATOR_CANCELLED; + } + + if (ob->mode == OB_MODE_SCULPT) { + ED_sculpt_undo_geometry_begin(ob); + } + + new_mesh = BKE_remesh_voxel_to_mesh_nomain(mesh, mesh->remesh_voxel_size); + + if (!new_mesh) { + return OPERATOR_CANCELLED; + } + + Mesh *obj_mesh_copy; + if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) { + obj_mesh_copy = BKE_mesh_new_nomain_from_template(mesh, mesh->totvert, 0, 0, 0, 0); + CustomData_copy( + &mesh->vdata, &obj_mesh_copy->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, mesh->totvert); + for (int i = 0; i < mesh->totvert; i++) { + copy_v3_v3(obj_mesh_copy->mvert[i].co, mesh->mvert[i].co); + } + } + + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + BKE_mesh_free(new_mesh); + + if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) { + BKE_remesh_reproject_paint_mask(mesh, obj_mesh_copy); + BKE_mesh_free(obj_mesh_copy); + } + + if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) { + BKE_mesh_smooth_flag_set(ob, true); + } + + if (ob->mode == OB_MODE_SCULPT) { + ED_sculpt_undo_geometry_end(ob); + } + + BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_voxel_remesh(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Voxel Remesh"; + ot->description = + "Calculates a new manifold mesh based on the volume of the current mesh. All data layers " + "will be lost"; + ot->idname = "OBJECT_OT_voxel_remesh"; + + /* api callbacks */ + ot->poll = object_remesh_poll; + ot->exec = voxel_remesh_exec; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 285e6aff7d0..efaac6e97cf 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5695,31 +5695,19 @@ static void sculpt_dynamic_topology_disable_ex( CustomData_free(&me->pdata, me->totpoly); /* Copy over stored custom data */ - me->totvert = unode->bm_enter_totvert; - me->totloop = unode->bm_enter_totloop; - me->totpoly = unode->bm_enter_totpoly; - me->totedge = unode->bm_enter_totedge; + me->totvert = unode->geom_totvert; + me->totloop = unode->geom_totloop; + me->totpoly = unode->geom_totpoly; + me->totedge = unode->geom_totedge; me->totface = 0; - CustomData_copy(&unode->bm_enter_vdata, - &me->vdata, - CD_MASK_MESH.vmask, - CD_DUPLICATE, - unode->bm_enter_totvert); - CustomData_copy(&unode->bm_enter_edata, - &me->edata, - CD_MASK_MESH.emask, - CD_DUPLICATE, - unode->bm_enter_totedge); - CustomData_copy(&unode->bm_enter_ldata, - &me->ldata, - CD_MASK_MESH.lmask, - CD_DUPLICATE, - unode->bm_enter_totloop); - CustomData_copy(&unode->bm_enter_pdata, - &me->pdata, - CD_MASK_MESH.pmask, - CD_DUPLICATE, - unode->bm_enter_totpoly); + CustomData_copy( + &unode->geom_vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, unode->geom_totvert); + CustomData_copy( + &unode->geom_edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, unode->geom_totedge); + CustomData_copy( + &unode->geom_ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, unode->geom_totloop); + CustomData_copy( + &unode->geom_pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, unode->geom_totpoly); BKE_mesh_update_customdata_pointers(me, false); } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index e66e1c49685..e646accf108 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -63,6 +63,7 @@ typedef enum { SCULPT_UNDO_DYNTOPO_BEGIN, SCULPT_UNDO_DYNTOPO_END, SCULPT_UNDO_DYNTOPO_SYMMETRIZE, + SCULPT_UNDO_GEOMETRY, } SculptUndoType; typedef struct SculptUndoNode { @@ -94,18 +95,20 @@ typedef struct SculptUndoNode { /* bmesh */ struct BMLogEntry *bm_entry; bool applied; - CustomData bm_enter_vdata; - CustomData bm_enter_edata; - CustomData bm_enter_ldata; - CustomData bm_enter_pdata; - int bm_enter_totvert; - int bm_enter_totedge; - int bm_enter_totloop; - int bm_enter_totpoly; /* shape keys */ char shapeName[sizeof(((KeyBlock *)0))->name]; + /* geometry modification operations and bmesh enter data */ + CustomData geom_vdata; + CustomData geom_edata; + CustomData geom_ldata; + CustomData geom_pdata; + int geom_totvert; + int geom_totedge; + int geom_totloop; + int geom_totpoly; + size_t undo_size; } SculptUndoNode; diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index d4c97faa0a6..3a3487227a3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -44,6 +44,7 @@ #include "BKE_ccg.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_multires.h" #include "BKE_paint.h" #include "BKE_key.h" @@ -425,6 +426,32 @@ static void sculpt_undo_bmesh_restore_end(bContext *C, } } +static void sculpt_undo_geometry_restore(SculptUndoNode *unode, Object *ob) +{ + Mesh *me; + sculpt_pbvh_clear(ob); + me = ob->data; + CustomData_free(&me->vdata, me->totvert); + CustomData_free(&me->edata, me->totedge); + CustomData_free(&me->fdata, me->totface); + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); + me->totvert = unode->geom_totvert; + me->totedge = unode->geom_totedge; + me->totloop = unode->geom_totloop; + me->totpoly = unode->geom_totpoly; + me->totface = 0; + CustomData_copy( + &unode->geom_vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, unode->geom_totvert); + CustomData_copy( + &unode->geom_edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, unode->geom_totedge); + CustomData_copy( + &unode->geom_ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, unode->geom_totloop); + CustomData_copy( + &unode->geom_pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, unode->geom_totpoly); + BKE_mesh_update_customdata_pointers(me, false); +} + /* Handle all dynamic-topology updates * * Returns true if this was a dynamic-topology undo step, otherwise @@ -442,7 +469,6 @@ static int sculpt_undo_bmesh_restore(bContext *C, case SCULPT_UNDO_DYNTOPO_END: sculpt_undo_bmesh_restore_end(C, unode, ob, ss); return true; - default: if (ss->bm_log) { sculpt_undo_bmesh_restore_generic(C, unode, ob, ss); @@ -480,6 +506,24 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); + if (lb->first) { + unode = lb->first; + if (unode->type == SCULPT_UNDO_GEOMETRY) { + if (unode->applied) { + sculpt_undo_geometry_restore(unode->next, ob); + unode->next->applied = true; + unode->applied = false; + } + else { + sculpt_undo_geometry_restore(unode, ob); + unode->next->applied = false; + unode->applied = true; + } + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask); + return; + } + } + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask); if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss)) { @@ -487,6 +531,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase } for (unode = lb->first; unode; unode = unode->next) { + if (!STREQ(unode->idname, ob->id.name)) { continue; } @@ -530,6 +575,8 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: BLI_assert(!"Dynamic topology should've already been handled"); break; + case SCULPT_UNDO_GEOMETRY: + break; } } @@ -617,17 +664,17 @@ static void sculpt_undo_free_list(ListBase *lb) BM_log_entry_drop(unode->bm_entry); } - if (unode->bm_enter_totvert) { - CustomData_free(&unode->bm_enter_vdata, unode->bm_enter_totvert); + if (unode->geom_totvert) { + CustomData_free(&unode->geom_vdata, unode->geom_totvert); } - if (unode->bm_enter_totedge) { - CustomData_free(&unode->bm_enter_edata, unode->bm_enter_totedge); + if (unode->geom_totedge) { + CustomData_free(&unode->geom_edata, unode->geom_totedge); } - if (unode->bm_enter_totloop) { - CustomData_free(&unode->bm_enter_ldata, unode->bm_enter_totloop); + if (unode->geom_totloop) { + CustomData_free(&unode->geom_ldata, unode->geom_totloop); } - if (unode->bm_enter_totpoly) { - CustomData_free(&unode->bm_enter_pdata, unode->bm_enter_totpoly); + if (unode->geom_totpoly) { + CustomData_free(&unode->geom_pdata, unode->geom_totpoly); } MEM_freeN(unode); @@ -743,6 +790,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: BLI_assert(!"Dynamic topology should've already been handled"); + case SCULPT_UNDO_GEOMETRY: break; } @@ -824,6 +872,36 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode) BKE_pbvh_vertex_iter_end; } +static SculptUndoNode *sculpt_undo_geometry_push(Object *ob, SculptUndoType type) +{ + UndoSculpt *usculpt = sculpt_undo_get_nodes(); + Mesh *me = ob->data; + bool applied; + + SculptUndoNode *unode = usculpt->nodes.first; + /* Store the original mesh in the first node, modifications in the second */ + applied = unode != NULL; + + unode = MEM_callocN(sizeof(*unode), __func__); + + BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname)); + unode->type = type; + unode->applied = applied; + + CustomData_copy(&me->vdata, &unode->geom_vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, me->totvert); + CustomData_copy(&me->edata, &unode->geom_edata, CD_MASK_MESH.emask, CD_DUPLICATE, me->totedge); + CustomData_copy(&me->ldata, &unode->geom_ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, me->totloop); + CustomData_copy(&me->pdata, &unode->geom_pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, me->totpoly); + unode->geom_totvert = me->totvert; + unode->geom_totedge = me->totedge; + unode->geom_totloop = me->totloop; + unode->geom_totpoly = me->totpoly; + + BLI_addtail(&usculpt->nodes, unode); + + return unode; +} + static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, SculptUndoType type) { UndoSculpt *usculpt = sculpt_undo_get_nodes(); @@ -852,17 +930,17 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt * (converting polys to triangles) that the BMLog can't * fully restore from */ CustomData_copy( - &me->vdata, &unode->bm_enter_vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, me->totvert); + &me->vdata, &unode->geom_vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, me->totvert); CustomData_copy( - &me->edata, &unode->bm_enter_edata, CD_MASK_MESH.emask, CD_DUPLICATE, me->totedge); + &me->edata, &unode->geom_edata, CD_MASK_MESH.emask, CD_DUPLICATE, me->totedge); CustomData_copy( - &me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, me->totloop); + &me->ldata, &unode->geom_ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, me->totloop); CustomData_copy( - &me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, me->totpoly); - unode->bm_enter_totvert = me->totvert; - unode->bm_enter_totedge = me->totedge; - unode->bm_enter_totloop = me->totloop; - unode->bm_enter_totpoly = me->totpoly; + &me->pdata, &unode->geom_pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, me->totpoly); + unode->geom_totvert = me->totvert; + unode->geom_totedge = me->totedge; + unode->geom_totloop = me->totloop; + unode->geom_totpoly = me->totpoly; unode->bm_entry = BM_log_entry_add(ss->bm_log); BM_log_all_added(ss->bm, ss->bm_log); @@ -906,6 +984,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: + case SCULPT_UNDO_GEOMETRY: break; } } @@ -928,6 +1007,11 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType BLI_thread_unlock(LOCK_CUSTOM1); return unode; } + else if (type == SCULPT_UNDO_GEOMETRY) { + unode = sculpt_undo_geometry_push(ob, type); + BLI_thread_unlock(LOCK_CUSTOM1); + return unode; + } else if ((unode = sculpt_undo_get_node(node))) { BLI_thread_unlock(LOCK_CUSTOM1); return unode; @@ -967,6 +1051,7 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: BLI_assert(!"Dynamic topology should've already been handled"); + case SCULPT_UNDO_GEOMETRY: break; } @@ -1163,6 +1248,18 @@ static void sculpt_undosys_step_free(UndoStep *us_p) sculpt_undo_free_list(&us->data.nodes); } +void ED_sculpt_undo_geometry_begin(struct Object *ob) +{ + sculpt_undo_push_begin("voxel remesh"); + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY); +} + +void ED_sculpt_undo_geometry_end(struct Object *ob) +{ + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY); + sculpt_undo_push_end(); +} + /* Export for ED_undo_sys. */ void ED_sculpt_undosys_type(UndoType *ut) { |