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_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh1
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc10
-rw-r--r--source/blender/blenloader/intern/versioning_300.c75
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_boolean.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc64
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc47
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_length.cc1
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc23
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc53
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc43
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_material_replace.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc47
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_separate_components.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_triangulate.cc16
17 files changed, 279 insertions, 131 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index b973d8b9a18..5ef0459663b 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 27
+#define BLENDER_FILE_SUBVERSION 28
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 4954b1d5ab2..724ca224cab 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -330,6 +330,7 @@ struct GeometrySet {
bool has_volume() const;
bool has_curve() const;
bool has_realized_data() const;
+ bool is_empty() const;
const Mesh *get_mesh_for_read() const;
const PointCloud *get_pointcloud_for_read() const;
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 400e0fda518..0aac6ae3adf 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -318,6 +318,16 @@ bool GeometrySet::has_realized_data() const
return this->get_component_for_read<InstancesComponent>() == nullptr;
}
+/* Return true if the geometry set has any component that isn't empty. */
+bool GeometrySet::is_empty() const
+{
+ if (components_.is_empty()) {
+ return true;
+ }
+ return !(this->has_mesh() || this->has_curve() || this->has_pointcloud() ||
+ this->has_instances());
+}
+
/* Create a new geometry set that only contains the given mesh. */
GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership)
{
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 86755cbaf95..3b51e40c218 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -449,6 +449,73 @@ static void do_versions_sequencer_speed_effect_recursive(Scene *scene, const Lis
#undef SEQ_SPEED_COMPRESS_IPO_Y
}
+static bNodeLink *find_connected_link(bNodeTree *ntree, bNodeSocket *in_socket)
+{
+ LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
+ if (link->tosock == in_socket) {
+ return link;
+ }
+ }
+ return NULL;
+}
+
+static void add_realize_instances_before_socket(bNodeTree *ntree,
+ bNode *node,
+ bNodeSocket *geometry_socket)
+{
+ BLI_assert(geometry_socket->type == SOCK_GEOMETRY);
+ bNodeLink *link = find_connected_link(ntree, geometry_socket);
+ if (link == NULL) {
+ return;
+ }
+
+ /* If the realize instances node is already before this socket, no need to continue. */
+ if (link->fromnode->type == GEO_NODE_REALIZE_INSTANCES) {
+ return;
+ }
+
+ bNode *realize_node = nodeAddStaticNode(NULL, ntree, GEO_NODE_REALIZE_INSTANCES);
+ realize_node->parent = node->parent;
+ realize_node->locx = node->locx - 100;
+ realize_node->locy = node->locy;
+ nodeAddLink(ntree, link->fromnode, link->fromsock, realize_node, realize_node->inputs.first);
+ link->fromnode = realize_node;
+ link->fromsock = realize_node->outputs.first;
+}
+
+/**
+ * If a node used to realize instances implicitly and will no longer do so in 3.0, add a "Realize
+ * Instances" node in front of it to avoid changing behavior. Don't do this if the node will be
+ * replaced anyway though.
+ */
+static void version_geometry_nodes_add_realize_instance_nodes(bNodeTree *ntree)
+{
+ LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
+ if (ELEM(node->type,
+ GEO_NODE_ATTRIBUTE_CAPTURE,
+ GEO_NODE_SEPARATE_COMPONENTS,
+ GEO_NODE_CONVEX_HULL,
+ GEO_NODE_CURVE_LENGTH,
+ GEO_NODE_BOOLEAN,
+ GEO_NODE_CURVE_FILLET,
+ GEO_NODE_CURVE_RESAMPLE,
+ GEO_NODE_CURVE_TO_MESH,
+ GEO_NODE_CURVE_TRIM,
+ GEO_NODE_MATERIAL_REPLACE,
+ GEO_NODE_MESH_SUBDIVIDE,
+ GEO_NODE_ATTRIBUTE_REMOVE,
+ GEO_NODE_TRIANGULATE)) {
+ bNodeSocket *geometry_socket = node->inputs.first;
+ add_realize_instances_before_socket(ntree, node, geometry_socket);
+ }
+ /* Also realize instances for the profile input of the curve to mesh node. */
+ if (node->type == GEO_NODE_CURVE_TO_MESH) {
+ bNodeSocket *profile_socket = node->inputs.last;
+ add_realize_instances_before_socket(ntree, node, profile_socket);
+ }
+ }
+}
+
void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
{
if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
@@ -531,6 +598,14 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 28)) {
+ LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ version_geometry_nodes_add_realize_instance_nodes(ntree);
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
index 81629a0f8b4..43fb00a482c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
@@ -117,8 +117,6 @@ static void geo_node_attribute_capture_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
- geometry_set = bke::geometry_set_realize_instances(geometry_set);
-
const bNode &node = params.node();
const NodeGeometryAttributeCapture &storage = *(const NodeGeometryAttributeCapture *)
node.storage;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc
index 21a9a338857..f93ef6f1db3 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc
@@ -47,8 +47,6 @@ static void geo_node_attribute_remove_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
Vector<std::string> attribute_names = params.extract_multi_input<std::string>("Attribute");
- geometry_set = geometry_set_realize_instances(geometry_set);
-
if (geometry_set.has<MeshComponent>()) {
remove_attribute(
geometry_set.get_component_for_write<MeshComponent>(), params, attribute_names);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
index 2a1c43a89fe..21b425c0ed4 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
@@ -83,10 +83,14 @@ static void geo_node_boolean_exec(GeoNodeExecParams params)
GeometrySet set_a;
if (operation == GEO_NODE_BOOLEAN_DIFFERENCE) {
set_a = params.extract_input<GeometrySet>("Geometry 1");
+ if (set_a.has_instances()) {
+ params.error_message_add(
+ NodeWarningType::Info,
+ TIP_("Instances are not supported for the first geometry input, and will not be used"));
+ }
/* Note that it technically wouldn't be necessary to realize the instances for the first
* geometry input, but the boolean code expects the first shape for the difference operation
* to be a single mesh. */
- set_a = geometry_set_realize_instances(set_a);
const Mesh *mesh_in_a = set_a.get_mesh_for_read();
if (mesh_in_a != nullptr) {
meshes.append(mesh_in_a);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
index f1e10e3d276..4377d32210d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
@@ -227,9 +227,13 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
return hull_from_bullet(geometry_set.get_mesh_for_read(), positions);
}
+/* Since only positions are read from the instances, this can be used as an internal optimization
+ * to avoid the cost of realizing instances before the node. But disable this for now, since
+ * re-enabling that optimization will be a separate step. */
+# if 0
static void read_positions(const GeometryComponent &component,
- Span<float4x4> transforms,
- Vector<float3> *r_coords)
+ Span<float4x4> transforms,
+ Vector<float3> *r_coords)
{
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
@@ -265,6 +269,31 @@ static void read_curve_positions(const CurveEval &curve,
}
}
+static Mesh *convex_hull_from_instances(const GeometrySet &geometry_set)
+{
+ Vector<GeometryInstanceGroup> set_groups;
+ bke::geometry_set_gather_instances(geometry_set, set_groups);
+
+ Vector<float3> coords;
+
+ for (const GeometryInstanceGroup &set_group : set_groups) {
+ const GeometrySet &set = set_group.geometry_set;
+ Span<float4x4> transforms = set_group.transforms;
+
+ if (set.has_pointcloud()) {
+ read_positions(*set.get_component_for_read<PointCloudComponent>(), transforms, &coords);
+ }
+ if (set.has_mesh()) {
+ read_positions(*set.get_component_for_read<MeshComponent>(), transforms, &coords);
+ }
+ if (set.has_curve()) {
+ read_curve_positions(*set.get_curve_for_read(), transforms, &coords);
+ }
+ }
+ return hull_from_bullet(nullptr, coords);
+}
+# endif
+
#endif /* WITH_BULLET */
static void geo_node_convex_hull_exec(GeoNodeExecParams params)
@@ -272,33 +301,14 @@ static void geo_node_convex_hull_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
#ifdef WITH_BULLET
- Mesh *mesh = nullptr;
- if (geometry_set.has_instances()) {
- Vector<GeometryInstanceGroup> set_groups;
- bke::geometry_set_gather_instances(geometry_set, set_groups);
-
- Vector<float3> coords;
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- Span<float4x4> transforms = set_group.transforms;
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ Mesh *mesh = compute_hull(geometry_set);
+ geometry_set.replace_mesh(mesh);
+ geometry_set.keep_only({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_INSTANCES});
+ });
- if (set.has_pointcloud()) {
- read_positions(*set.get_component_for_read<PointCloudComponent>(), transforms, &coords);
- }
- if (set.has_mesh()) {
- read_positions(*set.get_component_for_read<MeshComponent>(), transforms, &coords);
- }
- if (set.has_curve()) {
- read_curve_positions(*set.get_curve_for_read(), transforms, &coords);
- }
- }
- mesh = hull_from_bullet(nullptr, coords);
- }
- else {
- mesh = compute_hull(geometry_set);
- }
- params.set_output("Convex Hull", GeometrySet::create_with_mesh(mesh));
+ params.set_output("Convex Hull", std::move(geometry_set));
#else
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without Bullet"));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
index 830cfcc8331..67ce20efd9d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -563,19 +563,16 @@ static std::unique_ptr<CurveEval> fillet_curve(const CurveEval &input_curve,
return output_curve;
}
-static void geo_node_fillet_exec(GeoNodeExecParams params)
+static void calculate_curve_fillet(GeometrySet &geometry_set,
+ const GeometryNodeCurveFilletMode mode,
+ const Field<float> &radius_field,
+ const std::optional<Field<int>> &count_field,
+ const bool limit_radius)
{
- GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
-
- geometry_set = bke::geometry_set_realize_instances(geometry_set);
-
if (!geometry_set.has_curve()) {
- params.set_output("Curve", geometry_set);
return;
}
- NodeGeometryCurveFillet &node_storage = *(NodeGeometryCurveFillet *)params.node().storage;
- const GeometryNodeCurveFilletMode mode = (GeometryNodeCurveFilletMode)node_storage.mode;
FilletParam fillet_param;
fillet_param.mode = mode;
@@ -584,19 +581,16 @@ static void geo_node_fillet_exec(GeoNodeExecParams params)
const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
fn::FieldEvaluator field_evaluator{field_context, domain_size};
- Field<float> radius_field = params.extract_input<Field<float>>("Radius");
- field_evaluator.add(std::move(radius_field));
+ field_evaluator.add(radius_field);
if (mode == GEO_NODE_CURVE_FILLET_POLY) {
- Field<int> count_field = params.extract_input<Field<int>>("Count");
- field_evaluator.add(std::move(count_field));
+ field_evaluator.add(*count_field);
}
field_evaluator.evaluate();
fillet_param.radii = &field_evaluator.get_evaluated<float>(0);
if (fillet_param.radii->is_single() && fillet_param.radii->get_internal_single() < 0.0f) {
- params.set_output("Geometry", geometry_set);
return;
}
@@ -604,13 +598,36 @@ static void geo_node_fillet_exec(GeoNodeExecParams params)
fillet_param.counts = &field_evaluator.get_evaluated<int>(1);
}
- fillet_param.limit_radius = params.extract_input<bool>("Limit Radius");
+ fillet_param.limit_radius = limit_radius;
const CurveEval &input_curve = *geometry_set.get_curve_for_read();
std::unique_ptr<CurveEval> output_curve = fillet_curve(input_curve, fillet_param);
- params.set_output("Curve", GeometrySet::create_with_curve(output_curve.release()));
+ geometry_set.replace_curve(output_curve.release());
+}
+
+static void geo_node_fillet_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
+
+ NodeGeometryCurveFillet &node_storage = *(NodeGeometryCurveFillet *)params.node().storage;
+ const GeometryNodeCurveFilletMode mode = (GeometryNodeCurveFilletMode)node_storage.mode;
+
+ Field<float> radius_field = params.extract_input<Field<float>>("Radius");
+ const bool limit_radius = params.extract_input<bool>("Limit Radius");
+
+ std::optional<Field<int>> count_field;
+ if (mode == GEO_NODE_CURVE_FILLET_POLY) {
+ count_field.emplace(params.extract_input<Field<int>>("Count"));
+ }
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ calculate_curve_fillet(geometry_set, mode, radius_field, count_field, limit_radius);
+ });
+
+ params.set_output("Curve", std::move(geometry_set));
}
+
} // namespace blender::nodes
void register_node_type_geo_curve_fillet()
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
index 8fe054633a1..ac7df35bb72 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
@@ -28,7 +28,6 @@ static void geo_node_curve_length_declare(NodeDeclarationBuilder &b)
static void geo_node_curve_length_exec(GeoNodeExecParams params)
{
GeometrySet curve_set = params.extract_input<GeometrySet>("Curve");
- curve_set = bke::geometry_set_realize_instances(curve_set);
if (!curve_set.has_curve()) {
params.set_output("Length", 0.0f);
return;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index 208525f17f6..b8f62460069 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -202,20 +202,26 @@ static std::unique_ptr<CurveEval> resample_curve(const CurveEval &input_curve,
return output_curve;
}
-static void geo_node_resample_exec(GeoNodeExecParams params)
+static void geometry_set_curve_resample(GeometrySet &geometry_set,
+ const SampleModeParam &mode_param)
{
- GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
-
- geometry_set = bke::geometry_set_realize_instances(geometry_set);
-
if (!geometry_set.has_curve()) {
- params.set_output("Geometry", GeometrySet());
return;
}
const CurveEval &input_curve = *geometry_set.get_curve_for_read();
+ std::unique_ptr<CurveEval> output_curve = resample_curve(input_curve, mode_param);
+
+ geometry_set.replace_curve(output_curve.release());
+}
+
+static void geo_node_resample_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
NodeGeometryCurveResample &node_storage = *(NodeGeometryCurveResample *)params.node().storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
+
SampleModeParam mode_param;
mode_param.mode = mode;
if (mode == GEO_NODE_CURVE_RESAMPLE_COUNT) {
@@ -232,9 +238,10 @@ static void geo_node_resample_exec(GeoNodeExecParams params)
mode_param.length.emplace(resolution);
}
- std::unique_ptr<CurveEval> output_curve = resample_curve(input_curve, mode_param);
+ geometry_set.modify_geometry_sets(
+ [&](GeometrySet &geometry_set) { geometry_set_curve_resample(geometry_set, mode_param); });
- params.set_output("Geometry", GeometrySet::create_with_curve(output_curve.release()));
+ params.set_output("Geometry", std::move(geometry_set));
}
} // namespace blender::nodes
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index 89ba635ff4b..f7cef9bbf63 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -32,39 +32,52 @@ static void geo_node_curve_to_mesh_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>("Mesh");
}
-static void geo_node_curve_to_mesh_exec(GeoNodeExecParams params)
+static void geometry_set_curve_to_mesh(GeometrySet &geometry_set,
+ const GeometrySet &profile_set,
+ const GeoNodeExecParams &params)
{
- GeometrySet curve_set = params.extract_input<GeometrySet>("Curve");
- GeometrySet profile_set = params.extract_input<GeometrySet>("Profile Curve");
-
- curve_set = bke::geometry_set_realize_instances(curve_set);
- profile_set = bke::geometry_set_realize_instances(profile_set);
-
- /* NOTE: Theoretically an "is empty" check would be more correct for errors. */
- if (profile_set.has_mesh() && !profile_set.has_curve()) {
- params.error_message_add(NodeWarningType::Warning,
- TIP_("No curve data available in profile input"));
- }
-
- if (!curve_set.has_curve()) {
- if (curve_set.has_mesh()) {
+ if (!geometry_set.has_curve()) {
+ if (!geometry_set.is_empty()) {
params.error_message_add(NodeWarningType::Warning,
TIP_("No curve data available in curve input"));
}
- params.set_output("Mesh", GeometrySet());
return;
}
const CurveEval *profile_curve = profile_set.get_curve_for_read();
if (profile_curve == nullptr) {
- Mesh *mesh = bke::curve_to_wire_mesh(*curve_set.get_curve_for_read());
- params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
+ Mesh *mesh = bke::curve_to_wire_mesh(*geometry_set.get_curve_for_read());
+ geometry_set.replace_mesh(mesh);
}
else {
- Mesh *mesh = bke::curve_to_mesh_sweep(*curve_set.get_curve_for_read(), *profile_curve);
- params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
+ Mesh *mesh = bke::curve_to_mesh_sweep(*geometry_set.get_curve_for_read(), *profile_curve);
+ geometry_set.replace_mesh(mesh);
+ }
+}
+
+static void geo_node_curve_to_mesh_exec(GeoNodeExecParams params)
+{
+ GeometrySet curve_set = params.extract_input<GeometrySet>("Curve");
+ GeometrySet profile_set = params.extract_input<GeometrySet>("Profile Curve");
+
+ if (profile_set.has_instances()) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Instances are not supported in the profile input"));
+ params.set_output("Mesh", GeometrySet());
+ return;
+ }
+
+ if (!profile_set.has_curve() && !profile_set.is_empty()) {
+ params.error_message_add(NodeWarningType::Warning,
+ TIP_("No curve data available in the profile input"));
}
+
+ curve_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ geometry_set_curve_to_mesh(geometry_set, profile_set, params);
+ });
+
+ params.set_output("Mesh", std::move(curve_set));
}
} // namespace blender::nodes
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
index 2b6d25b6bf3..97043980899 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
@@ -320,28 +320,18 @@ static void trim_bezier_spline(Spline &spline,
bezier_spline.resize(size);
}
-static void geo_node_curve_trim_exec(GeoNodeExecParams params)
+static void geometry_set_curve_trim(GeometrySet &geometry_set,
+ const GeometryNodeCurveSampleMode mode,
+ const float start,
+ const float end)
{
- const NodeGeometryCurveTrim &node_storage = *(NodeGeometryCurveTrim *)params.node().storage;
- const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)node_storage.mode;
-
- GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
- geometry_set = bke::geometry_set_realize_instances(geometry_set);
if (!geometry_set.has_curve()) {
- params.set_output("Curve", std::move(geometry_set));
return;
}
- CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- CurveEval &curve = *curve_component.get_for_write();
+ CurveEval &curve = *geometry_set.get_curve_for_write();
MutableSpan<SplinePtr> splines = curve.splines();
- const float start = mode == GEO_NODE_CURVE_SAMPLE_FACTOR ?
- params.extract_input<float>("Start") :
- params.extract_input<float>("Start_001");
- const float end = mode == GEO_NODE_CURVE_SAMPLE_FACTOR ? params.extract_input<float>("End") :
- params.extract_input<float>("End_001");
-
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
Spline &spline = *splines[i];
@@ -382,6 +372,29 @@ static void geo_node_curve_trim_exec(GeoNodeExecParams params)
splines[i]->mark_cache_invalid();
}
});
+}
+
+static void geo_node_curve_trim_exec(GeoNodeExecParams params)
+{
+ const NodeGeometryCurveTrim &node_storage = *(NodeGeometryCurveTrim *)params.node().storage;
+ const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)node_storage.mode;
+
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
+
+ if (mode == GEO_NODE_CURVE_SAMPLE_FACTOR) {
+ const float start = params.extract_input<float>("Start");
+ const float end = params.extract_input<float>("End");
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ geometry_set_curve_trim(geometry_set, mode, start, end);
+ });
+ }
+ else if (mode == GEO_NODE_CURVE_SAMPLE_LENGTH) {
+ const float start = params.extract_input<float>("Start_001");
+ const float end = params.extract_input<float>("End_001");
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ geometry_set_curve_trim(geometry_set, mode, start, end);
+ });
+ }
params.set_output("Curve", std::move(geometry_set));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc b/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc
index a9c3bfc6ce0..a917434fa00 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc
@@ -40,11 +40,9 @@ static void geo_node_material_replace_exec(GeoNodeExecParams params)
Material *new_material = params.extract_input<Material *>("New");
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
- geometry_set = geometry_set_realize_instances(geometry_set);
- if (geometry_set.has<MeshComponent>()) {
- MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
- Mesh *mesh = mesh_component.get_for_write();
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ Mesh *mesh = geometry_set.get_mesh_for_write();
if (mesh != nullptr) {
for (const int i : IndexRange(mesh->totcol)) {
if (mesh->mat[i] == old_material) {
@@ -52,7 +50,7 @@ static void geo_node_material_replace_exec(GeoNodeExecParams params)
}
}
}
- }
+ });
params.set_output("Geometry", std::move(geometry_set));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
index 9ca74fed9a7..c436f5bd480 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
@@ -32,28 +32,9 @@ static void geo_node_mesh_subdivide_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>("Geometry");
}
-static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
+static void geometry_set_mesh_subdivide(GeometrySet &geometry_set, const int level)
{
- GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
- geometry_set = geometry_set_realize_instances(geometry_set);
-
if (!geometry_set.has_mesh()) {
- params.set_output("Geometry", geometry_set);
- return;
- }
-
-#ifndef WITH_OPENSUBDIV
- params.error_message_add(NodeWarningType::Error,
- TIP_("Disabled, Blender was compiled without OpenSubdiv"));
- params.set_output("Geometry", std::move(geometry_set));
- return;
-#endif
-
- /* See CCGSUBSURF_LEVEL_MAX for max limit. */
- const int subdiv_level = clamp_i(params.extract_input<int>("Level"), 0, 11);
-
- if (subdiv_level == 0) {
- params.set_output("Geometry", std::move(geometry_set));
return;
}
@@ -61,7 +42,7 @@ static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
/* Initialize mesh settings. */
SubdivToMeshSettings mesh_settings;
- mesh_settings.resolution = (1 << subdiv_level) + 1;
+ mesh_settings.resolution = (1 << level) + 1;
mesh_settings.use_optimal_display = false;
/* Initialize subdivision settings. */
@@ -79,7 +60,6 @@ static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
/* In case of bad topology, skip to input mesh. */
if (subdiv == nullptr) {
- params.set_output("Geometry", std::move(geometry_set));
return;
}
@@ -90,6 +70,29 @@ static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
mesh_component.replace(mesh_out);
BKE_subdiv_free(subdiv);
+}
+
+static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+#ifndef WITH_OPENSUBDIV
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Disabled, Blender was compiled without OpenSubdiv"));
+ params.set_output("Geometry", std::move(geometry_set));
+ return;
+#endif
+
+ /* See CCGSUBSURF_LEVEL_MAX for max limit. */
+ const int subdiv_level = clamp_i(params.extract_input<int>("Level"), 0, 11);
+
+ if (subdiv_level == 0) {
+ params.set_output("Geometry", std::move(geometry_set));
+ return;
+ }
+
+ geometry_set.modify_geometry_sets(
+ [&](GeometrySet &geometry_set) { geometry_set_mesh_subdivide(geometry_set, subdiv_level); });
params.set_output("Geometry", std::move(geometry_set));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc b/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc
index c63e4ec49d9..dafd10cee2d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc
@@ -25,20 +25,18 @@ static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>("Point Cloud");
b.add_output<decl::Geometry>("Curve");
b.add_output<decl::Geometry>("Volume");
+ b.add_output<decl::Geometry>("Instances");
}
static void geo_node_separate_components_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
- /* Note that it will be possible to skip realizing instances here when instancing
- * geometry directly is supported by creating corresponding geometry instances. */
- geometry_set = bke::geometry_set_realize_instances(geometry_set);
-
GeometrySet meshes;
GeometrySet point_clouds;
GeometrySet volumes;
GeometrySet curves;
+ GeometrySet instances;
if (geometry_set.has<MeshComponent>()) {
meshes.add(*geometry_set.get_component_for_read<MeshComponent>());
@@ -52,11 +50,15 @@ static void geo_node_separate_components_exec(GeoNodeExecParams params)
if (geometry_set.has<VolumeComponent>()) {
volumes.add(*geometry_set.get_component_for_read<VolumeComponent>());
}
+ if (geometry_set.has<InstancesComponent>()) {
+ instances.add(*geometry_set.get_component_for_read<InstancesComponent>());
+ }
params.set_output("Mesh", meshes);
params.set_output("Point Cloud", point_clouds);
params.set_output("Curve", curves);
params.set_output("Volume", volumes);
+ params.set_output("Instances", instances);
}
} // namespace blender::nodes
diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
index 8886c7194db..7ef0913622c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
@@ -58,14 +58,14 @@ static void geo_node_triangulate_exec(GeoNodeExecParams params)
GeometryNodeTriangulateNGons ngon_method = static_cast<GeometryNodeTriangulateNGons>(
params.node().custom2);
- geometry_set = geometry_set_realize_instances(geometry_set);
-
- /* #triangulate_mesh might modify the input mesh currently. */
- Mesh *mesh_in = geometry_set.get_mesh_for_write();
- if (mesh_in != nullptr) {
- Mesh *mesh_out = triangulate_mesh(mesh_in, quad_method, ngon_method, min_vertices, 0);
- geometry_set.replace_mesh(mesh_out);
- }
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ /* #triangulate_mesh might modify the input mesh currently. */
+ Mesh *mesh_in = geometry_set.get_mesh_for_write();
+ if (mesh_in != nullptr) {
+ Mesh *mesh_out = triangulate_mesh(mesh_in, quad_method, ngon_method, min_vertices, 0);
+ geometry_set.replace_mesh(mesh_out);
+ }
+ });
params.set_output("Geometry", std::move(geometry_set));
}