[Bf-blender-cvs] [6a7fd511804] temp-geometry-nodes-instances-api-v2: Geometry Nodes: Better support instances in point instance node
Hans Goudey
noreply at git.blender.org
Thu Feb 4 06:57:00 CET 2021
Commit: 6a7fd51180417b836917d23f3973f88889fe74cb
Author: Hans Goudey
Date: Wed Feb 3 23:56:56 2021 -0600
Branches: temp-geometry-nodes-instances-api-v2
https://developer.blender.org/rB6a7fd51180417b836917d23f3973f88889fe74cb
Geometry Nodes: Better support instances in point instance node
This does the elimination by distance in a single step for all instances
instead of treating each input mesh separately.
This needs some cleanup, but the bigger TODO is that attribute interpolation
gets a fair amount more complex with this implementation. Needs more thought.
===================================================================
M source/blender/blenkernel/BKE_geometry_set.hh
M source/blender/blenkernel/intern/geometry_set.cc
M source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 0ea43202b4a..771664ef209 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -483,6 +483,26 @@ using ForeachGeometryCallbackConst = std::function<void(
void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
const ForeachGeometryCallbackConst &callback);
-using GeometrySetGroup = std::pair<GeometrySet, blender::Vector<blender::float4x4>>;
-blender::Vector<GeometrySetGroup> BKE_geometry_set_gather_instanced(
+/**
+ * Used to keep track of a group of instances using the same geometry data.
+ *
+ * \note In the future, this can be used to store "geometry set instances".
+ */
+struct GeometryInstanceGroup {
+ /**
+ * The geometry set instanced on each of the transforms. The components are not necessarily
+ * owned here. For example, they may be owned by the instanced object. This cannot be a
+ * reference because not all instanced data will necessarily have a #geometry_set_eval.
+ */
+ GeometrySet geometry_set;
+
+ /**
+ * As an optimization to avoid copying, the same geometry set can be associated with multiple
+ * instances. Each instance is stored as a transform matrix here. Again, these must be owned
+ * because they may be transformed from the original data. TODO: Validate that last statement.
+ */
+ blender::Vector<blender::float4x4> transforms;
+};
+
+blender::Vector<GeometryInstanceGroup> BKE_geometry_set_gather_instanced(
const GeometrySet &geometry_set);
\ 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 b0023e2ad0c..f1f156de531 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -593,14 +593,20 @@ static GeometrySet object_get_geometry_set_for_read(const Object &object)
mesh_component.copy_vertex_group_names_from_object(object);
}
}
- // else if (object.type == OB_VOLUME) {
- // Volume *volume = BKE_modifier_get_volume...
- // }
+ /* TODO: Cover the case of pointclouds without modifiers,
+ * they may not be covered by the #geometry_set_eval case above. */
+ /* TODO: Add volume support. */
/* Return by value since there is no existing geometry set owned elsewhere to use. */
return new_geometry_set;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Geometry Set Instances Callback
+ * \{ */
+
static void foreach_geometry_component_recursive(const GeometrySet &geometry_set,
const ForeachGeometryCallbackConst &callback,
const float4x4 &transform);
@@ -664,6 +670,13 @@ static void foreach_geometry_component_recursive(const GeometrySet &geometry_set
}
}
+/**
+ * Execute a callback for every component of a geometry set. This approach is used to avoid
+ * allocating a temporary vector the store the flattened instances before operation.
+ *
+ * \note For convenience (to avoid duplication in the caller),
+ * this also executes the callback for the argument geometry set.
+ */
void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
const ForeachGeometryCallbackConst &callback)
{
@@ -673,18 +686,19 @@ void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
foreach_geometry_component_recursive(geometry_set, callback, unit_transform);
}
-/* ============= API 2 =============== */
+/** \} */
-using GeometrySetGroup = std::pair<GeometrySet, Vector<float4x4>>;
+/* -------------------------------------------------------------------- */
+/** \name Geometry Set Gather Recursive Instances
+ * \{ */
-static void collect_geometry_set_recursive(
- const GeometrySet &geometry_set,
- const float4x4 &transform,
- Vector<std::pair<GeometrySet, Vector<float4x4>>> &r_sets);
+static void collect_geometry_set_recursive(const GeometrySet &geometry_set,
+ const float4x4 &transform,
+ Vector<GeometryInstanceGroup> &r_sets);
static void collect_collection_geometry_set_recursive(const Collection &collection,
const float4x4 &transform,
- Vector<GeometrySetGroup> &r_sets)
+ Vector<GeometryInstanceGroup> &r_sets)
{
LISTBASE_FOREACH (const CollectionObject *, collection_object, &collection.gobject) {
BLI_assert(collection_object->ob != nullptr);
@@ -704,7 +718,7 @@ static void collect_collection_geometry_set_recursive(const Collection &collecti
static void collect_geometry_set_recursive(const GeometrySet &geometry_set,
const float4x4 &transform,
- Vector<GeometrySetGroup> &r_sets)
+ Vector<GeometryInstanceGroup> &r_sets)
{
r_sets.append({geometry_set, {transform}});
@@ -733,9 +747,17 @@ static void collect_geometry_set_recursive(const GeometrySet &geometry_set,
}
}
-Vector<GeometrySetGroup> BKE_geometry_set_gather_instanced(const GeometrySet &geometry_set)
+/**
+ * Return a vector of geometry sets, including a flattened array of instances. This approach
+ * (as opposed to #BKE_foreach_geometry_component_recursive) can be used where multiple iterations
+ * over the input data are needed, or where it simplifies code enough.
+ *
+ * \note For convenience (to avoid duplication in the caller),
+ * the returned vector also contains the argument geometry set.
+ */
+Vector<GeometryInstanceGroup> BKE_geometry_set_gather_instanced(const GeometrySet &geometry_set)
{
- Vector<GeometrySetGroup> result_vector;
+ Vector<GeometryInstanceGroup> result_vector;
float4x4 unit_transform;
unit_m4(unit_transform.values);
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 e7f20d98d56..7a414ec049b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -57,6 +57,7 @@ static void node_point_distribute_update(bNodeTree *UNUSED(ntree), bNode *node)
}
namespace blender::nodes {
+
struct AttributeInfo {
CustomDataType data_type;
AttributeDomain domain;
@@ -82,17 +83,18 @@ static Span<MLoopTri> get_mesh_looptris(const Mesh &mesh)
return {looptris, looptris_len};
}
-static void sample_mesh_surface(const Mesh &mesh,
- const float4x4 &transform,
- const float base_density,
- const FloatReadAttribute *density_factors,
- const int seed,
- Vector<float3> &r_positions,
- Vector<float3> &r_bary_coords,
- Vector<int> &r_looptri_indices)
+static int sample_mesh_surface(const Mesh &mesh,
+ const float4x4 &transform,
+ const float base_density,
+ const FloatReadAttribute *density_factors,
+ const int seed,
+ Vector<float3> &r_positions,
+ Vector<float3> &r_bary_coords,
+ Vector<int> &r_looptri_indices)
{
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
+ int points_len = 0;
for (const int looptri_index : looptris.index_range()) {
const MLoopTri &looptri = looptris[looptri_index];
const int v0_index = mesh.mloop[looptri.tri[0]].v;
@@ -127,73 +129,54 @@ static void sample_mesh_surface(const Mesh &mesh,
r_positions.append(point_pos);
r_bary_coords.append(bary_coord);
r_looptri_indices.append(looptri_index);
+ points_len++;
}
}
+ return points_len;
}
-BLI_NOINLINE static KDTree_3d *build_kdtree(Span<Vector<float3>> all_positions)
+BLI_NOINLINE static KDTree_3d *build_kdtree(Span<float3> positions)
{
- for (Vector<float3> positions : all_positions) {
- for (const float3 position : positions) {
- }
- }
KDTree_3d *kdtree = BLI_kdtree_3d_new(positions.size());
- int i = 0;
- for (Vector<float3> positions : all_positions) {
- for (const float3 position : positions) {
- BLI_kdtree_3d_insert(kdtree, i, positions[i]);
- i++;
- }
+ for (const int i : positions.index_range()) {
+ BLI_kdtree_3d_insert(kdtree, i, positions[i]);
}
BLI_kdtree_3d_balance(kdtree);
return kdtree;
}
BLI_NOINLINE static void update_elimination_mask_for_close_points(
- Span<Vector<float3>> positions_per_instance,
- const float minimum_distance,
- MutableSpan<bool> elimination_mask_per_instance)
+ Span<float3> positions, const float minimum_distance, MutableSpan<bool> elimination_mask)
{
if (minimum_distance <= 0.0f) {
return;
}
- for (const int i_set : get_groups.index_range()) {
- const GeometrySetGroup &set_group = get_groups[i_set];
- const GeometrySet &set = set_group.first;
- if (!set.has_mesh()) {
- continue;
- }
- const Mesh &mesh = *set.get_mesh_for_read();
- for (const float4x4 &transform : set_group.second) {
- }
- }
KDTree_3d *kdtree = build_kdtree(positions);
- for (const int i_instance :)
- for (const int i : positions.index_range()) {
- if (elimination_mask[i]) {
- continue;
- }
-
- struct CallbackData {
- int index;
- MutableSpan<bool> elimination_mask;
- } callback_data = {i, elimination_mask};
-
- BLI_kdtree_3d_range_search_cb(
- kdtree,
- positions[i],
- minimum_distance,
- [](void *user_data, int index, const float *UNUSED(co), float UN
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list