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:
authorJacques Lucke <jacques@blender.org>2021-02-18 12:13:56 +0300
committerJacques Lucke <jacques@blender.org>2021-02-18 12:13:56 +0300
commit999abee874bd7d69f6a40c27969598869799e8dc (patch)
tree96c8abe083aad1b289406e9178e43e83fbea9a02 /source/blender/blenkernel
parent1bcc8f84105a7715655bc42ec12eca41d06c38cf (diff)
Geometry Nodes: convert point cloud to mesh vertices for modifiers
Previously, when a Geometry Nodes modifier outputs a point cloud (e.g. generated using the Point Distribute node), other modifiers could not use that data. Now, the point cloud data is converted to mesh vertices for such modifiers. Ref T85281. Differential Revision: https://developer.blender.org/D10451
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_geometry_set_instances.hh3
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc5
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc170
3 files changed, 113 insertions, 65 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh
index 4f3c9c65203..f918adaff7c 100644
--- a/source/blender/blenkernel/BKE_geometry_set_instances.hh
+++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh
@@ -41,6 +41,7 @@ struct GeometryInstanceGroup {
Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &geometry_set);
+GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set);
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
struct AttributeInfo {
@@ -54,7 +55,7 @@ struct AttributeInfo {
* attribute with the given name on all of the input components.
*/
void gather_attribute_info(Map<std::string, AttributeInfo> &attributes,
- const GeometryComponentType component_type,
+ Span<GeometryComponentType> component_types,
Span<bke::GeometryInstanceGroup> set_groups,
const Set<std::string> &ignored_attributes);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 213e72d496b..4aa7cfae009 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -890,7 +890,7 @@ void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval,
*/
static Mesh *prepare_geometry_set_for_mesh_modifier(Mesh *mesh, GeometrySet &r_geometry_set)
{
- if (!r_geometry_set.has_instances()) {
+ if (!r_geometry_set.has_instances() && !r_geometry_set.has_pointcloud()) {
return mesh;
}
@@ -901,7 +901,8 @@ static Mesh *prepare_geometry_set_for_mesh_modifier(Mesh *mesh, GeometrySet &r_g
}
{
/* Combine mesh and all instances into a single mesh that can be passed to the modifier. */
- GeometrySet new_geometry_set = blender::bke::geometry_set_realize_instances(r_geometry_set);
+ GeometrySet new_geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(
+ r_geometry_set);
MeshComponent &mesh_component = new_geometry_set.get_component_for_write<MeshComponent>();
Mesh *new_mesh = mesh_component.release();
r_geometry_set = new_geometry_set;
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 436fc0f1d1d..66c7f53cdf5 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -24,6 +24,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_pointcloud_types.h"
namespace blender::bke {
@@ -165,44 +166,47 @@ Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &g
}
void gather_attribute_info(Map<std::string, AttributeInfo> &attributes,
- const GeometryComponentType component_type,
+ Span<GeometryComponentType> component_types,
Span<GeometryInstanceGroup> set_groups,
const Set<std::string> &ignored_attributes)
{
for (const GeometryInstanceGroup &set_group : set_groups) {
const GeometrySet &set = set_group.geometry_set;
- if (!set.has(component_type)) {
- continue;
- }
- const GeometryComponent &component = *set.get_component_for_read(component_type);
-
- for (const std::string &name : component.attribute_names()) {
- if (ignored_attributes.contains(name)) {
+ for (const GeometryComponentType component_type : component_types) {
+ if (!set.has(component_type)) {
continue;
}
- const ReadAttributePtr read_attribute = component.attribute_try_get_for_read(name);
- if (!read_attribute) {
- continue;
+ const GeometryComponent &component = *set.get_component_for_read(component_type);
+
+ for (const std::string &name : component.attribute_names()) {
+ if (ignored_attributes.contains(name)) {
+ continue;
+ }
+ const ReadAttributePtr read_attribute = component.attribute_try_get_for_read(name);
+ if (!read_attribute) {
+ continue;
+ }
+ const AttributeDomain domain = read_attribute->domain();
+ const CustomDataType data_type = read_attribute->custom_data_type();
+
+ auto add_info = [&, data_type, domain](AttributeInfo *info) {
+ info->domain = domain;
+ info->data_type = data_type;
+ };
+ auto modify_info = [&, data_type, domain](AttributeInfo *info) {
+ info->domain = domain; /* TODO: Use highest priority domain. */
+ info->data_type = bke::attribute_data_type_highest_complexity(
+ {info->data_type, data_type});
+ };
+
+ attributes.add_or_modify(name, add_info, modify_info);
}
- const AttributeDomain domain = read_attribute->domain();
- const CustomDataType data_type = read_attribute->custom_data_type();
-
- auto add_info = [&, data_type, domain](AttributeInfo *info) {
- info->domain = domain;
- info->data_type = data_type;
- };
- auto modify_info = [&, data_type, domain](AttributeInfo *info) {
- info->domain = domain; /* TODO: Use highest priority domain. */
- info->data_type = bke::attribute_data_type_highest_complexity(
- {info->data_type, data_type});
- };
-
- attributes.add_or_modify(name, add_info, modify_info);
}
}
}
-static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups)
+static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups,
+ const bool convert_points_to_vertices)
{
int totverts = 0;
int totloops = 0;
@@ -214,17 +218,22 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
int64_t cd_dirty_loop = 0;
for (const GeometryInstanceGroup &set_group : set_groups) {
const GeometrySet &set = set_group.geometry_set;
+ const int tot_transforms = set_group.transforms.size();
if (set.has_mesh()) {
const Mesh &mesh = *set.get_mesh_for_read();
- totverts += mesh.totvert * set_group.transforms.size();
- totloops += mesh.totloop * set_group.transforms.size();
- totedges += mesh.totedge * set_group.transforms.size();
- totpolys += mesh.totpoly * set_group.transforms.size();
+ totverts += mesh.totvert * tot_transforms;
+ totloops += mesh.totloop * tot_transforms;
+ totedges += mesh.totedge * tot_transforms;
+ totpolys += mesh.totpoly * tot_transforms;
cd_dirty_vert |= mesh.runtime.cd_dirty_vert;
cd_dirty_poly |= mesh.runtime.cd_dirty_poly;
cd_dirty_edge |= mesh.runtime.cd_dirty_edge;
cd_dirty_loop |= mesh.runtime.cd_dirty_loop;
}
+ if (convert_points_to_vertices && set.has_pointcloud()) {
+ const PointCloud &pointcloud = *set.get_pointcloud_for_read();
+ totverts += pointcloud.totpoint * tot_transforms;
+ }
}
Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys);
@@ -287,13 +296,25 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
poly_offset += mesh.totpoly;
}
}
+ if (convert_points_to_vertices && set.has_pointcloud()) {
+ const PointCloud &pointcloud = *set.get_pointcloud_for_read();
+ for (const float4x4 &transform : set_group.transforms) {
+ for (const int i : IndexRange(pointcloud.totpoint)) {
+ MVert &new_vert = new_mesh->mvert[vert_offset + i];
+ const float3 old_position = pointcloud.co[i];
+ const float3 new_position = transform * old_position;
+ copy_v3_v3(new_vert.co, new_position);
+ }
+ vert_offset += pointcloud.totpoint;
+ }
+ }
}
return new_mesh;
}
static void join_attributes(Span<GeometryInstanceGroup> set_groups,
- const GeometryComponentType component_type,
+ Span<GeometryComponentType> component_types,
const Map<std::string, AttributeInfo> &attribute_info,
GeometryComponent &result)
{
@@ -315,26 +336,28 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
int offset = 0;
for (const GeometryInstanceGroup &set_group : set_groups) {
const GeometrySet &set = set_group.geometry_set;
- if (set.has(component_type)) {
- const GeometryComponent &component = *set.get_component_for_read(component_type);
- const int domain_size = component.attribute_domain_size(domain_output);
- if (domain_size == 0) {
- continue; /* Domain size is 0, so no need to increment the offset. */
- }
- ReadAttributePtr source_attribute = component.attribute_try_get_for_read(
- name, domain_output, data_type_output);
-
- if (source_attribute) {
- fn::GSpan src_span = source_attribute->get_span();
- const void *src_buffer = src_span.data();
- for (const int UNUSED(i) : set_group.transforms.index_range()) {
- void *dst_buffer = dst_span[offset];
- cpp_type->copy_to_initialized_n(src_buffer, dst_buffer, domain_size);
- offset += domain_size;
+ for (const GeometryComponentType component_type : component_types) {
+ if (set.has(component_type)) {
+ const GeometryComponent &component = *set.get_component_for_read(component_type);
+ const int domain_size = component.attribute_domain_size(domain_output);
+ if (domain_size == 0) {
+ continue; /* Domain size is 0, so no need to increment the offset. */
+ }
+ ReadAttributePtr source_attribute = component.attribute_try_get_for_read(
+ name, domain_output, data_type_output);
+
+ if (source_attribute) {
+ fn::GSpan src_span = source_attribute->get_span();
+ const void *src_buffer = src_span.data();
+ for (const int UNUSED(i) : set_group.transforms.index_range()) {
+ void *dst_buffer = dst_span[offset];
+ cpp_type->copy_to_initialized_n(src_buffer, dst_buffer, domain_size);
+ offset += domain_size;
+ }
+ }
+ else {
+ offset += domain_size * set_group.transforms.size();
}
- }
- else {
- offset += domain_size * set_group.transforms.size();
}
}
}
@@ -343,21 +366,27 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
}
}
-static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups, GeometrySet &result)
+static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups,
+ bool convert_points_to_vertices,
+ GeometrySet &result)
{
- Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups);
+ Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups,
+ convert_points_to_vertices);
MeshComponent &dst_component = result.get_component_for_write<MeshComponent>();
dst_component.replace(new_mesh);
+ Vector<GeometryComponentType> component_types;
+ component_types.append(GeometryComponentType::Mesh);
+ if (convert_points_to_vertices) {
+ component_types.append(GeometryComponentType::PointCloud);
+ }
+
/* Don't copy attributes that are stored directly in the mesh data structs. */
Map<std::string, AttributeInfo> attributes;
- gather_attribute_info(
- attributes, GeometryComponentType::Mesh, set_groups, {"position", "material_index"});
- join_attributes(set_groups,
- GeometryComponentType::Mesh,
- attributes,
- static_cast<GeometryComponent &>(dst_component));
+ gather_attribute_info(attributes, component_types, set_groups, {"position", "material_index"});
+ join_attributes(
+ set_groups, component_types, attributes, static_cast<GeometryComponent &>(dst_component));
}
static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_groups,
@@ -376,9 +405,9 @@ static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_grou
PointCloud *pointcloud = BKE_pointcloud_new_nomain(totpoint);
dst_component.replace(pointcloud);
Map<std::string, AttributeInfo> attributes;
- gather_attribute_info(attributes, GeometryComponentType::Mesh, set_groups, {});
+ gather_attribute_info(attributes, {GeometryComponentType::PointCloud}, set_groups, {});
join_attributes(set_groups,
- GeometryComponentType::PointCloud,
+ {GeometryComponentType::PointCloud},
attributes,
static_cast<GeometryComponent &>(dst_component));
}
@@ -392,6 +421,23 @@ static void join_instance_groups_volume(Span<GeometryInstanceGroup> set_groups,
UNUSED_VARS(set_groups, dst_component);
}
+GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set)
+{
+ if (!geometry_set.has_instances() && !geometry_set.has_pointcloud()) {
+ return geometry_set;
+ }
+
+ GeometrySet new_geometry_set = geometry_set;
+ Vector<GeometryInstanceGroup> set_groups = geometry_set_gather_instances(geometry_set);
+ join_instance_groups_mesh(set_groups, true, new_geometry_set);
+ /* Remove all instances, even though some might contain other non-mesh data. We can't really
+ * keep only non-mesh instances in general. */
+ new_geometry_set.remove<InstancesComponent>();
+ /* If there was a point cloud, it is now part of the mesh. */
+ new_geometry_set.remove<PointCloudComponent>();
+ return new_geometry_set;
+}
+
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
{
if (!geometry_set.has_instances()) {
@@ -400,8 +446,8 @@ GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
GeometrySet new_geometry_set;
- Vector<GeometryInstanceGroup> set_groups = bke::geometry_set_gather_instances(geometry_set);
- join_instance_groups_mesh(set_groups, new_geometry_set);
+ Vector<GeometryInstanceGroup> set_groups = geometry_set_gather_instances(geometry_set);
+ join_instance_groups_mesh(set_groups, false, new_geometry_set);
join_instance_groups_pointcloud(set_groups, new_geometry_set);
join_instance_groups_volume(set_groups, new_geometry_set);