From c3b6e372542f9fb0ff238c8071cca4ae562445c3 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 3 Oct 2022 16:41:58 -0500 Subject: Geometry Nodes: Rename Control Point Neighbors Node Rename the node to "Offset Point in Curve" Since this was committed, more mesh and curve topology nodes have been committed with a different naming scheme (482d431bb6735e82069). Change the name of this node to match "Offset Corner in Face". Because the node was only added recently, it's a full rename, including the ID, so forward compatibility is broken. --- source/blender/blenkernel/BKE_node.h | 2 +- source/blender/blenkernel/intern/node.cc | 2 +- source/blender/blenloader/intern/versioning_300.cc | 7 + source/blender/nodes/NOD_geometry.h | 2 +- source/blender/nodes/NOD_static_types.h | 4 +- source/blender/nodes/geometry/CMakeLists.txt | 2 +- .../node_geo_input_control_point_neighbors.cc | 170 --------------------- .../nodes/node_geo_offset_point_in_curve.cc | 170 +++++++++++++++++++++ 8 files changed, 183 insertions(+), 176 deletions(-) delete mode 100644 source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc create mode 100644 source/blender/nodes/geometry/nodes/node_geo_offset_point_in_curve.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 43eeaed4b04..b1b4045370c 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1531,7 +1531,7 @@ struct TexResult; #define GEO_NODE_SAMPLE_INDEX 1174 #define GEO_NODE_SAMPLE_NEAREST 1175 #define GEO_NODE_SAMPLE_NEAREST_SURFACE 1176 -#define GEO_NODE_INPUT_CONTROL_POINT_NEIGHBORS 1177 +#define GEO_NODE_OFFSET_POINT_IN_CURVE 1177 #define GEO_NODE_CURVE_TOPOLOGY_CURVE_OF_POINT 1178 #define GEO_NODE_CURVE_TOPOLOGY_POINTS_OF_CURVE 1179 #define GEO_NODE_MESH_TOPOLOGY_OFFSET_CORNER_IN_FACE 1180 diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 47e9ecfb7bd..959093b73b8 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -4745,7 +4745,6 @@ static void registerGeometryNodes() register_node_type_geo_flip_faces(); register_node_type_geo_geometry_to_instance(); register_node_type_geo_image_texture(); - register_node_type_geo_input_control_point_neighbors(); register_node_type_geo_input_curve_handles(); register_node_type_geo_input_curve_tilt(); register_node_type_geo_input_id(); @@ -4802,6 +4801,7 @@ static void registerGeometryNodes() register_node_type_geo_mesh_topology_face_of_corner(); register_node_type_geo_mesh_topology_vertex_of_corner(); register_node_type_geo_object_info(); + register_node_type_geo_offset_point_in_curve(); register_node_type_geo_points_to_vertices(); register_node_type_geo_points_to_volume(); register_node_type_geo_points(); diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index bbb83ec3187..95bdb9b0a1c 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3615,5 +3615,12 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { + if (ntree->type != NTREE_GEOMETRY) { + continue; + } + version_node_id(ntree, GEO_NODE_OFFSET_POINT_IN_CURVE, "GeometryNodeOffsetPointInCurve"); + } } } diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 430deace8bb..3b886bd55c6 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -63,7 +63,6 @@ void register_node_type_geo_field_at_index(void); void register_node_type_geo_flip_faces(void); void register_node_type_geo_geometry_to_instance(void); void register_node_type_geo_image_texture(void); -void register_node_type_geo_input_control_point_neighbors(void); void register_node_type_geo_input_curve_handles(void); void register_node_type_geo_input_curve_tilt(void); void register_node_type_geo_input_id(void); @@ -120,6 +119,7 @@ void register_node_type_geo_mesh_topology_face_of_corner(void); void register_node_type_geo_mesh_topology_offset_corner_in_face(void); void register_node_type_geo_mesh_topology_vertex_of_corner(void); void register_node_type_geo_object_info(void); +void register_node_type_geo_offset_point_in_curve(void); void register_node_type_geo_points_to_vertices(void); void register_node_type_geo_points_to_volume(void); void register_node_type_geo_points(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 584fa797a8e..d1504060665 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -320,8 +320,7 @@ DefNode(GeometryNode, GEO_NODE_FILLET_CURVE, def_geo_curve_fillet, "FILLET_CURVE DefNode(GeometryNode, GEO_NODE_FLIP_FACES, 0, "FLIP_FACES", FlipFaces, "Flip Faces", "Reverse the order of the vertices and edges of selected faces, flipping their normal direction") DefNode(GeometryNode, GEO_NODE_GEOMETRY_TO_INSTANCE, 0, "GEOMETRY_TO_INSTANCE", GeometryToInstance, "Geometry to Instance", "Convert each input geometry into an instance, which can be much faster than the Join Geometry node when the inputs are large") DefNode(GeometryNode, GEO_NODE_IMAGE_TEXTURE, def_geo_image_texture, "IMAGE_TEXTURE", ImageTexture, "Image Texture", "Sample values from an image texture") -DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_HANDLES, 0, "INPUT_CURVE_HANDLES",InputCurveHandlePositions,"Curve Handle Positions", "Retrieve the position of each Bézier control point's handles") -DefNode(GeometryNode, GEO_NODE_INPUT_CONTROL_POINT_NEIGHBORS, 0, "INPUT_CONTROL_POINT_NEIGHBORS", InputControlPointNeighbors, "Control Point Neighbors", "Offset a control point index within its curve") +DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_HANDLES, 0, "INPUT_CURVE_HANDLES", InputCurveHandlePositions,"Curve Handle Positions", "Retrieve the position of each Bézier control point's handles") DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_TILT, 0, "INPUT_CURVE_TILT", InputCurveTilt, "Curve Tilt", "Retrieve the angle at each control point used to twist the curve's normal around its tangent") DefNode(GeometryNode, GEO_NODE_INPUT_ID, 0, "INPUT_ID", InputID, "ID", "Retrieve a stable random identifier value from the \"id\" attribute on the point domain, or the index if the attribute does not exist") DefNode(GeometryNode, GEO_NODE_INPUT_INDEX, 0, "INDEX", InputIndex, "Index", "Retrieve an integer value indicating the position of each element in the list, starting at zero") @@ -376,6 +375,7 @@ DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_FACE_OF_CORNER, 0, "FACE_OF_CORNER" DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_OFFSET_CORNER_IN_FACE, 0, "OFFSET_CORNER_IN_FACE", OffsetCornerInFace, "Offset Corner in Face", "Retrieve corners in the same face as another") DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_VERTEX_OF_CORNER, 0, "VERTEX_OF_CORNER", VertexOfCorner, "Vertex of Corner", "Retrieve the vertex each face corner is attached to") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO", ObjectInfo, "Object Info", "Retrieve information from an object") +DefNode(GeometryNode, GEO_NODE_OFFSET_POINT_IN_CURVE, 0, "OFFSET_POINT_IN_CURVE", OffsetPointInCurve, "Offset Point in Curve", "Offset a control point index within its curve") DefNode(GeometryNode, GEO_NODE_POINTS_TO_VERTICES, 0, "POINTS_TO_VERTICES", PointsToVertices, "Points to Vertices", "Generate a mesh vertex for each point cloud point") DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, def_geo_points_to_volume, "POINTS_TO_VOLUME", PointsToVolume, "Points to Volume", "Generate a fog volume sphere around every point") DefNode(GeometryNode, GEO_NODE_POINTS, 0, "POINTS", Points, "Points", "Generate a point cloud with positions and radii defined by fields") diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index d8391871571..2b8de906a77 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -73,7 +73,6 @@ set(SRC nodes/node_geo_flip_faces.cc nodes/node_geo_geometry_to_instance.cc nodes/node_geo_image_texture.cc - nodes/node_geo_input_control_point_neighbors.cc nodes/node_geo_input_curve_handles.cc nodes/node_geo_input_curve_tilt.cc nodes/node_geo_input_id.cc @@ -130,6 +129,7 @@ set(SRC nodes/node_geo_mesh_topology_offset_corner_in_face.cc nodes/node_geo_mesh_topology_vertex_of_corner.cc nodes/node_geo_object_info.cc + nodes/node_geo_offset_point_in_curve.cc nodes/node_geo_points.cc nodes/node_geo_points_to_vertices.cc nodes/node_geo_points_to_volume.cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc deleted file mode 100644 index 7af4b13cd57..00000000000 --- a/source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc +++ /dev/null @@ -1,170 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_task.hh" - -#include "BKE_curves.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes { - -int apply_offset_in_cyclic_range(const IndexRange range, const int start_index, const int offset) -{ - BLI_assert(range.contains(start_index)); - const int start_in_range = start_index - range.first(); - const int offset_in_range = start_in_range + offset; - const int mod_offset = offset_in_range % range.size(); - if (mod_offset >= 0) { - return range[mod_offset]; - } - return range.last(-(mod_offset + 1)); -} - -} // namespace blender::nodes - -namespace blender::nodes::node_geo_input_control_point_neighbors_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input(N_("Point Index")) - .implicit_field(implicit_field_inputs::index) - .hide_value() - .description( - N_("The index of the control point to evaluate. Defaults to the current index")); - b.add_input(N_("Offset")) - .dependent_field() - .description(N_("The number of control points along the curve to traverse")); - b.add_output(N_("Is Valid Offset")) - .field_source() - .description(N_("Outputs true if the evaluated control point plus the offset " - "is a valid index of the original curve")); - b.add_output(N_("Point Index")) - .field_source() - .description(N_("The index of the control point plus the offset within the entire " - "curves data-block")); -} - -class ControlPointNeighborFieldInput final : public bke::CurvesFieldInput { - private: - const Field index_; - const Field offset_; - - public: - ControlPointNeighborFieldInput(Field index, Field offset) - : CurvesFieldInput(CPPType::get(), "Control Point Neighbors"), - index_(std::move(index)), - offset_(std::move(offset)) - { - category_ = Category::Generated; - } - - GVArray get_varray_for_context(const bke::CurvesGeometry &curves, - const eAttrDomain domain, - const IndexMask mask) const final - { - const VArray cyclic = curves.cyclic(); - const Array parent_curves = curves.point_to_curve_map(); - - const bke::CurvesFieldContext context{curves, domain}; - fn::FieldEvaluator evaluator{context, &mask}; - evaluator.add(index_); - evaluator.add(offset_); - evaluator.evaluate(); - const VArray indices = evaluator.get_evaluated(0); - const VArray offsets = evaluator.get_evaluated(1); - - Array output(mask.min_array_size()); - for (const int i_selection : mask) { - const int i_point = std::clamp(indices[i_selection], 0, curves.points_num() - 1); - const int i_curve = parent_curves[i_point]; - const IndexRange curve_points = curves.points_for_curve(i_curve); - const int offset_point = i_point + offsets[i_point]; - - if (cyclic[i_curve]) { - output[i_selection] = apply_offset_in_cyclic_range( - curve_points, i_point, offsets[i_selection]); - continue; - } - output[i_selection] = std::clamp(offset_point, 0, curves.points_num() - 1); - } - - return VArray::ForContainer(std::move(output)); - } -}; - -class OffsetValidFieldInput final : public bke::CurvesFieldInput { - private: - const Field index_; - const Field offset_; - - public: - OffsetValidFieldInput(Field index, Field offset) - : CurvesFieldInput(CPPType::get(), "Offset Valid"), - index_(std::move(index)), - offset_(std::move(offset)) - { - category_ = Category::Generated; - } - - GVArray get_varray_for_context(const bke::CurvesGeometry &curves, - const eAttrDomain domain, - const IndexMask mask) const final - { - const VArray cyclic = curves.cyclic(); - const Array parent_curves = curves.point_to_curve_map(); - - const bke::CurvesFieldContext context{curves, domain}; - fn::FieldEvaluator evaluator{context, &mask}; - evaluator.add(index_); - evaluator.add(offset_); - evaluator.evaluate(); - const VArray indices = evaluator.get_evaluated(0); - const VArray offsets = evaluator.get_evaluated(1); - - Array output(mask.min_array_size()); - for (const int i_selection : mask) { - const int i_point = indices[i_selection]; - if (!curves.points_range().contains(i_point)) { - output[i_selection] = false; - continue; - } - - const int i_curve = parent_curves[i_point]; - const IndexRange curve_points = curves.points_for_curve(i_curve); - if (cyclic[i_curve]) { - output[i_selection] = true; - continue; - } - output[i_selection] = curve_points.contains(i_point + offsets[i_selection]); - }; - return VArray::ForContainer(std::move(output)); - } -}; - -static void node_geo_exec(GeoNodeExecParams params) -{ - Field index = params.extract_input>("Point Index"); - Field offset = params.extract_input>("Offset"); - - if (params.output_is_required("Point Index")) { - Field curve_point_field{std::make_shared(index, offset)}; - params.set_output("Point Index", std::move(curve_point_field)); - } - if (params.output_is_required("Is Valid Offset")) { - Field valid_field{std::make_shared(index, offset)}; - params.set_output("Is Valid Offset", std::move(valid_field)); - } -} - -} // namespace blender::nodes::node_geo_input_control_point_neighbors_cc - -void register_node_type_geo_input_control_point_neighbors() -{ - namespace file_ns = blender::nodes::node_geo_input_control_point_neighbors_cc; - static bNodeType ntype; - geo_node_type_base( - &ntype, GEO_NODE_INPUT_CONTROL_POINT_NEIGHBORS, "Control Point Neighbors", NODE_CLASS_INPUT); - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.declare = file_ns::node_declare; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/node_geo_offset_point_in_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_offset_point_in_curve.cc new file mode 100644 index 00000000000..6891593d6f7 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_offset_point_in_curve.cc @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_task.hh" + +#include "BKE_curves.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes { + +int apply_offset_in_cyclic_range(const IndexRange range, const int start_index, const int offset) +{ + BLI_assert(range.contains(start_index)); + const int start_in_range = start_index - range.first(); + const int offset_in_range = start_in_range + offset; + const int mod_offset = offset_in_range % range.size(); + if (mod_offset >= 0) { + return range[mod_offset]; + } + return range.last(-(mod_offset + 1)); +} + +} // namespace blender::nodes + +namespace blender::nodes::node_geo_offset_point_in_curve_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input(N_("Point Index")) + .implicit_field(implicit_field_inputs::index) + .hide_value() + .description( + N_("The index of the control point to evaluate. Defaults to the current index")); + b.add_input(N_("Offset")) + .dependent_field() + .description(N_("The number of control points along the curve to traverse")); + b.add_output(N_("Is Valid Offset")) + .field_source() + .description(N_("Outputs true if the evaluated control point plus the offset " + "is a valid index of the original curve")); + b.add_output(N_("Point Index")) + .field_source() + .description(N_("The index of the control point plus the offset within the entire " + "curves data-block")); +} + +class ControlPointNeighborFieldInput final : public bke::CurvesFieldInput { + private: + const Field index_; + const Field offset_; + + public: + ControlPointNeighborFieldInput(Field index, Field offset) + : CurvesFieldInput(CPPType::get(), "Offset Point in Curve"), + index_(std::move(index)), + offset_(std::move(offset)) + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const bke::CurvesGeometry &curves, + const eAttrDomain domain, + const IndexMask mask) const final + { + const VArray cyclic = curves.cyclic(); + const Array parent_curves = curves.point_to_curve_map(); + + const bke::CurvesFieldContext context{curves, domain}; + fn::FieldEvaluator evaluator{context, &mask}; + evaluator.add(index_); + evaluator.add(offset_); + evaluator.evaluate(); + const VArray indices = evaluator.get_evaluated(0); + const VArray offsets = evaluator.get_evaluated(1); + + Array output(mask.min_array_size()); + for (const int i_selection : mask) { + const int i_point = std::clamp(indices[i_selection], 0, curves.points_num() - 1); + const int i_curve = parent_curves[i_point]; + const IndexRange curve_points = curves.points_for_curve(i_curve); + const int offset_point = i_point + offsets[i_point]; + + if (cyclic[i_curve]) { + output[i_selection] = apply_offset_in_cyclic_range( + curve_points, i_point, offsets[i_selection]); + continue; + } + output[i_selection] = std::clamp(offset_point, 0, curves.points_num() - 1); + } + + return VArray::ForContainer(std::move(output)); + } +}; + +class OffsetValidFieldInput final : public bke::CurvesFieldInput { + private: + const Field index_; + const Field offset_; + + public: + OffsetValidFieldInput(Field index, Field offset) + : CurvesFieldInput(CPPType::get(), "Offset Valid"), + index_(std::move(index)), + offset_(std::move(offset)) + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const bke::CurvesGeometry &curves, + const eAttrDomain domain, + const IndexMask mask) const final + { + const VArray cyclic = curves.cyclic(); + const Array parent_curves = curves.point_to_curve_map(); + + const bke::CurvesFieldContext context{curves, domain}; + fn::FieldEvaluator evaluator{context, &mask}; + evaluator.add(index_); + evaluator.add(offset_); + evaluator.evaluate(); + const VArray indices = evaluator.get_evaluated(0); + const VArray offsets = evaluator.get_evaluated(1); + + Array output(mask.min_array_size()); + for (const int i_selection : mask) { + const int i_point = indices[i_selection]; + if (!curves.points_range().contains(i_point)) { + output[i_selection] = false; + continue; + } + + const int i_curve = parent_curves[i_point]; + const IndexRange curve_points = curves.points_for_curve(i_curve); + if (cyclic[i_curve]) { + output[i_selection] = true; + continue; + } + output[i_selection] = curve_points.contains(i_point + offsets[i_selection]); + }; + return VArray::ForContainer(std::move(output)); + } +}; + +static void node_geo_exec(GeoNodeExecParams params) +{ + Field index = params.extract_input>("Point Index"); + Field offset = params.extract_input>("Offset"); + + if (params.output_is_required("Point Index")) { + Field curve_point_field{std::make_shared(index, offset)}; + params.set_output("Point Index", std::move(curve_point_field)); + } + if (params.output_is_required("Is Valid Offset")) { + Field valid_field{std::make_shared(index, offset)}; + params.set_output("Is Valid Offset", std::move(valid_field)); + } +} + +} // namespace blender::nodes::node_geo_offset_point_in_curve_cc + +void register_node_type_geo_offset_point_in_curve() +{ + namespace file_ns = blender::nodes::node_geo_offset_point_in_curve_cc; + static bNodeType ntype; + geo_node_type_base( + &ntype, GEO_NODE_OFFSET_POINT_IN_CURVE, "Offset Point in Curve", NODE_CLASS_INPUT); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.declare = file_ns::node_declare; + nodeRegisterType(&ntype); +} -- cgit v1.2.3