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

Draft
Hans Goudey wants to merge 19 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.
19 changed files with 348 additions and 447 deletions

View File

@ -681,7 +681,7 @@ void BKE_armature_deform_coords_with_editmesh(const Object *ob_arm,
int deformflag,
float (*vert_coords_prev)[3],
const char *defgrp_name,
BMEditMesh *em_target);
const BMEditMesh *em_target);
/** \} */

View File

@ -423,7 +423,7 @@ void BKE_curve_deform_coords_with_editmesh(const Object *ob_curve,
int defgrp_index,
short flag,
short defaxis,
BMEditMesh *em_target);
const BMEditMesh *em_target);
/**
* \param orco: Input vec and orco = local coord in curve space

View File

@ -40,6 +40,7 @@ struct Scene;
* #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));
}
};
@ -675,6 +682,25 @@ class VolumeComponent : public GeometryComponent {
static constexpr inline GeometryComponent::Type static_type = Type::Volume;
};
struct MeshEditHints {
/**
* Mesh created by object evaluation. It only has leading deformation modifiers applied.
*
* \todo This should use a similar system to #CurvesEditHints storing just an array for the
* deformed positions, but for historical reasons we copy the whole mesh.
*/
ImplicitSharingPtr<MeshComponent> mesh_deform;
/**
* Evaluated mesh cage in edit mode.
*
* \note When the mesh's `runtime->deformed_only` is true, its vertex positions and other
* geometry arrays will be aligned the edit-mesh. Otherwise the #CD_ORIGINDEX custom-data should
* be used to map the cage geometry back to the original indices, see
* #eModifierTypeFlag_SupportsMapping.
*/
ImplicitSharingPtr<MeshComponent> mesh_cage;
};
/**
* When the original data is in some edit mode, we want to propagate some additional information
* through object evaluation. This information can be used by edit modes to support working on
@ -696,6 +722,8 @@ class GeometryComponentEditData final : public GeometryComponent {
*/
std::unique_ptr<GreasePencilEditHints> grease_pencil_edit_hints_;
std::unique_ptr<MeshEditHints> mesh_edit_hints_;
GeometryComponentEditData();
GeometryComponentPtr copy() const final;

View File

@ -106,6 +106,6 @@ void BKE_lattice_deform_coords_with_editmesh(const Object *ob_lattice,
short flag,
const char *defgrp_name,
float fac,
BMEditMesh *em_target);
const BMEditMesh *em_target);
/** \} */

View File

@ -223,7 +223,7 @@ struct ModifierTypeInfo {
*/
void (*deform_verts_EM)(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
const BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions);
@ -578,7 +578,7 @@ void BKE_modifier_deform_verts(ModifierData *md,
void BKE_modifier_deform_vertsEM(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
const BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions);

View File

@ -84,22 +84,6 @@ struct ObjectRuntime {
*/
GeometrySet *geometry_set_eval = nullptr;
/**
* Mesh structure created during object evaluation.
* It has deformation only modifiers applied on it.
*/
Mesh *mesh_deform_eval = nullptr;
/**
* Evaluated mesh cage in edit mode.
*
* \note When the mesh's `runtime->deformed_only` is true, the meshes vertex positions
* and other geometry arrays will be aligned the edit-mesh. Otherwise the #CD_ORIGINDEX
* custom-data should be used to map the cage geometry back to the original indices, see
* #eModifierTypeFlag_SupportsMapping.
*/
Mesh *editmesh_eval_cage = nullptr;
/**
* Original grease pencil bGPdata pointer, before object->data was changed to point
* to gpd_eval.

View File

@ -88,8 +88,12 @@ using blender::bke::MeshComponent;
# define ASSERT_IS_VALID_MESH(mesh)
#endif
namespace blender::bke {
static void mesh_init_origspace(Mesh *mesh);
}
/* -------------------------------------------------------------------- */
static float *dm_getVertArray(DerivedMesh *dm)
@ -237,7 +241,7 @@ void DM_release(DerivedMesh *dm)
MEM_SAFE_FREE(dm->face_offsets);
}
void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *mesh, KeyBlock *kb)
void BKE_mesh_runtime_eval_to_meshkey(const Mesh *me_deformed, Mesh *mesh, KeyBlock *kb)
{
/* Just a shallow wrapper around #BKE_keyblock_convert_from_mesh,
* that ensures both evaluated mesh and original one has same number of vertices. */
@ -463,6 +467,8 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval)
mesh_eval->runtime->edit_mesh = mesh_input->runtime->edit_mesh;
}
namespace blender::bke {
/**
* Modifies the given mesh and geometry set. The mesh is not passed as part of the mesh component
* in the \a geometry_set input, it is only passed in \a input_mesh and returned in the return
@ -471,56 +477,30 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval)
* The purpose of the geometry set is to store all geometry components that are generated
* by modifiers to allow outputting non-mesh data from modifiers.
*/
static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
const ModifierEvalContext &mectx,
Mesh *input_mesh,
GeometrySet &geometry_set)
static void modifier_modify_mesh_and_geometry_set(ModifierData *md,
const ModifierEvalContext &mectx,
GeometrySet &geometry_set)
{
Mesh *mesh_output = nullptr;
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
if (mti->modify_geometry_set == nullptr) {
mesh_output = BKE_modifier_modify_mesh(md, &mectx, input_mesh);
if (mti->modify_geometry_set) {
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
BKE_mesh_wrapper_ensure_mdata(mesh);
}
mti->modify_geometry_set(md, &mectx, &geometry_set);
}
else {
/* For performance reasons, this should be called by the modifier and/or nodes themselves at
* some point. */
BKE_mesh_wrapper_ensure_mdata(input_mesh);
/* Replace only the mesh rather than the whole component, because the entire #MeshComponent
* might have been replaced by data from a different object in the node tree, which means the
* component contains vertex group name data for that object that should not be removed. */
geometry_set.replace_mesh(input_mesh, GeometryOwnershipType::Editable);
/* Let the modifier change the geometry set. */
mti->modify_geometry_set(md, &mectx, &geometry_set);
/* Release the mesh from the geometry set again. */
if (geometry_set.has<MeshComponent>()) {
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
if (mesh_component.get() != input_mesh) {
/* Make sure the mesh component actually owns the mesh before taking over ownership. */
mesh_component.ensure_owns_direct_data();
}
mesh_output = mesh_component.release();
}
/* Need to ensure that non-mesh data is also owned by the geometry set. Otherwise it might be
* freed while there is still a reference to it in the geometry. */
geometry_set.ensure_owns_direct_data();
/* Return an empty mesh instead of null. */
if (mesh_output == nullptr) {
mesh_output = BKE_mesh_new_nomain(0, 0, 0, 0);
BKE_mesh_copy_parameters_for_eval(mesh_output, input_mesh);
}
Mesh *new_mesh = BKE_modifier_modify_mesh(md, &mectx, geometry_set.get_mesh_for_write());
geometry_set.replace_mesh(new_mesh);
}
return mesh_output;
if (!geometry_set.has_mesh()) {
geometry_set.replace_mesh(BKE_mesh_new_nomain(0, 0, 0, 0));
}
}
static void set_rest_position(Mesh &mesh)
{
using namespace blender;
using namespace blender::bke;
BKE_mesh_wrapper_ensure_mdata(&mesh);
MutableAttributeAccessor attributes = mesh.attributes_for_write();
const AttributeReader positions = attributes.lookup<float3>("position");
attributes.remove("rest_position");
@ -538,31 +518,38 @@ static void set_rest_position(Mesh &mesh)
}
}
static void mesh_calc_modifiers(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const bool use_deform,
const bool need_mapping,
const CustomData_MeshMasks *dataMask,
const bool use_cache,
const bool allow_shared_mesh,
/* return args */
Mesh **r_deform,
Mesh **r_final,
GeometrySet **r_geometry_set)
static MeshEditHints &geometry_mesh_edit_hints_ensure(GeometrySet &geometry)
{
using namespace blender::bke;
/* Input mesh shouldn't be modified. */
Mesh *mesh_input = (Mesh *)ob->data;
/* The final mesh is the result of calculating all enabled modifiers. */
Mesh *mesh_final = nullptr;
/* The result of calculating all leading deform modifiers. */
Mesh *mesh_deform = nullptr;
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
GeometrySet geometry_set_final;
auto &edit_data = geometry.get_component_for_write<GeometryComponentEditData>();
if (!edit_data.mesh_edit_hints_) {
edit_data.mesh_edit_hints_ = std::make_unique<MeshEditHints>();
}
return *edit_data.mesh_edit_hints_;
}
static void save_deform_mesh(GeometrySet &geometry)
{
if (const Mesh *mesh = geometry.get_mesh()) {
MeshEditHints &edit_data = geometry_mesh_edit_hints_ensure(geometry);
edit_data.mesh_deform = geometry.get_component_ptr<MeshComponent>();
}
}
static GeometrySet mesh_calc_modifiers(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const bool use_deform,
const bool need_mapping,
const CustomData_MeshMasks *dataMask,
const bool use_cache)
{
const Mesh *mesh_input = static_cast<const Mesh *>(ob->data);
BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_EVAL_FINAL_RESULT) == 0);
GeometrySet geometry_set = GeometrySet::from_mesh(const_cast<Mesh *>(mesh_input),
GeometryOwnershipType::ReadOnly);
/* Mesh with constructive modifiers but no deformation applied. Tracked
* along with final mesh if undeformed / orco coordinates are requested
* for texturing. */
@ -605,11 +592,9 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
BKE_modifiers_clear_errors(ob);
if (ob->modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
if (mesh_final == nullptr) {
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
set_rest_position(*mesh);
}
set_rest_position(*mesh_final);
}
/* Apply all leading deform modifiers. */
@ -623,20 +608,17 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
if (mti->type == ModifierTypeType::OnlyDeform && !sculpt_dyntopo) {
ScopedModifierTimer modifier_timer{*md};
if (!mesh_final) {
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
}
if (mti->required_data_mask) {
CustomData_MeshMasks mask{};
mti->required_data_mask(md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
add_orco_mesh(ob, nullptr, mesh_final, nullptr, CD_ORCO);
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
if (mti->required_data_mask) {
CustomData_MeshMasks mask{};
mti->required_data_mask(md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
add_orco_mesh(ob, nullptr, mesh, nullptr, CD_ORCO);
}
}
}
BKE_modifier_deform_verts(md, &mectx, mesh_final, mesh_final->vert_positions_for_write());
BKE_modifier_deform_verts(md, &mectx, mesh, mesh->vert_positions_for_write());
}
}
else {
break;
@ -646,9 +628,7 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
/* Result of all leading deforming modifiers is cached for
* places that wish to use the original mesh but with deformed
* coordinates (like vertex paint). */
if (r_deform) {
mesh_deform = BKE_mesh_copy_for_eval(mesh_final ? mesh_final : mesh_input);
}
save_deform_mesh(geometry_set);
}
/* Apply all remaining constructive and deforming modifiers. */
@ -706,45 +686,31 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
continue;
}
blender::bke::ScopedModifierTimer modifier_timer{*md};
ScopedModifierTimer modifier_timer{*md};
/* Add orco mesh as layer if needed by this modifier. */
if (mesh_final && mesh_orco && mti->required_data_mask) {
CustomData_MeshMasks mask = {0};
mti->required_data_mask(md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_ORCO);
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
if (mesh_orco && mti->required_data_mask) {
CustomData_MeshMasks mask = {0};
mti->required_data_mask(md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
add_orco_mesh(ob, nullptr, mesh, mesh_orco, CD_ORCO);
}
}
}
if (mti->type == ModifierTypeType::OnlyDeform) {
if (!mesh_final) {
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
BKE_modifier_deform_verts(md, &mectx, mesh, mesh->vert_positions_for_write());
}
BKE_modifier_deform_verts(md, &mectx, mesh_final, mesh_final->vert_positions_for_write());
}
else {
bool check_for_needs_mapping = false;
if (mesh_final != nullptr) {
if (have_non_onlydeform_modifiers_applied == false) {
/* If we only deformed, we won't have initialized #CD_ORIGINDEX.
* as this is the only part of the function that initializes mapping. */
check_for_needs_mapping = true;
}
}
else {
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
check_for_needs_mapping = true;
}
have_non_onlydeform_modifiers_applied = true;
/* determine which data layers are needed by following modifiers */
CustomData_MeshMasks nextmask = md_datamask->next ? md_datamask->next->mask : final_datamask;
if (check_for_needs_mapping) {
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
/* Initialize original indices the first time we evaluate a
* constructive modifier. Modifiers will then do mapping mostly
* automatic by copying them through CustomData_copy_data along
@ -756,70 +722,54 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX))
{
/* calc */
CustomData_add_layer(
&mesh_final->vert_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->verts_num);
CustomData_add_layer(
&mesh_final->edge_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->edges_num);
CustomData_add_layer(
&mesh_final->face_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->faces_num);
CustomData_add_layer(&mesh->vert_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh->verts_num);
CustomData_add_layer(&mesh->edge_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh->edges_num);
CustomData_add_layer(&mesh->face_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh->faces_num);
/* Not worth parallelizing this,
* gives less than 0.1% overall speedup in best of best cases... */
range_vn_i((int *)CustomData_get_layer_for_write(
&mesh_final->vert_data, CD_ORIGINDEX, mesh_final->verts_num),
mesh_final->verts_num,
&mesh->vert_data, CD_ORIGINDEX, mesh->verts_num),
mesh->verts_num,
0);
range_vn_i((int *)CustomData_get_layer_for_write(
&mesh_final->edge_data, CD_ORIGINDEX, mesh_final->edges_num),
mesh_final->edges_num,
&mesh->edge_data, CD_ORIGINDEX, mesh->edges_num),
mesh->edges_num,
0);
range_vn_i((int *)CustomData_get_layer_for_write(
&mesh_final->face_data, CD_ORIGINDEX, mesh_final->faces_num),
mesh_final->faces_num,
&mesh->face_data, CD_ORIGINDEX, mesh->faces_num),
mesh->faces_num,
0);
}
}
/* set the Mesh to only copy needed data */
CustomData_MeshMasks mask = md_datamask->mask;
/* needMapping check here fixes bug #28112, otherwise it's
* possible that it won't be copied */
CustomData_MeshMasks_update(&mask, &append_mask);
if (need_mapping) {
mask.vmask |= CD_MASK_ORIGINDEX;
mask.emask |= CD_MASK_ORIGINDEX;
mask.pmask |= CD_MASK_ORIGINDEX;
}
mesh_set_only_copy(mesh_final, &mask);
/* set the Mesh to only copy needed data */
CustomData_MeshMasks mask = md_datamask->mask;
/* needMapping check here fixes bug #28112, otherwise it's
* possible that it won't be copied */
CustomData_MeshMasks_update(&mask, &append_mask);
if (need_mapping) {
mask.vmask |= CD_MASK_ORIGINDEX;
mask.emask |= CD_MASK_ORIGINDEX;
mask.pmask |= CD_MASK_ORIGINDEX;
}
mesh_set_only_copy(mesh, &mask);
/* add cloth rest shape key if needed */
if (mask.vmask & CD_MASK_CLOTH_ORCO) {
add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_CLOTH_ORCO);
}
/* add cloth rest shape key if needed */
if (mask.vmask & CD_MASK_CLOTH_ORCO) {
add_orco_mesh(ob, nullptr, mesh, mesh_orco, CD_CLOTH_ORCO);
}
/* add an origspace layer if needed */
if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
if (!CustomData_has_layer(&mesh_final->corner_data, CD_ORIGSPACE_MLOOP)) {
CustomData_add_layer(&mesh_final->corner_data,
CD_ORIGSPACE_MLOOP,
CD_SET_DEFAULT,
mesh_final->corners_num);
mesh_init_origspace(mesh_final);
/* add an origspace layer if needed */
if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
if (!CustomData_has_layer(&mesh->corner_data, CD_ORIGSPACE_MLOOP)) {
CustomData_add_layer(
&mesh->corner_data, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh->corners_num);
mesh_init_origspace(mesh);
}
}
}
Mesh *mesh_next = modifier_modify_mesh_and_geometry_set(
md, mectx, mesh_final, geometry_set_final);
ASSERT_IS_VALID_MESH(mesh_next);
if (mesh_next) {
/* if the modifier returned a new mesh, release the old one */
if (mesh_final != mesh_next) {
BLI_assert(mesh_final != mesh_input);
BKE_id_free(nullptr, mesh_final);
}
mesh_final = mesh_next;
}
modifier_modify_mesh_and_geometry_set(md, mectx, geometry_set);
/* create an orco mesh in parallel */
if (nextmask.vmask & CD_MASK_ORCO) {
@ -840,17 +790,14 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask);
mesh_set_only_copy(mesh_orco, &temp_cddata_masks);
mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco);
ASSERT_IS_VALID_MESH(mesh_next);
if (mesh_next) {
/* if the modifier returned a new mesh, release the old one */
if (mesh_orco != mesh_next) {
Mesh *mesh_orco_new = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco);
ASSERT_IS_VALID_MESH(mesh_orco_new);
if (mesh_orco_new) {
if (mesh_orco != mesh_orco_new) {
BLI_assert(mesh_orco != mesh_input);
BKE_id_free(nullptr, mesh_orco);
}
mesh_orco = mesh_next;
mesh_orco = mesh_orco_new;
}
}
@ -866,21 +813,23 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
nextmask.pmask |= CD_MASK_ORIGINDEX;
mesh_set_only_copy(mesh_orco_cloth, &nextmask);
mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco_cloth);
ASSERT_IS_VALID_MESH(mesh_next);
if (mesh_next) {
/* if the modifier returned a new mesh, release the old one */
if (mesh_orco_cloth != mesh_next) {
Mesh *mesh_orco_cloth_new = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco_cloth);
ASSERT_IS_VALID_MESH(mesh_orco_cloth_new);
if (mesh_orco_cloth_new) {
if (mesh_orco_cloth != mesh_orco_cloth_new) {
BLI_assert(mesh_orco != mesh_input);
BKE_id_free(nullptr, mesh_orco_cloth);
}
mesh_orco_cloth = mesh_next;
mesh_orco_cloth = mesh_orco_cloth_new;
}
}
mesh_final->runtime->deformed_only = false;
if (const Mesh *mesh = geometry_set.get_mesh()) {
if (mesh->runtime->deformed_only) {
Mesh *mesh_mut = geometry_set.get_mesh_for_write();
mesh_mut->runtime->deformed_only = false;
}
}
}
if (sculpt_mode && md->type == eModifierType_Multires) {
@ -894,32 +843,6 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
BKE_modifier_free_temporary_data(md);
}
if (mesh_final == nullptr) {
if (allow_shared_mesh) {
mesh_final = mesh_input;
}
else {
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
}
}
/* Denotes whether the object which the modifier stack came from owns the mesh or whether the
* mesh is shared across multiple objects since there are no effective modifiers. */
const bool is_own_mesh = (mesh_final != mesh_input);
/* Add orco coordinates to final and deformed mesh if requested. */
if (final_datamask.vmask & CD_MASK_ORCO) {
/* No need in ORCO layer if the mesh was not deformed or modified: undeformed mesh in this case
* matches input mesh. */
if (is_own_mesh) {
add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_ORCO);
}
if (mesh_deform) {
add_orco_mesh(ob, nullptr, mesh_deform, nullptr, CD_ORCO);
}
}
if (mesh_orco) {
BKE_id_free(nullptr, mesh_orco);
}
@ -929,46 +852,18 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
/* Remove temporary data layer only needed for modifier evaluation.
* Save some memory, and ensure GPU subdivision does not need to deal with this. */
CustomData_free_layers(&mesh_final->vert_data, CD_CLOTH_ORCO, mesh_final->verts_num);
/* Compute normals. */
if (is_own_mesh) {
mesh_calc_finalize(mesh_input, mesh_final);
}
else {
blender::bke::MeshRuntime *runtime = mesh_input->runtime;
if (runtime->mesh_eval == nullptr) {
std::lock_guard lock{mesh_input->runtime->eval_mutex};
if (runtime->mesh_eval == nullptr) {
/* Not yet finalized by any instance, do it now
* Isolate since computing normals is multithreaded and we are holding a lock. */
blender::threading::isolate_task([&] {
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
mesh_calc_finalize(mesh_input, mesh_final);
runtime->mesh_eval = mesh_final;
});
}
else {
/* Already finalized by another instance, reuse. */
mesh_final = runtime->mesh_eval;
}
}
else {
/* Already finalized by another instance, reuse. */
mesh_final = runtime->mesh_eval;
if (const Mesh *mesh = geometry_set.get_mesh()) {
if (CustomData_has_layer(&mesh->vert_data, CD_CLOTH_ORCO)) {
Mesh *mesh_mut = geometry_set.get_mesh_for_write();
CustomData_free_layers(&mesh_mut->vert_data, CD_CLOTH_ORCO, mesh_mut->verts_num);
}
}
/* Return final mesh */
*r_final = mesh_final;
if (r_deform) {
*r_deform = mesh_deform;
}
if (r_geometry_set) {
*r_geometry_set = new GeometrySet(std::move(geometry_set_final));
}
return geometry_set;
}
} // namespace blender::bke
bool editbmesh_modifier_is_enabled(const Scene *scene,
const Object *ob,
ModifierData *md,
@ -989,6 +884,8 @@ bool editbmesh_modifier_is_enabled(const Scene *scene,
return true;
}
namespace blender::bke {
static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
{
switch (mesh->runtime->wrapper_type) {
@ -1006,21 +903,21 @@ static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
return {};
}
static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const CustomData_MeshMasks *dataMask,
/* return args */
Mesh **r_cage,
Mesh **r_final,
GeometrySet **r_geometry_set)
static void save_cage_mesh(GeometrySet &geometry)
{
Mesh *mesh_input = (Mesh *)ob->data;
BMEditMesh *em_input = mesh_input->runtime->edit_mesh.get();
if (const Mesh *mesh = geometry.get_mesh()) {
MeshEditHints &edit_data = geometry_mesh_edit_hints_ensure(geometry);
edit_data.mesh_cage = geometry.get_component_ptr<MeshComponent>();
}
}
Mesh *mesh_cage = nullptr;
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
GeometrySet geometry_set_final;
static GeometrySet editbmesh_calc_modifiers(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
const Mesh *mesh_input = static_cast<const Mesh *>(ob->data);
const BMEditMesh *em_input = mesh_input->runtime->edit_mesh.get();
/* Mesh with constructive modifiers but no deformation applied. Tracked
* along with final mesh if undeformed / orco coordinates are requested
@ -1050,12 +947,12 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
CDMaskLink *md_datamask = datamasks;
CustomData_MeshMasks append_mask = CD_MASK_BAREMESH;
Mesh *mesh_final = BKE_mesh_wrapper_from_editmesh(
mesh_input->runtime->edit_mesh, &final_datamask, mesh_input);
GeometrySet geometry_set = GeometrySet::from_mesh(
BKE_mesh_wrapper_from_editmesh(mesh_input->runtime->edit_mesh, &final_datamask, mesh_input));
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true);
if (r_cage && cageIndex == -1) {
mesh_cage = mesh_final;
if (cageIndex == -1) {
save_cage_mesh(geometry_set);
}
/* The mesh from edit mode should not have any original index layers already, since those
@ -1068,8 +965,9 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
BKE_modifiers_clear_errors(ob);
if (ob->modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
BKE_mesh_wrapper_ensure_mdata(mesh_final);
set_rest_position(*mesh_final);
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
set_rest_position(*mesh);
}
}
bool non_deform_modifier_applied = false;
@ -1080,47 +978,30 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
}
blender::bke::ScopedModifierTimer modifier_timer{*md};
Mesh *mesh = geometry_set.get_mesh_for_write();
/* Add an orco mesh as layer if needed by this modifier. */
if (mesh_orco && mti->required_data_mask) {
CustomData_MeshMasks mask = {0};
mti->required_data_mask(md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
}
}
if (mesh_final == mesh_cage) {
/* If the cage mesh has already been assigned, we have passed the cage index in the modifier
* list. If the cage and final meshes are still the same, duplicate the final mesh so the
* cage mesh isn't modified anymore. */
mesh_final = BKE_mesh_copy_for_eval(mesh_final);
if (mesh_cage->runtime->edit_mesh) {
mesh_final->runtime->edit_mesh = mesh_cage->runtime->edit_mesh;
mesh_final->runtime->is_original_bmesh = true;
if (mesh_cage->runtime->edit_data) {
mesh_final->runtime->edit_data = std::make_unique<blender::bke::EditMeshData>(
*mesh_cage->runtime->edit_data);
}
add_orco_mesh(ob, em_input, mesh, mesh_orco, CD_ORCO);
}
}
if (mti->type == ModifierTypeType::OnlyDeform) {
if (mti->deform_verts_EM) {
BKE_modifier_deform_vertsEM(md,
&mectx,
em_input,
mesh_final,
mesh_wrapper_vert_coords_ensure_for_write(mesh_final));
BKE_mesh_wrapper_tag_positions_changed(mesh_final);
BKE_modifier_deform_vertsEM(
md, &mectx, em_input, mesh, mesh_wrapper_vert_coords_ensure_for_write(mesh));
BKE_mesh_wrapper_tag_positions_changed(mesh);
}
else {
BKE_mesh_wrapper_ensure_mdata(mesh_final);
BKE_modifier_deform_verts(md, &mectx, mesh_final, mesh_final->vert_positions_for_write());
mesh_final->tag_positions_changed();
BKE_mesh_wrapper_ensure_mdata(mesh);
BKE_modifier_deform_verts(md, &mectx, mesh, mesh->vert_positions_for_write());
}
}
else {
Mesh *mesh = geometry_set.get_mesh_for_write();
non_deform_modifier_applied = true;
/* create an orco derivedmesh in parallel */
@ -1157,33 +1038,25 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
mask.emask |= CD_MASK_ORIGINDEX;
mask.pmask |= CD_MASK_ORIGINDEX;
mesh_set_only_copy(mesh_final, &mask);
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
mesh_set_only_copy(mesh, &mask);
if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
if (!CustomData_has_layer(&mesh_final->corner_data, CD_ORIGSPACE_MLOOP)) {
CustomData_add_layer(&mesh_final->corner_data,
CD_ORIGSPACE_MLOOP,
CD_SET_DEFAULT,
mesh_final->corners_num);
mesh_init_origspace(mesh_final);
if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
if (!CustomData_has_layer(&mesh->corner_data, CD_ORIGSPACE_MLOOP)) {
CustomData_add_layer(
&mesh->corner_data, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh->corners_num);
mesh_init_origspace(mesh);
}
}
mesh->runtime->deformed_only = false;
}
Mesh *mesh_next = modifier_modify_mesh_and_geometry_set(
md, mectx, mesh_final, geometry_set_final);
ASSERT_IS_VALID_MESH(mesh_next);
if (mesh_next) {
if (mesh_final != mesh_next) {
BKE_id_free(nullptr, mesh_final);
}
mesh_final = mesh_next;
}
mesh_final->runtime->deformed_only = false;
modifier_modify_mesh_and_geometry_set(md, mectx, geometry_set);
}
if (r_cage && i == cageIndex) {
mesh_cage = mesh_final;
if (i == cageIndex) {
blender::bke::save_cage_mesh(geometry_set);
}
}
@ -1191,24 +1064,18 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
/* Add orco coordinates to final and deformed mesh if requested. */
if (final_datamask.vmask & CD_MASK_ORCO) {
/* FIXME(@ideasman42): avoid the need to convert to mesh data just to add an orco layer. */
BKE_mesh_wrapper_ensure_mdata(mesh_final);
add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
/* FIXME(@ideasman42): avoid the need to convert to mesh data just to add an orco layer. */
BKE_mesh_wrapper_ensure_mdata(mesh);
add_orco_mesh(ob, em_input, mesh, mesh_orco, CD_ORCO);
}
}
if (mesh_orco) {
BKE_id_free(nullptr, mesh_orco);
}
/* Return final mesh. */
*r_final = mesh_final;
if (r_cage) {
*r_cage = mesh_cage;
}
if (r_geometry_set) {
*r_geometry_set = new GeometrySet(std::move(geometry_set_final));
}
return geometry_set;
}
static void mesh_build_extra_data(const Depsgraph *depsgraph,
@ -1228,53 +1095,28 @@ static void mesh_build_data(Depsgraph *depsgraph,
const CustomData_MeshMasks *dataMask,
const bool need_mapping)
{
#if 0 /* XXX This is already taken care of in #mesh_calc_modifiers... */
if (need_mapping) {
/* Also add the flag so that it is recorded in lastDataMask. */
dataMask->vmask |= CD_MASK_ORIGINDEX;
dataMask->emask |= CD_MASK_ORIGINDEX;
dataMask->pmask |= CD_MASK_ORIGINDEX;
}
#endif
const Mesh *mesh_input = static_cast<const Mesh *>(ob->data);
Mesh *mesh_eval = nullptr, *mesh_deform_eval = nullptr;
GeometrySet *geometry_set_eval = nullptr;
mesh_calc_modifiers(depsgraph,
scene,
ob,
true,
need_mapping,
dataMask,
true,
true,
&mesh_deform_eval,
&mesh_eval,
&geometry_set_eval);
GeometrySet geometry_set = mesh_calc_modifiers(
depsgraph, scene, ob, true, need_mapping, dataMask, true);
/* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result
* is not guaranteed to be owned by object.
*
* Check ownership now, since later on we can not go to a mesh owned by someone else via
* object's runtime: this could cause access freed data on depsgraph destruction (mesh who owns
* the final result might be freed prior to object). */
Mesh *mesh = (Mesh *)ob->data;
const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime->mesh_eval);
BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned);
const Mesh *mesh_eval = geometry_set.get_mesh();
/* Add the final mesh as a non-owning component to the geometry set. */
MeshComponent &mesh_component = geometry_set_eval->get_component_for_write<MeshComponent>();
mesh_component.replace(mesh_eval, GeometryOwnershipType::Editable);
ob->runtime->geometry_set_eval = geometry_set_eval;
BKE_object_eval_assign_data(ob, &const_cast<ID &>(mesh_eval->id), false);
ob->runtime->geometry_set_eval = new GeometrySet(std::move(geometry_set));
ob->runtime->mesh_deform_eval = mesh_deform_eval;
ob->runtime->last_data_mask = *dataMask;
ob->runtime->last_need_mapping = need_mapping;
/* Make sure that drivers can target shapekey properties.
* Note that this causes a potential inconsistency, as the shapekey may have a
* different topology than the evaluated mesh. */
BLI_assert(mesh->key == nullptr || DEG_is_evaluated_id(&mesh->key->id));
mesh_eval->key = mesh->key;
if (mesh_input->key) {
BLI_assert(DEG_is_evaluated_id(&mesh_input->key->id));
if (mesh_eval != mesh_input) {
const_cast<Mesh *>(mesh_eval)->key = mesh_input->key;
}
}
if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) {
if (DEG_is_active(depsgraph)) {
@ -1285,48 +1127,58 @@ static void mesh_build_data(Depsgraph *depsgraph,
mesh_build_extra_data(depsgraph, ob, mesh_eval);
}
static void ensure_mesh_component_mdata(GeometrySet &geometry_set)
{
const Mesh *mesh = geometry_set.get_mesh();
}
static void editbmesh_build_data(Depsgraph *depsgraph,
const Scene *scene,
Object *obedit,
CustomData_MeshMasks *dataMask)
{
Mesh *mesh = static_cast<Mesh *>(obedit->data);
Mesh *me_cage;
Mesh *me_final;
GeometrySet *non_mesh_components;
const Mesh *mesh_input = static_cast<const Mesh *>(obedit->data);
editbmesh_calc_modifiers(
depsgraph, scene, obedit, dataMask, &me_cage, &me_final, &non_mesh_components);
/* The modifier stack result is expected to share edit mesh pointer with the input.
* This is similar `mesh_calc_finalize()`. */
BKE_mesh_free_editmesh(me_final);
BKE_mesh_free_editmesh(me_cage);
me_final->runtime->edit_mesh = me_cage->runtime->edit_mesh = mesh->runtime->edit_mesh;
GeometrySet geometry_set = editbmesh_calc_modifiers(depsgraph, scene, obedit, dataMask);
/* Object has edit_mesh but is not in edit mode (object shares mesh datablock with another object
* with is in edit mode).
* Convert edit mesh to mesh until the draw manager can draw mesh wrapper which is not in the
* edit mode. */
if (!(obedit->mode & OB_MODE_EDIT)) {
BKE_mesh_wrapper_ensure_mdata(me_final);
if (me_final != me_cage) {
BKE_mesh_wrapper_ensure_mdata(me_cage);
MeshEditHints &edit_hints =
*geometry_set.get_component_for_write<GeometryComponentEditData>().mesh_edit_hints_;
const bool cage_mesh_shared = edit_hints.mesh_cage->get() == geometry_set.get_mesh();
Mesh *mesh = geometry_set.get_mesh_for_write();
BKE_mesh_wrapper_ensure_mdata(mesh);
if (cage_mesh_shared) {
save_cage_mesh(geometry_set);
}
else {
if (edit_hints.mesh_cage->is_mutable()) {
edit_hints.mesh_cage->tag_ensured_mutable();
}
else {
edit_hints.mesh_cage = edit_hints.mesh_cage->copy();
}
Mesh *mesh_cage = const_cast<MeshComponent &>(*edit_hints.mesh_cage).get_for_write();
BKE_mesh_wrapper_ensure_mdata(mesh_cage);
}
}
const bool is_mesh_eval_owned = (me_final != mesh->runtime->mesh_eval);
BKE_object_eval_assign_data(obedit, &me_final->id, is_mesh_eval_owned);
Mesh *mesh_final = const_cast<Mesh *>(geometry_set.get_mesh());
BKE_object_eval_assign_data(obedit, &mesh_final->id, false);
/* Make sure that drivers can target shapekey properties.
* Note that this causes a potential inconsistency, as the shapekey may have a
* different topology than the evaluated mesh. */
BLI_assert(mesh->key == nullptr || DEG_is_evaluated_id(&mesh->key->id));
me_final->key = mesh->key;
BLI_assert(mesh_input->key == nullptr || DEG_is_evaluated_id(&mesh_input->key->id));
if (mesh_input->key && !mesh_final->key) {
mesh_final->key = mesh_input->key;
}
obedit->runtime->editmesh_eval_cage = me_cage;
obedit->runtime->geometry_set_eval = non_mesh_components;
obedit->runtime->geometry_set_eval = new GeometrySet(std::move(geometry_set));
obedit->runtime->last_data_mask = *dataMask;
}
@ -1385,11 +1237,14 @@ static void object_get_datamask(const Depsgraph *depsgraph,
}
}
} // namespace blender::bke
void makeDerivedMesh(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
using namespace blender::bke;
BLI_assert(ob->type == OB_MESH);
/* Evaluated meshes aren't supposed to be created on original instances. If you do,
@ -1426,6 +1281,7 @@ Mesh *mesh_get_eval_deform(Depsgraph *depsgraph,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
using namespace blender::bke;
BMEditMesh *em = ((Mesh *)ob->data)->runtime->edit_mesh.get();
if (em != nullptr) {
/* There is no such a concept as deformed mesh in edit mode.
@ -1450,7 +1306,7 @@ Mesh *mesh_get_eval_deform(Depsgraph *depsgraph,
CustomData_MeshMasks cddata_masks = *dataMask;
object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
if (!ob->runtime->mesh_deform_eval ||
if (!BKE_object_get_mesh_deform_eval(ob) ||
!CustomData_MeshMasks_are_matching(&(ob->runtime->last_data_mask), &cddata_masks) ||
(need_mapping && !ob->runtime->last_need_mapping))
{
@ -1459,7 +1315,7 @@ Mesh *mesh_get_eval_deform(Depsgraph *depsgraph,
depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime->last_need_mapping);
}
return ob->runtime->mesh_deform_eval;
return const_cast<Mesh *>(BKE_object_get_mesh_deform_eval(ob));
}
Mesh *mesh_create_eval_final(Depsgraph *depsgraph,
@ -1467,10 +1323,11 @@ Mesh *mesh_create_eval_final(Depsgraph *depsgraph,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
Mesh *result;
mesh_calc_modifiers(
depsgraph, scene, ob, true, false, dataMask, false, false, nullptr, &result, nullptr);
return result;
using namespace blender::bke;
GeometrySet geometry_set = mesh_calc_modifiers(
depsgraph, scene, ob, true, false, dataMask, false);
geometry_set.ensure_owns_direct_data();
return geometry_set.get_component_for_write<MeshComponent>().release();
}
Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph,
@ -1478,10 +1335,11 @@ Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
Mesh *result;
mesh_calc_modifiers(
depsgraph, scene, ob, false, false, dataMask, false, false, nullptr, &result, nullptr);
return result;
using namespace blender::bke;
GeometrySet geometry_set = mesh_calc_modifiers(
depsgraph, scene, ob, false, false, dataMask, false);
geometry_set.ensure_owns_direct_data();
return geometry_set.get_component_for_write<MeshComponent>().release();
}
Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
@ -1489,10 +1347,11 @@ Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
Mesh *result;
mesh_calc_modifiers(
depsgraph, scene, ob, false, false, dataMask, false, false, nullptr, &result, nullptr);
return result;
using namespace blender::bke;
GeometrySet geometry_set = mesh_calc_modifiers(
depsgraph, scene, ob, false, false, dataMask, false);
geometry_set.ensure_owns_direct_data();
return geometry_set.get_component_for_write<MeshComponent>().release();
}
/***/
@ -1503,6 +1362,7 @@ Mesh *editbmesh_get_eval_cage(Depsgraph *depsgraph,
BMEditMesh * /*em*/,
const CustomData_MeshMasks *dataMask)
{
using namespace blender::bke;
CustomData_MeshMasks cddata_masks = *dataMask;
/* if there's no derived mesh or the last data mask used doesn't include
@ -1510,13 +1370,13 @@ Mesh *editbmesh_get_eval_cage(Depsgraph *depsgraph,
*/
object_get_datamask(depsgraph, obedit, &cddata_masks, nullptr);
if (!obedit->runtime->editmesh_eval_cage ||
if (!BKE_object_get_editmesh_eval_cage(obedit) ||
!CustomData_MeshMasks_are_matching(&(obedit->runtime->last_data_mask), &cddata_masks))
{
editbmesh_build_data(depsgraph, scene, obedit, &cddata_masks);
}
return obedit->runtime->editmesh_eval_cage;
return const_cast<Mesh *>(BKE_object_get_editmesh_eval_cage(obedit));
}
Mesh *editbmesh_get_eval_cage_from_orig(Depsgraph *depsgraph,
@ -1570,6 +1430,8 @@ void mesh_get_mapped_verts_coords(Mesh *mesh_eval, blender::MutableSpan<blender:
}
}
namespace blender::bke {
static void mesh_init_origspace(Mesh *mesh)
{
const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
@ -1644,3 +1506,5 @@ static void mesh_init_origspace(Mesh *mesh)
BKE_mesh_tessface_clear(mesh);
}
} // namespace blender::bke

View File

@ -489,7 +489,7 @@ static void armature_deform_coords_impl(const Object *ob_arm,
const char *defgrp_name,
blender::Span<MDeformVert> dverts,
const Mesh *me_target,
BMEditMesh *em_target,
const BMEditMesh *em_target,
bGPDstroke *gps_target)
{
const bArmature *arm = static_cast<const bArmature *>(ob_arm->data);
@ -710,7 +710,7 @@ void BKE_armature_deform_coords_with_editmesh(const Object *ob_arm,
int deformflag,
float (*vert_coords_prev)[3],
const char *defgrp_name,
BMEditMesh *em_target)
const BMEditMesh *em_target)
{
armature_deform_coords_impl(ob_arm,
ob_target,

View File

@ -204,7 +204,7 @@ static void curve_deform_coords_impl(const Object *ob_curve,
const int defgrp_index,
const short flag,
const short defaxis,
BMEditMesh *em_target)
const BMEditMesh *em_target)
{
Curve *cu;
int a;
@ -391,7 +391,7 @@ void BKE_curve_deform_coords_with_editmesh(const Object *ob_curve,
const int defgrp_index,
const short flag,
const short defaxis,
BMEditMesh *em_target)
const BMEditMesh *em_target)
{
curve_deform_coords_impl(ob_curve,
ob_target,

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);
@ -529,31 +529,31 @@ void GeometrySet::replace_grease_pencil(GreasePencil *grease_pencil,
Mesh *GeometrySet::get_mesh_for_write()
{
MeshComponent *component = this->get_component_ptr<MeshComponent>();
MeshComponent *component = this->get_component_for_write_ptr<MeshComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
PointCloud *GeometrySet::get_pointcloud_for_write()
{
PointCloudComponent *component = this->get_component_ptr<PointCloudComponent>();
PointCloudComponent *component = this->get_component_for_write_ptr<PointCloudComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
Volume *GeometrySet::get_volume_for_write()
{
VolumeComponent *component = this->get_component_ptr<VolumeComponent>();
VolumeComponent *component = this->get_component_for_write_ptr<VolumeComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
Curves *GeometrySet::get_curves_for_write()
{
CurveComponent *component = this->get_component_ptr<CurveComponent>();
CurveComponent *component = this->get_component_for_write_ptr<CurveComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
Instances *GeometrySet::get_instances_for_write()
{
InstancesComponent *component = this->get_component_ptr<InstancesComponent>();
InstancesComponent *component = this->get_component_for_write_ptr<InstancesComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
@ -569,7 +569,7 @@ CurvesEditHints *GeometrySet::get_curve_edit_hints_for_write()
GreasePencil *GeometrySet::get_grease_pencil_for_write()
{
GreasePencilComponent *component = this->get_component_ptr<GreasePencilComponent>();
GreasePencilComponent *component = this->get_component_for_write_ptr<GreasePencilComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}

View File

@ -339,7 +339,7 @@ static void lattice_deform_coords_impl(const Object *ob_lattice,
const char *defgrp_name,
const float fac,
const Mesh *me_target,
BMEditMesh *em_target)
const BMEditMesh *em_target)
{
LatticeDeformData *lattice_deform_data;
const MDeformVert *dvert = nullptr;
@ -459,7 +459,7 @@ void BKE_lattice_deform_coords_with_editmesh(const Object *ob_lattice,
const short flag,
const char *defgrp_name,
const float fac,
BMEditMesh *em_target)
const BMEditMesh *em_target)
{
lattice_deform_coords_impl(ob_lattice,
ob_target,

View File

@ -929,7 +929,7 @@ void BKE_modifier_deform_verts(ModifierData *md,
void BKE_modifier_deform_vertsEM(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
const BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions)
{

View File

@ -1636,13 +1636,6 @@ void BKE_object_free_derived_caches(Object *ob)
object_update_from_subsurf_ccg(ob);
if (ob->runtime->editmesh_eval_cage &&
ob->runtime->editmesh_eval_cage != reinterpret_cast<Mesh *>(ob->runtime->data_eval))
{
BKE_id_free(nullptr, ob->runtime->editmesh_eval_cage);
}
ob->runtime->editmesh_eval_cage = nullptr;
if (ob->runtime->data_eval != nullptr) {
if (ob->runtime->is_data_eval_owned) {
ID *data_eval = ob->runtime->data_eval;
@ -1657,11 +1650,6 @@ void BKE_object_free_derived_caches(Object *ob)
}
ob->runtime->data_eval = nullptr;
}
if (ob->runtime->mesh_deform_eval != nullptr) {
Mesh *mesh_deform_eval = ob->runtime->mesh_deform_eval;
BKE_id_free(nullptr, mesh_deform_eval);
ob->runtime->mesh_deform_eval = nullptr;
}
/* Restore initial pointer for copy-on-evaluation data-blocks, object->data
* might be pointing to an evaluated data-block data was just freed above. */
@ -1682,10 +1670,8 @@ void BKE_object_free_derived_caches(Object *ob)
ob->runtime->gpd_eval = nullptr;
}
if (ob->runtime->geometry_set_eval != nullptr) {
delete ob->runtime->geometry_set_eval;
ob->runtime->geometry_set_eval = nullptr;
}
delete ob->runtime->geometry_set_eval;
ob->runtime->geometry_set_eval = nullptr;
}
void BKE_object_free_caches(Object *object)
@ -4217,26 +4203,59 @@ const Mesh *BKE_object_get_editmesh_eval_final(const Object *object)
return nullptr;
}
return reinterpret_cast<Mesh *>(object->runtime->data_eval);
return reinterpret_cast<const Mesh *>(object->runtime->data_eval);
}
const Mesh *BKE_object_get_editmesh_eval_cage(const Object *object)
{
using namespace blender::bke;
BLI_assert(!DEG_is_original_id(&object->id));
BLI_assert(object->type == OB_MESH);
const Mesh *mesh = static_cast<const Mesh *>(object->data);
BLI_assert(mesh->runtime->edit_mesh != nullptr);
UNUSED_VARS_NDEBUG(mesh);
return object->runtime->editmesh_eval_cage;
const GeometrySet *geometry_set = object->runtime->geometry_set_eval;
if (!geometry_set) {
return nullptr;
}
const auto *component = geometry_set->get_component<GeometryComponentEditData>();
if (!component) {
return nullptr;
}
const MeshEditHints *edit_hints = component->mesh_edit_hints_.get();
if (!edit_hints) {
return nullptr;
}
const MeshComponent *mesh_component = edit_hints->mesh_cage.get();
if (!mesh_component) {
return nullptr;
}
return mesh_component->get();
}
const Mesh *BKE_object_get_mesh_deform_eval(const Object *object)
{
using namespace blender::bke;
BLI_assert(!DEG_is_original_id(&object->id));
BLI_assert(object->type == OB_MESH);
return object->runtime->mesh_deform_eval;
const GeometrySet *geometry_set = object->runtime->geometry_set_eval;
if (!geometry_set) {
return nullptr;
}
const auto *component = geometry_set->get_component<GeometryComponentEditData>();
if (!component) {
return nullptr;
}
const MeshEditHints *edit_hints = component->mesh_edit_hints_.get();
if (!edit_hints) {
return nullptr;
}
const MeshComponent *mesh_component = edit_hints->mesh_deform.get();
if (!mesh_component) {
return nullptr;
}
return mesh_component->get();
}
Lattice *BKE_object_get_lattice(const Object *object)
@ -4875,7 +4894,6 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int /*flag*/)
blender::bke::ObjectRuntime *runtime = object->runtime;
runtime->data_eval = nullptr;
runtime->gpd_eval = nullptr;
runtime->mesh_deform_eval = nullptr;
runtime->curve_cache = nullptr;
runtime->object_as_temp_mesh = nullptr;
runtime->pose_backup = nullptr;

View File

@ -89,6 +89,12 @@ template<typename T> class ImplicitSharingPtr {
return data_ != nullptr;
}
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<T, U>))>
operator ImplicitSharingPtr<U>() const
{
return ImplicitSharingPtr<U>(static_cast<U *>(data_));
}
const T *get() const
{
return data_;

View File

@ -139,7 +139,7 @@ static void deform_verts(ModifierData *md,
static void deform_verts_EM(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
const BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions)
{

View File

@ -116,7 +116,7 @@ static void deform_verts(ModifierData *md,
static void deform_verts_EM(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
const BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions)
{

View File

@ -107,7 +107,7 @@ static void deform_verts(ModifierData *md,
static void deform_verts_EM(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
const BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions)
{

View File

@ -69,7 +69,7 @@ static void deform_matrices(ModifierData *md,
static void deform_verts_EM(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh * /*em*/,
const BMEditMesh * /*em*/,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions)
{