Blender  V3.3
node_geo_curve_primitive_arc.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <numeric>
4 
5 #include "BLI_math_base_safe.h"
6 
7 #include "BKE_curves.hh"
8 
9 #include "UI_interface.h"
10 #include "UI_resources.h"
11 
12 #include "node_geometry_util.hh"
13 
15 
17 
19 {
20  auto enable_points = [](bNode &node) {
22  };
23  auto enable_radius = [](bNode &node) {
25  };
26 
27  b.add_input<decl::Int>(N_("Resolution"))
28  .default_value(16)
29  .min(2)
30  .max(256)
31  .subtype(PROP_UNSIGNED)
32  .description(N_("The number of points on the arc"));
33  b.add_input<decl::Vector>(N_("Start"))
34  .default_value({-1.0f, 0.0f, 0.0f})
35  .subtype(PROP_TRANSLATION)
36  .description(N_("Position of the first control point"))
37  .make_available(enable_points);
38  b.add_input<decl::Vector>(N_("Middle"))
39  .default_value({0.0f, 2.0f, 0.0f})
40  .subtype(PROP_TRANSLATION)
41  .description(N_("Position of the middle control point"))
42  .make_available(enable_points);
43  b.add_input<decl::Vector>(N_("End"))
44  .default_value({1.0f, 0.0f, 0.0f})
45  .subtype(PROP_TRANSLATION)
46  .description(N_("Position of the last control point"))
47  .make_available(enable_points);
48  b.add_input<decl::Float>(N_("Radius"))
49  .default_value(1.0f)
50  .min(0.0f)
51  .subtype(PROP_DISTANCE)
52  .description(N_("Distance of the points from the origin"))
53  .make_available(enable_radius);
54  b.add_input<decl::Float>(N_("Start Angle"))
55  .default_value(0.0f)
56  .subtype(PROP_ANGLE)
57  .description(N_("Starting angle of the arc"))
58  .make_available(enable_radius);
59  b.add_input<decl::Float>(N_("Sweep Angle"))
60  .default_value(1.75f * M_PI)
61  .min(-2 * M_PI)
62  .max(2 * M_PI)
63  .subtype(PROP_ANGLE)
64  .description(N_("Length of the arc"))
65  .make_available(enable_radius);
66  b.add_input<decl::Float>(N_("Offset Angle"))
67  .default_value(0.0f)
68  .subtype(PROP_ANGLE)
69  .description(N_("Offset angle of the arc"))
70  .make_available(enable_points);
71  b.add_input<decl::Bool>(N_("Connect Center"))
72  .default_value(false)
73  .description(N_("Connect the arc at the center"));
74  b.add_input<decl::Bool>(N_("Invert Arc"))
75  .default_value(false)
76  .description(N_("Invert and draw opposite arc"));
77 
78  b.add_output<decl::Geometry>(N_("Curve"));
79  b.add_output<decl::Vector>(N_("Center"))
80  .description(N_("The center of the circle described by the three points"))
81  .make_available(enable_points);
82  b.add_output<decl::Vector>(N_("Normal"))
83  .description(N_("The normal direction of the plane described by the three points, pointing "
84  "towards the positive Z axis"))
85  .make_available(enable_points);
86  b.add_output<decl::Float>(N_("Radius"))
87  .description(N_("The radius of the circle described by the three points"))
88  .make_available(enable_points);
89 }
90 
91 static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
92 {
93  uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
94 }
95 
97 {
98  NodeGeometryCurvePrimitiveArc *data = MEM_cnew<NodeGeometryCurvePrimitiveArc>(__func__);
99 
101  node->storage = data;
102 }
103 
105 {
106  const NodeGeometryCurvePrimitiveArc &storage = node_storage(*node);
108 
109  bNodeSocket *start_socket = ((bNodeSocket *)node->inputs.first)->next;
110  bNodeSocket *middle_socket = start_socket->next;
111  bNodeSocket *end_socket = middle_socket->next;
112 
113  bNodeSocket *radius_socket = end_socket->next;
114  bNodeSocket *start_angle_socket = radius_socket->next;
115  bNodeSocket *sweep_angle_socket = start_angle_socket->next;
116 
117  bNodeSocket *offset_angle_socket = sweep_angle_socket->next;
118 
119  bNodeSocket *center_out_socket = ((bNodeSocket *)node->outputs.first)->next;
120  bNodeSocket *normal_out_socket = center_out_socket->next;
121  bNodeSocket *radius_out_socket = normal_out_socket->next;
122 
123  const bool radius_mode = (mode == GEO_NODE_CURVE_PRIMITIVE_ARC_TYPE_RADIUS);
124  const bool points_mode = (mode == GEO_NODE_CURVE_PRIMITIVE_ARC_TYPE_POINTS);
125 
126  nodeSetSocketAvailability(ntree, start_socket, points_mode);
127  nodeSetSocketAvailability(ntree, middle_socket, points_mode);
128  nodeSetSocketAvailability(ntree, end_socket, points_mode);
129 
130  nodeSetSocketAvailability(ntree, radius_socket, radius_mode);
131  nodeSetSocketAvailability(ntree, start_angle_socket, radius_mode);
132  nodeSetSocketAvailability(ntree, sweep_angle_socket, radius_mode);
133 
134  nodeSetSocketAvailability(ntree, offset_angle_socket, points_mode);
135 
136  nodeSetSocketAvailability(ntree, center_out_socket, points_mode);
137  nodeSetSocketAvailability(ntree, normal_out_socket, points_mode);
138  nodeSetSocketAvailability(ntree, radius_out_socket, points_mode);
139 }
140 
141 static float3 rotate_vector_around_axis(const float3 vector, const float3 axis, const float angle)
142 {
143  float3 result = vector;
144  float mat[3][3];
145  axis_angle_to_mat3(mat, axis, angle);
146  mul_m3_v3(mat, result);
147  return result;
148 }
149 
150 static bool colinear_f3_f3_f3(const float3 p1, const float3 p2, const float3 p3)
151 {
152  const float3 a = math::normalize(p2 - p1);
153  const float3 b = math::normalize(p3 - p1);
154  return (ELEM(a, b, b * -1.0f));
155 }
156 
157 static Curves *create_arc_curve_from_points(const int resolution,
158  const float3 a,
159  const float3 b,
160  const float3 c,
161  float angle_offset,
162  const bool connect_center,
163  const bool invert_arc,
164  float3 &r_center,
165  float3 &r_normal,
166  float &r_radius)
167 {
168  const int size = connect_center ? resolution + 1 : resolution;
171 
172  const int stepcount = resolution - 1;
173  const int centerpoint = resolution;
174  MutableSpan<float3> positions = curves.positions_for_write();
175 
176  const bool is_colinear = colinear_f3_f3_f3(a, b, c);
177 
178  float3 center;
179  float3 normal;
180  float radius;
181  const float3 mid_ac = math::midpoint(a, c);
182  normal_tri_v3(normal, a, c, b);
183 
184  if (is_colinear || a == c || a == b || b == c || resolution == 2) {
185  /* If colinear, generate a point line between points. */
186  float3 p1, p2;
187 
188  /* Find the two points that are furthest away from each other. */
189  const float ab = math::distance_squared(a, b);
190  const float ac = math::distance_squared(a, c);
191  const float bc = math::distance_squared(b, c);
192  if (ab > ac && ab > bc) {
193  p1 = a;
194  p2 = b;
195  }
196  else if (bc > ab && bc > ac) {
197  p1 = b;
198  p2 = c;
199  }
200  else {
201  p1 = a;
202  p2 = c;
203  }
204 
205  const float step = 1.0f / stepcount;
206  for (const int i : IndexRange(resolution)) {
207  const float factor = step * i;
208  positions[i] = math::interpolate(p1, p2, factor);
209  }
210  center = mid_ac;
211  radius = 0.0f;
212  }
213  else {
214  /* Midpoints of `A->B` and `B->C`. */
215  const float3 mid_ab = math::midpoint(a, b);
216  const float3 mid_bc = math::midpoint(c, b);
217 
218  /* Normalized vectors of `A->B` and `B->C`. */
219  const float3 nba = math::normalize(b - a);
220  const float3 ncb = math::normalize(c - b);
221 
222  /* Normal of plane of main 2 segments A->B and `B->C`. */
223  const float3 nabc = math::normalize(math::cross(nba, ncb));
224 
225  /* Determine center point from the intersection of 3 planes. */
226  float plane_1[4], plane_2[4], plane_3[4];
227  plane_from_point_normal_v3(plane_1, mid_ab, nabc);
228  plane_from_point_normal_v3(plane_2, mid_ab, nba);
229  plane_from_point_normal_v3(plane_3, mid_bc, ncb);
230 
231  /* If the 3 planes do not intersect at one point, just return empty geometry. */
232  if (!isect_plane_plane_plane_v3(plane_1, plane_2, plane_3, center)) {
233  r_center = mid_ac;
234  r_normal = normal;
235  r_radius = 0.0f;
236  return nullptr;
237  }
238 
239  /* Radial vectors. */
240  const float3 rad_a = math::normalize(a - center);
241  const float3 rad_b = math::normalize(b - center);
242  const float3 rad_c = math::normalize(c - center);
243 
244  /* Calculate angles. */
245  radius = math::distance(center, b);
246  float angle_ab = angle_signed_on_axis_v3v3_v3(rad_a, rad_b, normal) + 2.0f * M_PI;
247  float angle_ac = angle_signed_on_axis_v3v3_v3(rad_a, rad_c, normal) + 2.0f * M_PI;
248  float angle = (angle_ac > angle_ab) ? angle_ac : angle_ab;
249  angle -= 2.0f * M_PI;
250  if (invert_arc) {
251  angle = -(2.0f * M_PI - angle);
252  }
253 
254  /* Create arc. */
255  const float step = angle / stepcount;
256  for (const int i : IndexRange(resolution)) {
257  const float factor = step * i + angle_offset;
258  float3 out = rotate_vector_around_axis(rad_a, -normal, factor);
259  positions[i] = out * radius + center;
260  }
261  }
262 
263  if (connect_center) {
264  curves.cyclic_for_write().first() = true;
265  positions[centerpoint] = center;
266  }
267 
268  /* Ensure normal is relative to Z-up. */
269  if (math::dot(float3(0, 0, 1), normal) < 0) {
270  normal = -normal;
271  }
272 
273  r_center = center;
274  r_radius = radius;
275  r_normal = normal;
276  return curves_id;
277 }
278 
279 static Curves *create_arc_curve_from_radius(const int resolution,
280  const float radius,
281  const float start_angle,
282  const float sweep_angle,
283  const bool connect_center,
284  const bool invert_arc)
285 {
286  const int size = connect_center ? resolution + 1 : resolution;
289 
290  const int stepcount = resolution - 1;
291  const int centerpoint = resolution;
292  MutableSpan<float3> positions = curves.positions_for_write();
293 
294  const float sweep = (invert_arc) ? -(2.0f * M_PI - sweep_angle) : sweep_angle;
295 
296  const float theta_step = sweep / float(stepcount);
297  for (const int i : IndexRange(resolution)) {
298  const float theta = theta_step * i + start_angle;
299  const float x = radius * cos(theta);
300  const float y = radius * sin(theta);
301  positions[i] = float3(x, y, 0.0f);
302  }
303 
304  if (connect_center) {
305  curves.cyclic_for_write().first() = true;
306  positions[centerpoint] = float3(0.0f, 0.0f, 0.0f);
307  }
308 
309  return curves_id;
310 }
311 
313 {
314  const NodeGeometryCurvePrimitiveArc &storage = node_storage(params.node());
315 
317 
318  switch (mode) {
320  float3 r_center, r_normal;
321  float r_radius;
323  std::max(params.extract_input<int>("Resolution"), 2),
324  params.extract_input<float3>("Start"),
325  params.extract_input<float3>("Middle"),
326  params.extract_input<float3>("End"),
327  params.extract_input<float>("Offset Angle"),
328  params.extract_input<bool>("Connect Center"),
329  params.extract_input<bool>("Invert Arc"),
330  r_center,
331  r_normal,
332  r_radius);
333  params.set_output("Curve", GeometrySet::create_with_curves(curves));
334  params.set_output("Center", r_center);
335  params.set_output("Normal", r_normal);
336  params.set_output("Radius", r_radius);
337  break;
338  }
341  std::max(params.extract_input<int>("Resolution"), 2),
342  params.extract_input<float>("Radius"),
343  params.extract_input<float>("Start Angle"),
344  params.extract_input<float>("Sweep Angle"),
345  params.extract_input<bool>("Connect Center"),
346  params.extract_input<bool>("Invert Arc"));
347 
348  params.set_output("Curve", GeometrySet::create_with_curves(curves));
349  break;
350  }
351  }
352 }
353 
354 } // namespace blender::nodes::node_geo_curve_primitive_arc_cc
355 
357 {
359 
360  static bNodeType ntype;
364  node_type_storage(&ntype,
365  "NodeGeometryCurvePrimitiveArc",
371  nodeRegisterType(&ntype);
372 }
typedef float(TangentPoint)[2]
Low-level operations for curves.
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4443
#define NODE_STORAGE_FUNCS(StorageT)
Definition: BKE_node.h:1563
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
Definition: node.cc:3664
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4390
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4426
#define GEO_NODE_CURVE_PRIMITIVE_ARC
Definition: BKE_node.h:1490
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define M_PI
Definition: BLI_math_base.h:20
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
bool isect_plane_plane_plane_v3(const float plane_a[4], const float plane_b[4], const float plane_c[4], float r_isect_co[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_geom.c:2101
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void axis_angle_to_mat3(float R[3][3], const float axis[3], float angle)
float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:488
#define UNUSED(x)
#define ELEM(...)
@ CURVE_TYPE_POLY
GeometryNodeCurvePrimitiveArcMode
@ GEO_NODE_CURVE_PRIMITIVE_ARC_TYPE_POINTS
@ GEO_NODE_CURVE_PRIMITIVE_ARC_TYPE_RADIUS
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
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
@ PROP_DISTANCE
Definition: RNA_types.h:149
@ PROP_ANGLE
Definition: RNA_types.h:145
@ PROP_TRANSLATION
Definition: RNA_types.h:154
@ PROP_UNSIGNED
Definition: RNA_types.h:142
@ UI_ITEM_R_EXPAND
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
OperationNode * node
void * tree
bNodeTree * ntree
IconTextureDrawCall normal
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
static ulong * next
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:311
Curves * curves_new_nomain_single(int points_num, CurveType type)
Definition: curves.cc:375
T distance_squared(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T distance(const T &a, const T &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
T midpoint(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
static Curves * create_arc_curve_from_points(const int resolution, const float3 a, const float3 b, const float3 c, float angle_offset, const bool connect_center, const bool invert_arc, float3 &r_center, float3 &r_normal, float &r_radius)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
static void node_update(bNodeTree *ntree, bNode *node)
static float3 rotate_vector_around_axis(const float3 vector, const float3 axis, const float angle)
static Curves * create_arc_curve_from_radius(const int resolution, const float radius, const float start_angle, const float sweep_angle, const bool connect_center, const bool invert_arc)
static bool colinear_f3_f3_f3(const float3 p1, const float3 p2, const float3 p3)
vec_base< float, 3 > float3
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
Definition: node.cc:1082
void register_node_type_geo_curve_primitive_arc()
MutableSpan< float3 > positions
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:55
void node_free_standard_storage(bNode *node)
Definition: node_util.c:43
CurvesGeometry geometry
static GeometrySet create_with_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
struct bNodeSocket * next
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:244
NodeDeclareFunction declare
Definition: BKE_node.h:324
float max
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480