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/BKE_geometry_set.hh6
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc107
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_object_info.cc36
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc83
4 files changed, 171 insertions, 61 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 51f7507bd6c..5d21eff43b9 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -474,3 +474,9 @@ class VolumeComponent : public GeometryComponent {
static constexpr inline GeometryComponentType static_type = GeometryComponentType::Volume;
};
+
+using ForeachGeometryCallbackConst = std::function<void(
+ const GeometryComponent &component, blender::Span<blender::float4x4> transforms)>;
+
+void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
+ const ForeachGeometryCallbackConst &callback); \ No newline at end of file
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 833e1dd3719..6c4de64861d 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -14,19 +14,24 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "BLI_listbase_wrapper.hh" /* TODO: Couldn't figure this out yet. */
+
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_wrapper.h"
+#include "BKE_modifier.h"
#include "BKE_pointcloud.h"
#include "BKE_volume.h"
+#include "DNA_collection_types.h"
#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
using blender::float3;
using blender::float4x4;
+using blender::ListBaseWrapper;
using blender::MutableSpan;
using blender::Span;
using blender::StringRef;
@@ -549,6 +554,108 @@ bool InstancesComponent::is_empty() const
return transforms_.size() == 0;
}
+static void foreach_geometry_component_recursive(const GeometrySet &geometry_set,
+ const ForeachGeometryCallbackConst &callback,
+ const float4x4 &transform);
+
+static GeometrySet object_get_geometry_set_for_read(const Object &object)
+{
+ /* Objects evaluated with a nodes modifier will have a geometry set already. */
+ if (object.runtime.geometry_set_eval != nullptr) {
+ return *object.runtime.geometry_set_eval;
+ }
+
+ /* Otherwise, construct a new geometry set with the component based on the object type. */
+ GeometrySet new_geometry_set;
+
+ if (object.type == OB_MESH) {
+ Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(
+ &const_cast<Object &>(object), false);
+
+ if (mesh != nullptr) {
+ BKE_mesh_wrapper_ensure_mdata(mesh);
+
+ MeshComponent &mesh_component = new_geometry_set.get_component_for_write<MeshComponent>();
+ mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
+ mesh_component.copy_vertex_group_names_from_object(object);
+ }
+ }
+ // else if (object.type == OB_VOLUME) {
+ // Volume *volume = BKE_modifier_get_volume...
+ // }
+
+ /* Return by value since there is no existing geometry set owned elsewhere to use. */
+ return new_geometry_set;
+}
+
+static void foreach_collection_geometry_set_recursive(const Collection &collection,
+ const ForeachGeometryCallbackConst &callback,
+ const float4x4 &transform)
+{
+ LISTBASE_FOREACH (const CollectionObject *, collection_object, &collection.gobject) {
+ BLI_assert(collection_object->ob != nullptr);
+ const Object &object = *collection_object->ob;
+ GeometrySet instance_geometry_set = object_get_geometry_set_for_read(object);
+
+ /* TODO: This seems to work-- validate this. */
+ const float4x4 instance_transform = transform * object.obmat;
+ foreach_geometry_component_recursive(instance_geometry_set, callback, instance_transform);
+ }
+ LISTBASE_FOREACH (const CollectionChild *, collection_child, &collection.children) {
+ BLI_assert(collection_child->collection != nullptr);
+ const Collection &collection = *collection_child->collection;
+ foreach_collection_geometry_set_recursive(collection, callback, transform);
+ }
+}
+
+static void foreach_geometry_component_recursive(const GeometrySet &geometry_set,
+ const ForeachGeometryCallbackConst &callback,
+ const float4x4 &transform)
+{
+ if (geometry_set.has_mesh()) {
+ callback(*geometry_set.get_component_for_read<MeshComponent>(), {transform});
+ }
+ if (geometry_set.has_pointcloud()) {
+ callback(*geometry_set.get_component_for_read<PointCloudComponent>(), {transform});
+ }
+ if (geometry_set.has_volume()) {
+ callback(*geometry_set.get_component_for_read<VolumeComponent>(), {transform});
+ }
+
+ if (geometry_set.has_instances()) {
+ const InstancesComponent &instances_component =
+ *geometry_set.get_component_for_read<InstancesComponent>();
+
+ Span<float4x4> transforms = instances_component.transforms();
+ Span<InstancedData> instances = instances_component.instanced_data();
+ for (const int i : instances.index_range()) {
+ const InstancedData &data = instances[i];
+ const float4x4 &transform = transforms[i];
+
+ if (data.type == INSTANCE_DATA_TYPE_OBJECT) {
+ BLI_assert(data.data.object != nullptr);
+ const Object &object = *data.data.object;
+ GeometrySet instance_geometry_set = object_get_geometry_set_for_read(object);
+ foreach_geometry_component_recursive(instance_geometry_set, callback, transform);
+ }
+ else if (data.type == INSTANCE_DATA_TYPE_COLLECTION) {
+ BLI_assert(data.data.collection != nullptr);
+ const Collection &collection = *data.data.collection;
+ foreach_collection_geometry_set_recursive(collection, callback, transform);
+ }
+ }
+ }
+}
+
+void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
+ const ForeachGeometryCallbackConst &callback)
+{
+ float4x4 unit_transform;
+ unit_m4(unit_transform.values);
+
+ foreach_geometry_component_recursive(geometry_set, callback, unit_transform);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
index d713c191d5d..bc36ff809fa 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
@@ -69,35 +69,15 @@ static void geo_node_object_info_exec(GeoNodeExecParams params)
quat_to_eul(rotation, quaternion);
if (object != self_object) {
- if (object->type == OB_MESH) {
- Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object, false);
- if (mesh != nullptr) {
- BKE_mesh_wrapper_ensure_mdata(mesh);
-
- /* Make a copy because the life time of the other mesh might be shorter. */
- Mesh *copied_mesh = BKE_mesh_copy_for_eval(mesh, false);
-
- if (transform_space_relative) {
- /* Transform into the local space of the object that is being modified. */
- BKE_mesh_transform(copied_mesh, transform, true);
- }
-
- MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
- mesh_component.replace(copied_mesh);
- mesh_component.copy_vertex_group_names_from_object(*object);
- }
+ InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
+
+ if (transform_space_relative) {
+ instances.add_instance(object, transform);
}
- if (object->type == OB_VOLUME) {
- InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
-
- if (transform_space_relative) {
- instances.add_instance(object, transform);
- }
- else {
- float unit_transform[4][4];
- unit_m4(unit_transform);
- instances.add_instance(object, unit_transform);
- }
+ else {
+ float unit_transform[4][4];
+ unit_m4(unit_transform);
+ instances.add_instance(object, unit_transform);
}
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index eaf13b94eb9..2a3a72d990d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -79,6 +79,7 @@ static Span<MLoopTri> get_mesh_looptris(const Mesh &mesh)
}
static void sample_mesh_surface(const Mesh &mesh,
+ const float4x4 transform,
const float base_density,
const FloatReadAttribute *density_factors,
const int seed,
@@ -93,9 +94,10 @@ static void sample_mesh_surface(const Mesh &mesh,
const int v0_index = mesh.mloop[looptri.tri[0]].v;
const int v1_index = mesh.mloop[looptri.tri[1]].v;
const int v2_index = mesh.mloop[looptri.tri[2]].v;
- const float3 v0_pos = mesh.mvert[v0_index].co;
- const float3 v1_pos = mesh.mvert[v1_index].co;
- const float3 v2_pos = mesh.mvert[v2_index].co;
+
+ const float3 v0_pos = transform * float3(mesh.mvert[v0_index].co);
+ const float3 v1_pos = transform * float3(mesh.mvert[v1_index].co);
+ const float3 v2_pos = transform * float3(mesh.mvert[v2_index].co);
float looptri_density_factor = 1.0f;
if (density_factors != nullptr) {
@@ -387,6 +389,7 @@ BLI_NOINLINE static void add_remaining_point_attributes(const MeshComponent &mes
}
static void sample_mesh_surface_with_minimum_distance(const Mesh &mesh,
+ const float4x4 transform,
const float max_density,
const float minimum_distance,
const FloatReadAttribute &density_factors,
@@ -396,7 +399,7 @@ static void sample_mesh_surface_with_minimum_distance(const Mesh &mesh,
Vector<int> &r_looptri_indices)
{
sample_mesh_surface(
- mesh, max_density, nullptr, seed, r_positions, r_bary_coords, r_looptri_indices);
+ mesh, transform, max_density, nullptr, seed, r_positions, r_bary_coords, r_looptri_indices);
Array<bool> elimination_mask(r_positions.size(), false);
update_elimination_mask_for_close_points(r_positions, minimum_distance, elimination_mask);
update_elimination_mask_based_on_density_factors(
@@ -412,7 +415,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
GeometryNodePointDistributeMethod distribute_method =
static_cast<GeometryNodePointDistributeMethod>(params.node().custom1);
- if (!geometry_set.has_mesh()) {
+ if (!geometry_set.has_mesh() && !geometry_set.has_instances()) {
params.set_output("Geometry", std::move(geometry_set_out));
return;
}
@@ -425,38 +428,52 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
return;
}
- const MeshComponent &mesh_component = *geometry_set.get_component_for_read<MeshComponent>();
- const Mesh *mesh_in = mesh_component.get_for_read();
-
- if (mesh_in == nullptr || mesh_in->mpoly == nullptr) {
- params.set_output("Geometry", std::move(geometry_set_out));
- return;
- }
-
- const FloatReadAttribute density_factors = mesh_component.attribute_get_for_read<float>(
- density_attribute, ATTR_DOMAIN_POINT, 1.0f);
const int seed = params.get_input<int>("Seed");
Vector<float3> positions;
Vector<float3> bary_coords;
Vector<int> looptri_indices;
- switch (distribute_method) {
- case GEO_NODE_POINT_DISTRIBUTE_RANDOM:
- sample_mesh_surface(
- *mesh_in, density, &density_factors, seed, positions, bary_coords, looptri_indices);
- break;
- case GEO_NODE_POINT_DISTRIBUTE_POISSON:
- const float minimum_distance = params.extract_input<float>("Distance Min");
- sample_mesh_surface_with_minimum_distance(*mesh_in,
- density,
- minimum_distance,
- density_factors,
- seed,
- positions,
- bary_coords,
- looptri_indices);
- break;
- }
+ BKE_foreach_geometry_component_recursive(
+ geometry_set,
+ [&](const GeometryComponent &component, blender::Span<blender::float4x4> transforms) {
+ if (component.type() != GeometryComponentType::Mesh) {
+ return;
+ }
+
+ const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
+ const Mesh *mesh_in = mesh_component.get_for_read();
+ if (mesh_in == nullptr || mesh_in->mpoly == nullptr) {
+ return;
+ }
+ const FloatReadAttribute density_factors = mesh_component.attribute_get_for_read<float>(
+ density_attribute, ATTR_DOMAIN_POINT, 1.0f);
+
+ switch (distribute_method) {
+ case GEO_NODE_POINT_DISTRIBUTE_RANDOM:
+ sample_mesh_surface(*mesh_in,
+ transforms[0],
+ density,
+ &density_factors,
+ seed,
+ positions,
+ bary_coords,
+ looptri_indices);
+ break;
+ case GEO_NODE_POINT_DISTRIBUTE_POISSON:
+ const float minimum_distance = params.get_input<float>("Distance Min");
+ sample_mesh_surface_with_minimum_distance(*mesh_in,
+ transforms[0],
+ density,
+ minimum_distance,
+ density_factors,
+ seed,
+ positions,
+ bary_coords,
+ looptri_indices);
+ break;
+ }
+ });
+
const int tot_points = positions.size();
PointCloud *pointcloud = BKE_pointcloud_new_nomain(tot_points);
@@ -470,7 +487,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
geometry_set_out.get_component_for_write<PointCloudComponent>();
point_component.replace(pointcloud);
- add_remaining_point_attributes(mesh_component, point_component, bary_coords, looptri_indices);
+ // add_remaining_point_attributes(mesh_component, point_component, bary_coords, looptri_indices);
params.set_output("Geometry", std::move(geometry_set_out));
}