Geometry Nodes: Spline Length Input Node

The Spline Length Input node provides a field containing the
length of the current evaluated spline to the Point and Spline
domains.

Differential Revision: https://developer.blender.org/D12706
This commit is contained in:
Johnny Matthews 2021-10-01 09:58:49 -05:00
parent 9e456ca695
commit dc30a9087c
7 changed files with 116 additions and 1 deletions

View File

@ -525,6 +525,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeCurveFill"),
NodeItem("GeometryNodeCurveTrim"),
NodeItem("GeometryNodeCurveLength"),
NodeItem("GeometryNodeSplineLength"),
NodeItem("GeometryNodeCurveSubdivide"),
NodeItem("GeometryNodeCurveParameter"),
NodeItem("GeometryNodeInputTangent"),

View File

@ -1508,8 +1508,9 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_POINTS_TO_VERTICES 1094
#define GEO_NODE_CURVE_REVERSE 1095
#define GEO_NODE_PROXIMITY 1096
#define GEO_NODE_CURVE_SUBDIVIDE 1097
#define GEO_NODE_INPUT_SPLINE_LENGTH 1098
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -5767,6 +5767,7 @@ static void registerGeometryNodes()
register_node_type_geo_input_normal();
register_node_type_geo_input_position();
register_node_type_geo_input_tangent();
register_node_type_geo_input_spline_length();
register_node_type_geo_instance_on_points();
register_node_type_geo_is_viewport();
register_node_type_geo_join_geometry();

View File

@ -217,6 +217,7 @@ set(SRC
geometry/nodes/node_geo_input_material.cc
geometry/nodes/node_geo_input_normal.cc
geometry/nodes/node_geo_input_position.cc
geometry/nodes/node_geo_input_spline_length.cc
geometry/nodes/node_geo_input_tangent.cc
geometry/nodes/node_geo_instance_on_points.cc
geometry/nodes/node_geo_is_viewport.cc

View File

@ -86,6 +86,7 @@ void register_node_type_geo_input_index(void);
void register_node_type_geo_input_material(void);
void register_node_type_geo_input_normal(void);
void register_node_type_geo_input_position(void);
void register_node_type_geo_input_spline_length(void);
void register_node_type_geo_input_tangent(void);
void register_node_type_geo_instance_on_points(void);
void register_node_type_geo_is_viewport(void);

View File

@ -345,6 +345,7 @@ DefNode(GeometryNode, GEO_NODE_INPUT_INDEX, 0, "INDEX", InputIndex, "Index", "")
DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "")
DefNode(GeometryNode, GEO_NODE_INPUT_NORMAL, 0, "INPUT_NORMAL", InputNormal, "Normal", "")
DefNode(GeometryNode, GEO_NODE_INPUT_POSITION, 0, "POSITION", InputPosition, "Position", "")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_LENGTH, 0, "SPLINE_LENGTH", SplineLength, "Spline Length", "")
DefNode(GeometryNode, GEO_NODE_INPUT_TANGENT, 0, "INPUT_TANGENT", InputTangent, "Curve Tangent", "")
DefNode(GeometryNode, GEO_NODE_INSTANCE_ON_POINTS, 0, "INSTANCE_ON_POINTS", InstanceOnPoints, "Instance on Points", "")
DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "")

View File

@ -0,0 +1,109 @@
/*
* 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 "node_geometry_util.hh"
#include "BKE_spline.hh"
namespace blender::nodes {
static void geo_node_input_spline_length_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Float>("Length").field_source();
}
static const GVArray *construct_spline_length_gvarray(const CurveComponent &component,
const AttributeDomain domain,
ResourceScope &scope)
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
return nullptr;
}
Span<SplinePtr> splines = curve->splines();
auto length_fn = [splines](int i) { return splines[i]->length(); };
if (domain == ATTR_DOMAIN_CURVE) {
return &scope.construct<
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
splines.size(), splines.size(), length_fn);
}
if (domain == ATTR_DOMAIN_POINT) {
GVArrayPtr length = std::make_unique<
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
splines.size(), splines.size(), length_fn);
return scope
.add_value(component.attribute_try_adapt_domain(
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT))
.get();
}
return nullptr;
}
class SplineLengthFieldInput final : public fn::FieldInput {
public:
SplineLengthFieldInput() : fn::FieldInput(CPPType::get<float>(), "Spline Length")
{
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_spline_length_gvarray(curve_component, domain, scope);
}
}
return nullptr;
}
uint64_t hash() const override
{
/* Some random constant hash. */
return 3549623580;
}
bool is_equal_to(const fn::FieldNode &other) const override
{
return dynamic_cast<const SplineLengthFieldInput *>(&other) != nullptr;
}
};
static void geo_node_input_spline_length_exec(GeoNodeExecParams params)
{
Field<float> length_field{std::make_shared<SplineLengthFieldInput>()};
params.set_output("Length", std::move(length_field));
}
} // namespace blender::nodes
void register_node_type_geo_input_spline_length()
{
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_SPLINE_LENGTH, "Spline Length", NODE_CLASS_INPUT, 0);
ntype.geometry_node_execute = blender::nodes::geo_node_input_spline_length_exec;
ntype.declare = blender::nodes::geo_node_input_spline_length_declare;
nodeRegisterType(&ntype);
}