diff options
author | Hans Goudey <h.goudey@me.com> | 2021-09-21 22:20:54 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2021-09-21 22:20:54 +0300 |
commit | 6d162d35e2c85ea4fb990f0c459ec36064cf0550 (patch) | |
tree | a0e5f89fdfedf77eb21439438760b2cffb7ba94f /source/blender/nodes | |
parent | 29e3545194804428676b0adf881f418a96a40a9a (diff) |
Geometry Nodes: Fill instances separately in the curve fill node
With this commit, each referenced instance data will be converted to
a geometry instances and processed separately. This should result in
a large speedup when the instances component has many insances
referring to the same data.
This change can act as a blueprint for other nodes that need to
implement similar behavior. It adds some helper functions on the
instances component to make that easier.
Thanks to Erik Abrahamsson for a proof of concept patch.
Differential Revision: https://developer.blender.org/D12572
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc index d8f40b0a0df..8de2975f9b0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc @@ -124,37 +124,55 @@ static Mesh *cdt_to_mesh(const blender::meshintersect::CDT_result<double> &resul return mesh; } -static Mesh *curve_fill_calculate(GeoNodeExecParams ¶ms, const CurveComponent &component) +static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCurveFillMode mode) { - const CurveEval &curve = *component.get_for_read(); - if (curve.splines().size() == 0) { - return nullptr; + if (!geometry_set.has_curve()) { + return; } - const NodeGeometryCurveFill &storage = *(const NodeGeometryCurveFill *)params.node().storage; - const GeometryNodeCurveFillMode mode = (GeometryNodeCurveFillMode)storage.mode; + const CurveEval &curve = *geometry_set.get_curve_for_read(); + if (curve.splines().is_empty()) { + geometry_set.replace_curve(nullptr); + return; + } const CDT_output_type output_type = (mode == GEO_NODE_CURVE_FILL_MODE_NGONS) ? CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES : CDT_INSIDE_WITH_HOLES; const blender::meshintersect::CDT_result<double> results = do_cdt(curve, output_type); - return cdt_to_mesh(results); + Mesh *mesh = cdt_to_mesh(results); + + geometry_set.replace_mesh(mesh); + geometry_set.replace_curve(nullptr); } static void geo_node_curve_fill_exec(GeoNodeExecParams params) { 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("Mesh", GeometrySet()); + const NodeGeometryCurveFill &storage = *(const NodeGeometryCurveFill *)params.node().storage; + const GeometryNodeCurveFillMode mode = (GeometryNodeCurveFillMode)storage.mode; + + if (geometry_set.has_instances()) { + InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>(); + instances.ensure_geometry_instances(); + + threading::parallel_for(IndexRange(instances.references_amount()), 16, [&](IndexRange range) { + for (int i : range) { + GeometrySet &geometry_set = instances.geometry_set_from_reference(i); + geometry_set = bke::geometry_set_realize_instances(geometry_set); + curve_fill_calculate(geometry_set, mode); + } + }); + + params.set_output("Mesh", std::move(geometry_set)); return; } - Mesh *mesh = curve_fill_calculate(params, - *geometry_set.get_component_for_read<CurveComponent>()); - params.set_output("Mesh", GeometrySet::create_with_mesh(mesh)); + curve_fill_calculate(geometry_set, mode); + + params.set_output("Mesh", std::move(geometry_set)); } } // namespace blender::nodes |