Commit: 3ec74ee230045a22599b514dbcb28338b8882782 Author: Hans Goudey Date: Wed Jun 9 16:35:36 2021 -0500 Branches: temp-geometry-nodes-curve-deform-node https://developer.blender.org/rB3ec74ee230045a22599b514dbcb28338b8882782
Merge branch 'master' into temp-geometry-nodes-curve-deform-node =================================================================== =================================================================== diff --cc source/blender/blenkernel/BKE_spline.hh index efc165a7198,dfbe82f31fd..eb944fc8b5c --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@@ -172,10 -170,27 +172,29 @@@ class Spline LookupResult lookup_evaluated_length(const float length) const; blender::Array<float> sample_uniform_index_factors(const int samples_size) const; + void sample_length_parameters_to_index_factors(blender::MutableSpan<float> parameters) const; + LookupResult lookup_data_from_index_factor(const float index_factor) const; + void sample_based_on_index_factors(const blender::fn::GVArray &src, + blender::Span<float> index_factors, + blender::fn::GMutableSpan dst) const; + template<typename T> + void sample_based_on_index_factors(const blender::VArray<T> &src, + blender::Span<float> index_factors, + blender::MutableSpan<T> dst) const + { + this->sample_based_on_index_factors( + blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst)); + } + template<typename T> + void sample_based_on_index_factors(blender::Span<T> src, + blender::Span<float> index_factors, + blender::MutableSpan<T> dst) const + { + this->sample_based_on_index_factors(blender::VArray_For_Span(src), index_factors, dst); + } + /** * Interpolate a virtual array of data with the size of the number of control points to the * evaluated points. For poly splines, the lifetime of the returned virtual array must not diff --cc source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc index 0ed6264faa1,00000000000..8f57ef2d64a mode 100644,000000..100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc @@@ -1,291 -1,0 +1,291 @@@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_array.hh" +#include "BLI_float4x4.hh" +#include "BLI_task.hh" +#include "BLI_timeit.hh" + +#include "BKE_attribute_math.hh" +#include "BKE_geometry_set_instances.hh" +#include "BKE_spline.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +using blender::float4x4; +using blender::bke::GeometryInstanceGroup; + +static bNodeSocketTemplate geo_node_curve_deform_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_GEOMETRY, N_("Curve")}, + {SOCK_STRING, N_("Factor")}, + {SOCK_FLOAT, N_("Factor"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + // {SOCK_BOOLEAN, N_("Use Radius")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_deform_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_curve_deform_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + const bNode *node = (bNode *)ptr->data; + NodeGeometryCurveDeform &node_storage = *(NodeGeometryCurveDeform *)node->storage; + const GeometryNodeCurveDeformMode mode = (GeometryNodeCurveDeformMode)node_storage.input_mode; + + uiItemR(layout, ptr, "position_axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + + uiItemR(layout, ptr, "input_mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + + if (mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE) { + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + uiItemR(layout, ptr, "attribute_input_type", 0, IFACE_("Factor"), ICON_NONE); + } +} + +static void geo_node_curve_deform_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCurveDeform *data = (NodeGeometryCurveDeform *)MEM_callocN( + sizeof(NodeGeometryCurveDeform), __func__); + + data->input_mode = GEO_NODE_CURVE_DEFORM_POSITION; + data->position_axis = GEO_NODE_CURVE_DEFORM_POSX; + data->attribute_input_type = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + node->storage = data; +} + +namespace blender::nodes { + +static void geo_node_curve_deform_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeGeometryCurveDeform &node_storage = *(NodeGeometryCurveDeform *)node->storage; + const GeometryNodeCurveDeformMode mode = (GeometryNodeCurveDeformMode)node_storage.input_mode; + + bNodeSocket *attribute_socket = ((bNodeSocket *)node->inputs.first)->next->next; + + nodeSetSocketAvailability(attribute_socket, mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE); + update_attribute_input_socket_availabilities( + *node, + "Factor", + (GeometryNodeAttributeInputMode)node_storage.attribute_input_type, + mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE); +} + +static void spline_deform(const Spline &spline, + Span<float> index_factors, + const int axis_index, + MutableSpan<float3> positions) +{ + Span<float3> spline_positions = spline.evaluated_positions(); + Span<float3> spline_tangents = spline.evaluated_tangents(); + Span<float3> spline_normals = spline.evaluated_normals(); - GVArray_Typed<float> radii{spline.interpolate_to_evaluated_points(spline.radii())}; ++ GVArray_Typed<float> radii = spline.interpolate_to_evaluated_points(spline.radii()); + + parallel_for(positions.index_range(), 1024, [&](IndexRange range) { + for (const int i : range) { + const Spline::LookupResult interp = spline.lookup_data_from_index_factor(index_factors[i]); + const int index = interp.evaluated_index; + const int next_index = interp.next_evaluated_index; + const float factor = interp.factor; + + float4x4 matrix = float4x4::from_normalized_axis_data( + {0, 0, 0}, + float3::interpolate(spline_normals[index], spline_normals[next_index], factor) + .normalized(), + float3::interpolate(spline_tangents[index], spline_tangents[next_index], factor) + .normalized()); + matrix.apply_scale(interpf(radii[next_index], radii[index], factor)); + + float3 position = positions[i]; + position[axis_index] = 0.0f; + + positions[i] = matrix * position; + positions[i] += float3::interpolate( + spline_positions[index], spline_positions[next_index], factor); + } + }); +} + +static int axis_to_index(const GeometryNodeCurveDeformPositionAxis axis) +{ + switch (axis) { + case GEO_NODE_CURVE_DEFORM_POSX: + case GEO_NODE_CURVE_DEFORM_NEGX: + return 0; + case GEO_NODE_CURVE_DEFORM_POSY: + case GEO_NODE_CURVE_DEFORM_NEGY: + return 1; + case GEO_NODE_CURVE_DEFORM_POSZ: + case GEO_NODE_CURVE_DEFORM_NEGZ: + return 2; + } + BLI_assert_unreachable(); + return -1; +} + +static bool axis_is_negative(const GeometryNodeCurveDeformPositionAxis axis) +{ + switch (axis) { + case GEO_NODE_CURVE_DEFORM_POSX: + case GEO_NODE_CURVE_DEFORM_POSY: + case GEO_NODE_CURVE_DEFORM_POSZ: + return false; + case GEO_NODE_CURVE_DEFORM_NEGX: + case GEO_NODE_CURVE_DEFORM_NEGY: + case GEO_NODE_CURVE_DEFORM_NEGZ: + return true; + } + BLI_assert_unreachable(); + return false; +} + +static float find_upper_bound(Span<float3> positions, const int index) +{ + float max = FLT_MIN; + for (const float3 &position : positions) { + if (position[index] > max) { + max = position[index]; + } + } + return max; +} + +static float find_lower_bound(Span<float3> positions, const int index) +{ + float min = FLT_MAX; + for (const float3 &position : positions) { + if (position[index] < min) { + min = position[index]; + } + } + return min; +} + +static void execute_on_component(const GeoNodeExecParams ¶ms, + const CurveEval &curve, + GeometryComponent &component) +{ + const NodeGeometryCurveDeform &node_storage = *(NodeGeometryCurveDeform *)params.node().storage; + const GeometryNodeCurveDeformMode mode = (GeometryNodeCurveDeformMode)node_storage.input_mode; + const GeometryNodeCurveDeformPositionAxis axis = (GeometryNodeCurveDeformPositionAxis) + node_storage.position_axis; + const int axis_index = axis_to_index(axis); + + if (curve.splines().size() == 0) { + BLI_assert_unreachable(); + return; + } + + const Spline &spline = *curve.splines().first(); + const float total_length = spline.length(); + + const int size = component.attribute_domain_size(ATTR_DOMAIN_POINT); + OutputAttribute_Typed<float3> position_attribute = + component.attribute_try_get_for_output<float3>("position", ATTR_DOMAIN_POINT, {0, 0, 0}); + MutableSpan<float3> positions = position_attribute.as_span(); + + Array<float> parameters(size); + + if (mode == GEO_NODE_CURVE_DEFORM_POSITION) { + if (axis_is_negative(axis)) { + parallel_for(positions.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + parameters[i] = std::clamp(positions[i][axis_index], 0.0f, total_length); + } + }); + } + else { + parallel_for(positions.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + parameters[i] = total_length - std::clamp(positions[i][axis_index], 0.0f, total_length); + } + }); + } + } @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs