Blender  V3.3
node_geo_input_tangent.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_task.hh"
4 
5 #include "BKE_curves.hh"
6 
7 #include "node_geometry_util.hh"
8 
10 
12 {
13  b.add_output<decl::Vector>(N_("Tangent")).field_source();
14 }
15 
17 {
18  const VArray<int8_t> types = curves.curve_types();
19  const VArray<int> resolutions = curves.resolution();
20  const VArray<bool> cyclic = curves.cyclic();
21  const Span<float3> positions = curves.positions();
22 
23  const Span<float3> evaluated_tangents = curves.evaluated_tangents();
24 
25  Array<float3> results(curves.points_num());
26 
27  threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
28  for (const int i_curve : range) {
29  const IndexRange points = curves.points_for_curve(i_curve);
30  const IndexRange evaluated_points = curves.evaluated_points_for_curve(i_curve);
31 
32  MutableSpan<float3> curve_tangents = results.as_mutable_span().slice(points);
33 
34  switch (types[i_curve]) {
35  case CURVE_TYPE_CATMULL_ROM: {
36  Span<float3> tangents = evaluated_tangents.slice(evaluated_points);
37  const int resolution = resolutions[i_curve];
38  for (const int i : IndexRange(points.size())) {
39  curve_tangents[i] = tangents[resolution * i];
40  }
41  break;
42  }
43  case CURVE_TYPE_POLY:
44  curve_tangents.copy_from(evaluated_tangents.slice(evaluated_points));
45  break;
46  case CURVE_TYPE_BEZIER: {
47  Span<float3> tangents = evaluated_tangents.slice(evaluated_points);
48  curve_tangents.first() = tangents.first();
49  const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
50  for (const int i : IndexRange(points.size()).drop_front(1)) {
51  curve_tangents[i] = tangents[offsets[i - 1]];
52  }
53  break;
54  }
55  case CURVE_TYPE_NURBS: {
56  const Span<float3> curve_positions = positions.slice(points);
57  bke::curves::poly::calculate_tangents(curve_positions, cyclic[i_curve], curve_tangents);
58  break;
59  }
60  }
61  }
62  });
63  return results;
64 }
65 
67  const eAttrDomain domain)
68 {
69  if (!component.has_curves()) {
70  return {};
71  }
72 
73  const Curves &curves_id = *component.get_for_read();
75 
76  const VArray<int8_t> types = curves.curve_types();
77  if (curves.is_single_type(CURVE_TYPE_POLY)) {
78  return component.attributes()->adapt_domain<float3>(
79  VArray<float3>::ForSpan(curves.evaluated_tangents()), ATTR_DOMAIN_POINT, domain);
80  }
81 
83 
84  if (domain == ATTR_DOMAIN_POINT) {
85  return VArray<float3>::ForContainer(std::move(tangents));
86  }
87 
88  if (domain == ATTR_DOMAIN_CURVE) {
89  return component.attributes()->adapt_domain<float3>(
91  }
92 
93  return nullptr;
94 }
95 
97  public:
98  TangentFieldInput() : GeometryFieldInput(CPPType::get<float3>(), "Tangent node")
99  {
100  category_ = Category::Generated;
101  }
102 
104  const eAttrDomain domain,
105  IndexMask UNUSED(mask)) const final
106  {
107  if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
108  const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
109  return construct_curve_tangent_gvarray(curve_component, domain);
110  }
111  return {};
112  }
113 
114  uint64_t hash() const override
115  {
116  /* Some random constant hash. */
117  return 91827364589;
118  }
119 
120  bool is_equal_to(const fn::FieldNode &other) const override
121  {
122  return dynamic_cast<const TangentFieldInput *>(&other) != nullptr;
123  }
124 };
125 
127 {
128  Field<float3> tangent_field{std::make_shared<TangentFieldInput>()};
129  params.set_output("Tangent", std::move(tangent_field));
130 }
131 
132 } // namespace blender::nodes::node_geo_input_tangent_cc
133 
135 {
136  namespace file_ns = blender::nodes::node_geo_input_tangent_cc;
137 
138  static bNodeType ntype;
139 
143  nodeRegisterType(&ntype);
144 }
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_CURVE
Definition: BKE_attribute.h:31
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
Low-level operations for curves.
@ GEO_COMPONENT_TYPE_CURVE
#define NODE_CLASS_INPUT
Definition: BKE_node.h:345
#define GEO_NODE_INPUT_TANGENT
Definition: BKE_node.h:1428
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define final(a, b, c)
Definition: BLI_hash.h:21
#define UNUSED(x)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
@ CURVE_TYPE_POLY
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
bool is_equal_to(const fn::FieldNode &other) const override
GVArray get_varray_for_context(const GeometryComponent &component, const eAttrDomain domain, IndexMask UNUSED(mask)) const final
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
static char ** types
Definition: makesdna.c:67
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
static Array< float3 > curve_tangent_point_domain(const bke::CurvesGeometry &curves)
static VArray< float3 > construct_curve_tangent_gvarray(const CurveComponent &component, const eAttrDomain domain)
static void node_declare(NodeDeclarationBuilder &b)
static void node_geo_exec(GeoNodeExecParams params)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Definition: BLI_task.hh:51
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > positions
MutableSpan< float3 > tangents
void register_node_type_geo_input_tangent()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
unsigned __int64 uint64_t
Definition: stdint.h:90
CurvesGeometry geometry
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)