WIP: Mesh: Improve and simplify modifier evaluation logic #119968

Draft
Hans Goudey wants to merge 33 commits from HooglyBoogly/blender:fix-modifier-eval-geometry-set-improve into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
5 changed files with 40 additions and 22 deletions
Showing only changes of commit 54f94093cc - Show all commits

View File

@ -450,6 +450,7 @@ class CurvesEditHints {
/**
* Evaluated positions for the points in #curves_orig. If this is empty, the positions from the
* evaluated #Curves should be used if possible.
* \todo Use implicit sharing
*/
std::optional<Array<float3>> positions;
/**

View File

@ -35,10 +35,9 @@ struct Scene;
* Through this, you get access to both the edit #BMesh, its tessellation,
* and various data that doesn't belong in the #BMesh struct itself
* (mostly related to mesh evaluation).
*
* #Mesh.runtime.edit_mesh stores a pointer to this structure.
*/
struct BMEditMesh {
/* Always owned by an original mesh in edit mode. */
BMesh *bm;
/**

View File

@ -168,6 +168,13 @@ struct GeometrySet {
return static_cast<Component &>(this->get_component_for_write(Component::static_type));
}
GeometryComponentPtr get_component_ptr(GeometryComponent::Type component_type) const;
template<typename Component> ImplicitSharingPtr<Component> get_component_ptr() const
{
BLI_STATIC_ASSERT(is_geometry_component_v<Component>, "");
return static_cast<ImplicitSharingPtr<Component>>(components_(Component::static_type));
}
/**
* Get the component of the given type. Might return null if the component does not exist yet.
*/
@ -428,11 +435,11 @@ struct GeometrySet {
* Retrieve the pointer to a component without creating it if it does not exist,
* unlike #get_component_for_write.
*/
GeometryComponent *get_component_ptr(GeometryComponent::Type type);
template<typename Component> Component *get_component_ptr()
GeometryComponent *get_component_for_write_ptr(GeometryComponent::Type type);
template<typename Component> Component *get_component_for_write_ptr()
{
BLI_STATIC_ASSERT(is_geometry_component_v<Component>, "");
return static_cast<Component *>(get_component_ptr(Component::static_type));
return static_cast<Component *>(get_component_for_write_ptr(Component::static_type));
}
};

View File

@ -938,6 +938,8 @@ static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
return {};
}
namespace blender::bke {
static Mesh *mesh_copy_with_edit_data(const Mesh &mesh)
{
Mesh *result = BKE_mesh_copy_for_eval(&mesh);
@ -953,16 +955,28 @@ static Mesh *mesh_copy_with_edit_data(const Mesh &mesh)
return result;
}
static void save_cage_mesh(GeometrySet &geometry_set)
{
if (const Mesh *mesh = geometry_set.get_mesh()) {
auto &edit_data = geometry_set.get_component_for_write<GeometryComponentEditData>();
if (!edit_data.mesh_edit_hints_) {
edit_data.mesh_edit_hints_ = std::make_unique<MeshEditHints>();
}
BLI_assert(!edit_data.mesh_edit_hints_->mesh_cage);
edit_data.mesh_edit_hints_->mesh_cage = geometry_set.get_component_ptr<MeshComponent>();
}
}
} // namespace blender::bke
static GeometrySet editbmesh_calc_modifiers(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
BMEditMesh *em_input,
const CustomData_MeshMasks *dataMask,
/* return args */
Mesh **r_cage)
const CustomData_MeshMasks *dataMask)
{
using namespace blender::bke;
const Mesh *mesh_input = static_cast<const Mesh *>(ob->data);
Mesh *mesh_cage = nullptr;
/* Mesh with constructive modifiers but no deformation applied. Tracked
* along with final mesh if undeformed / orco coordinates are requested
@ -996,8 +1010,8 @@ static GeometrySet editbmesh_calc_modifiers(Depsgraph *depsgraph,
BKE_mesh_wrapper_from_editmesh(em_input, &final_datamask, mesh_input));
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true);
if (r_cage && cageIndex == -1) {
mesh_cage = mesh_copy_with_edit_data(*geometry_set.get_mesh());
if (cageIndex == -1) {
save_cage_mesh(geometry_set);
}
/* The mesh from edit mode should not have any original index layers already, since those
@ -1100,8 +1114,8 @@ static GeometrySet editbmesh_calc_modifiers(Depsgraph *depsgraph,
modifier_modify_mesh_and_geometry_set(md, mectx, geometry_set);
}
if (r_cage && i == cageIndex) {
mesh_cage = mesh_copy_with_edit_data(*geometry_set.get_mesh());
if (i == cageIndex) {
blender::bke::save_cage_mesh(geometry_set);
}
}
@ -1121,16 +1135,15 @@ static GeometrySet editbmesh_calc_modifiers(Depsgraph *depsgraph,
}
/* Compute normals. */
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
editbmesh_calc_modifier_final_normals_or_defer(mesh);
if (geometry_set.get_mesh()->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
editbmesh_calc_modifier_final_normals_or_defer(mesh);
}
}
if (mesh_cage) {
editbmesh_calc_modifier_final_normals_or_defer(mesh_cage);
}
if (r_cage) {
*r_cage = mesh_cage;
}
return geometry_set;
}
@ -1192,9 +1205,7 @@ static void editbmesh_build_data(Depsgraph *depsgraph,
CustomData_MeshMasks *dataMask)
{
Mesh *mesh = static_cast<Mesh *>(obedit->data);
Mesh *me_cage;
GeometrySet geometry_set = editbmesh_calc_modifiers(
depsgraph, scene, obedit, em, dataMask, &me_cage);
GeometrySet geometry_set = editbmesh_calc_modifiers(depsgraph, scene, obedit, em, dataMask);
Mesh *mesh_final = geometry_set.get_mesh_for_write();

View File

@ -133,7 +133,7 @@ GeometryComponent &GeometrySet::get_component_for_write(GeometryComponent::Type
return const_cast<GeometryComponent &>(*component_ptr);
}
GeometryComponent *GeometrySet::get_component_ptr(GeometryComponent::Type type)
GeometryComponent *GeometrySet::get_component_for_write_ptr(GeometryComponent::Type type)
{
if (this->has(type)) {
return &this->get_component_for_write(type);