Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc99
-rw-r--r--source/blender/blenkernel/intern/pointcloud.cc32
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc22
-rw-r--r--source/blender/makesdna/DNA_object_types.h11
4 files changed, 143 insertions, 21 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 78d4ad6fe19..b8219dcf7ac 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -50,6 +50,7 @@
#include "BKE_colorband.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
+#include "BKE_geometry_set.hh"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
@@ -881,6 +882,56 @@ void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval,
BLI_assert(me_eval->runtime.wrapper_type_finalize == 0);
}
+/**
+ * Modifies the given mesh and geometry set. The geometry set is expect to have NO mesh component.
+ * After this function ends, the geometry set will still have NO mesh component. Instead, an input
+ * mesh is passed separately and is returned separately.
+ *
+ * The purpose of the geometry set is to store all non-mesh geometry components that are generated
+ * by modifiers.
+ */
+static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
+ const ModifierEvalContext &mectx,
+ Object *ob,
+ Mesh *input_mesh,
+ GeometrySet &geometry_set)
+{
+ Mesh *mesh_output = nullptr;
+ const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
+ if (mti->modifyGeometrySet == nullptr) {
+ mesh_output = BKE_modifier_modify_mesh(md, &mectx, input_mesh);
+ }
+ 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);
+
+ /* Adds a new mesh component to the geometry set based on the #input_mesh. */
+ BLI_assert(!geometry_set.has<MeshComponent>());
+ MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
+ mesh_component.replace(input_mesh, GeometryOwnershipType::Editable);
+ mesh_component.copy_vertex_group_names_from_object(*ob);
+
+ /* Let the modifier change the geometry set. */
+ mti->modifyGeometrySet(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>();
+ mesh_output = mesh_component.release();
+ geometry_set.remove<MeshComponent>();
+ }
+
+ /* Return an empty mesh instead of null. */
+ if (mesh_output == nullptr) {
+ mesh_output = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
+ BKE_mesh_copy_settings(mesh_output, input_mesh);
+ }
+ }
+
+ return mesh_output;
+}
+
static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -892,7 +943,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
const bool allow_shared_mesh,
/* return args */
Mesh **r_deform,
- Mesh **r_final)
+ Mesh **r_final,
+ GeometrySet **r_geometry_set)
{
/* Input and final mesh. Final mesh is only created the moment the first
* constructive modifier is executed, or a deform modifier needs normals
@@ -900,6 +952,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
Mesh *mesh_input = (Mesh *)ob->data;
Mesh *mesh_final = nullptr;
Mesh *mesh_deform = nullptr;
+ /* This geometry set contains the non-mesh data that might be generated by modifiers. */
+ GeometrySet geometry_set_final;
BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
/* Deformed vertex locations array. Deform only modifier need this type of
@@ -1197,7 +1251,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
}
}
- Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final);
+ Mesh *mesh_next = modifier_modify_mesh_and_geometry_set(
+ md, mectx, ob, mesh_final, geometry_set_final);
ASSERT_IS_VALID_MESH(mesh_next);
if (mesh_next) {
@@ -1375,6 +1430,9 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
if (r_deform) {
*r_deform = mesh_deform;
}
+ if (r_geometry_set) {
+ *r_geometry_set = new GeometrySet(std::move(geometry_set_final));
+ }
}
float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3]
@@ -1483,7 +1541,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
const CustomData_MeshMasks *dataMask,
/* return args */
Mesh **r_cage,
- Mesh **r_final)
+ Mesh **r_final,
+ GeometrySet **r_geometry_set)
{
/* Input and final mesh. Final mesh is only created the moment the first
* constructive modifier is executed, or a deform modifier needs normals
@@ -1491,6 +1550,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
Mesh *mesh_input = (Mesh *)ob->data;
Mesh *mesh_final = nullptr;
Mesh *mesh_cage = nullptr;
+ /* This geometry set contains the non-mesh data that might be generated by modifiers. */
+ GeometrySet geometry_set_final;
/* Deformed vertex locations array. Deform only modifier need this type of
* float array rather than MVert*. Tracked along with mesh_final as an
@@ -1655,7 +1716,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
}
}
- Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final);
+ Mesh *mesh_next = modifier_modify_mesh_and_geometry_set(
+ md, mectx, ob, mesh_final, geometry_set_final);
ASSERT_IS_VALID_MESH(mesh_next);
if (mesh_next) {
@@ -1757,6 +1819,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
if (r_cage) {
*r_cage = mesh_cage;
}
+ if (r_geometry_set) {
+ *r_geometry_set = new GeometrySet(std::move(geometry_set_final));
+ }
}
static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval)
@@ -1803,6 +1868,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
#endif
Mesh *mesh_eval = nullptr, *mesh_deform_eval = nullptr;
+ GeometrySet *geometry_set_eval = nullptr;
mesh_calc_modifiers(depsgraph,
scene,
ob,
@@ -1813,7 +1879,8 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
true,
true,
&mesh_deform_eval,
- &mesh_eval);
+ &mesh_eval,
+ &geometry_set_eval);
/* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result
* is not guaranteed to be owned by object.
@@ -1825,6 +1892,12 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
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);
+ /* Add the final mesh as read-only non-owning component to the geometry set. */
+ BLI_assert(!geometry_set_eval->has<MeshComponent>());
+ MeshComponent &mesh_component = geometry_set_eval->get_component_for_write<MeshComponent>();
+ mesh_component.replace(mesh_eval, GeometryOwnershipType::ReadOnly);
+ ob->runtime.geometry_set_eval = geometry_set_eval;
+
ob->runtime.mesh_deform_eval = mesh_deform_eval;
ob->runtime.last_data_mask = *dataMask;
ob->runtime.last_need_mapping = need_mapping;
@@ -1864,11 +1937,14 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph,
Mesh *me_cage;
Mesh *me_final;
+ GeometrySet *non_mesh_components;
- editbmesh_calc_modifiers(depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final);
+ editbmesh_calc_modifiers(
+ depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final, &non_mesh_components);
em->mesh_eval_final = me_final;
em->mesh_eval_cage = me_cage;
+ obedit->runtime.geometry_set_eval = non_mesh_components;
BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final);
@@ -2020,7 +2096,8 @@ Mesh *mesh_create_eval_final(Depsgraph *depsgraph,
{
Mesh *final;
- mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final);
+ mesh_calc_modifiers(
+ depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final, nullptr);
return final;
}
@@ -2034,7 +2111,7 @@ Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph,
Mesh *final;
mesh_calc_modifiers(
- depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final);
+ depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final, nullptr);
return final;
}
@@ -2046,7 +2123,8 @@ Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph,
{
Mesh *final;
- mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final);
+ mesh_calc_modifiers(
+ depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr);
return final;
}
@@ -2058,7 +2136,8 @@ Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
{
Mesh *final;
- mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final);
+ mesh_calc_modifiers(
+ depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr);
return final;
}
diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc
index b4a9ad73048..7bd14e80333 100644
--- a/source/blender/blenkernel/intern/pointcloud.cc
+++ b/source/blender/blenkernel/intern/pointcloud.cc
@@ -371,6 +371,25 @@ static void pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph,
}
}
+static PointCloud *take_pointcloud_ownership_from_geometry_set(GeometrySet &geometry_set)
+{
+ if (!geometry_set.has<PointCloudComponent>()) {
+ return nullptr;
+ }
+ PointCloudComponent &pointcloud_component =
+ geometry_set.get_component_for_write<PointCloudComponent>();
+ PointCloud *pointcloud = pointcloud_component.release();
+ if (pointcloud != nullptr) {
+ /* Add back, but as read-only non-owning component. */
+ pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly);
+ }
+ else {
+ /* The component was empty, we can also remove it. */
+ geometry_set.remove<PointCloudComponent>();
+ }
+ return pointcloud;
+}
+
void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
{
/* Free any evaluated data and restore original data. */
@@ -382,10 +401,17 @@ void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene
GeometryOwnershipType::ReadOnly);
pointcloud_evaluate_modifiers(depsgraph, scene, object, geometry_set);
+ PointCloud *pointcloud_eval = take_pointcloud_ownership_from_geometry_set(geometry_set);
+
+ /* If the geometry set did not contain a point cloud, we still create an empty one. */
+ if (pointcloud_eval == nullptr) {
+ pointcloud_eval = BKE_pointcloud_new_nomain(0);
+ }
+
/* Assign evaluated object. */
- PointCloud *dummy_pointcloud = BKE_pointcloud_new_nomain(0);
- BKE_object_eval_assign_data(object, &dummy_pointcloud->id, true);
- object->runtime.geometry_set_eval = new GeometrySet(geometry_set);
+ const bool eval_is_owned = pointcloud_eval != pointcloud;
+ BKE_object_eval_assign_data(object, &pointcloud_eval->id, eval_is_owned);
+ object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set));
}
/* Draw Cache */
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index b92bf475f49..e472d82f2ee 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -136,8 +136,8 @@ bool deg_iterator_components_step(BLI_Iterator *iter)
return false;
}
- if (data->geometry_component_owner->type != OB_POINTCLOUD) {
- /* Only point clouds support multiple geometry components currently. */
+ if (data->geometry_component_owner->runtime.geometry_set_eval == nullptr) {
+ /* Return the object itself, if it does not have a geometry set yet. */
iter->current = data->geometry_component_owner;
data->geometry_component_owner = nullptr;
return true;
@@ -149,10 +149,16 @@ bool deg_iterator_components_step(BLI_Iterator *iter)
return false;
}
+ /* The mesh component. */
if (data->geometry_component_id == 0) {
data->geometry_component_id++;
- /* The mesh component. */
+ /* Don't use a temporary object for this component, when the owner is a mesh object. */
+ if (data->geometry_component_owner->type == OB_MESH) {
+ iter->current = data->geometry_component_owner;
+ return true;
+ }
+
const Mesh *mesh = geometry_set->get_mesh_for_read();
if (mesh != nullptr) {
Object *temp_object = &data->temp_geometry_component_object;
@@ -164,10 +170,17 @@ bool deg_iterator_components_step(BLI_Iterator *iter)
return true;
}
}
+
+ /* The pointcloud component. */
if (data->geometry_component_id == 1) {
data->geometry_component_id++;
- /* The pointcloud component. */
+ /* Don't use a temporary object for this component, when the owner is a point cloud object. */
+ if (data->geometry_component_owner->type == OB_POINTCLOUD) {
+ iter->current = data->geometry_component_owner;
+ return true;
+ }
+
const PointCloud *pointcloud = geometry_set->get_pointcloud_for_read();
if (pointcloud != nullptr) {
Object *temp_object = &data->temp_geometry_component_object;
@@ -179,6 +192,7 @@ bool deg_iterator_components_step(BLI_Iterator *iter)
return true;
}
}
+
data->geometry_component_owner = nullptr;
return false;
}
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 71f67d8a3b4..0a3a2cd0b64 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -150,14 +150,17 @@ typedef struct Object_Runtime {
*/
struct ID *data_orig;
/**
- * Object data structure created during object evaluation.
- * It has all modifiers applied.
+ * Object data structure created during object evaluation. It has all modifiers applied.
+ * The type is determined by the type of the original object. For example, for mesh and curve
+ * objects, this is a mesh. For a volume object, this is a volume.
*/
struct ID *data_eval;
/**
- * Some objects support evaluating to a geometry set instead of a single ID. In those cases the
- * evaluated geometry will be stored here instead of in #data_eval.
+ * Objects can evaluate to a geometry set instead of a single ID. In those cases, the evaluated
+ * geometry set will be stored here. An ID of the correct type is still stored in #data_eval.
+ * #geometry_set_eval might reference the ID pointed to by #data_eval as well, but does not own
+ * the data.
*/
struct GeometrySet *geometry_set_eval;