Blender V4.3
curves_add.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#include "BLI_rand.hh"
11
12#include "BKE_attribute.hh"
13#include "BKE_context.hh"
14#include "BKE_curves.hh"
15#include "BKE_node_runtime.hh"
16
17#include "BLT_translation.hh"
18
19#include "ED_curves.hh"
20#include "ED_node.hh"
21#include "ED_object.hh"
22
23#include "DNA_modifier_types.h"
24#include "DNA_node_types.h"
25#include "DNA_object_types.h"
26
28
29static bool has_surface_deformation_node(const bNodeTree &ntree)
30{
31 if (!ntree.nodes_by_type("GeometryNodeDeformCurvesOnSurface").is_empty()) {
32 return true;
33 }
34 for (const bNode *node : ntree.group_nodes()) {
35 if (const bNodeTree *sub_tree = reinterpret_cast<const bNodeTree *>(node->id)) {
36 if (has_surface_deformation_node(*sub_tree)) {
37 return true;
38 }
39 }
40 }
41 return false;
42}
43
44static bool has_surface_deformation_node(const Object &curves_ob)
45{
46 LISTBASE_FOREACH (const ModifierData *, md, &curves_ob.modifiers) {
47 if (md->type != eModifierType_Nodes) {
48 continue;
49 }
50 const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
51 if (nmd->node_group == nullptr) {
52 continue;
53 }
55 return true;
56 }
57 }
58 return false;
59}
60
62{
63 if (has_surface_deformation_node(curves_ob)) {
64 return;
65 }
66
67 Main *bmain = CTX_data_main(&C);
68 Scene *scene = CTX_data_scene(&C);
69
71 nullptr, bmain, scene, &curves_ob, DATA_("Surface Deform"), eModifierType_Nodes);
72 NodesModifierData &nmd = *reinterpret_cast<NodesModifierData *>(md);
73 nmd.node_group = bke::node_tree_add_tree(bmain, DATA_("Surface Deform"), "GeometryNodeTree");
74
76 nmd.node_group->geometry_node_asset_traits = MEM_cnew<GeometryNodeAssetTraits>(__func__);
77 }
78
80
81 bNodeTree *ntree = nmd.node_group;
82 ntree->tree_interface.add_socket(
83 "Geometry", "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_OUTPUT, nullptr);
84 ntree->tree_interface.add_socket(
85 "Geometry", "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_INPUT, nullptr);
86 bNode *group_input = bke::node_add_static_node(&C, ntree, NODE_GROUP_INPUT);
87 bNode *group_output = bke::node_add_static_node(&C, ntree, NODE_GROUP_OUTPUT);
88 bNode *deform_node = bke::node_add_static_node(&C, ntree, GEO_NODE_DEFORM_CURVES_ON_SURFACE);
89
91
93 group_input,
94 static_cast<bNodeSocket *>(group_input->outputs.first),
95 deform_node,
96 bke::node_find_socket(deform_node, SOCK_IN, "Curves"));
98 deform_node,
99 bke::node_find_socket(deform_node, SOCK_OUT, "Curves"),
100 group_output,
101 static_cast<bNodeSocket *>(group_output->inputs.first));
102
103 group_input->locx = -200;
104 group_output->locx = 200;
105 deform_node->locx = 0;
106
108}
109
110bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int points_per_curve)
111{
112 bke::CurvesGeometry curves(points_per_curve * curves_size, curves_size);
113
114 MutableSpan<int> offsets = curves.offsets_for_write();
115 MutableSpan<float3> positions = curves.positions_for_write();
116 bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
117 bke::SpanAttributeWriter<float> radius = attributes.lookup_or_add_for_write_only_span<float>(
118 "radius", bke::AttrDomain::Point);
119
120 for (const int i : offsets.index_range()) {
121 offsets[i] = points_per_curve * i;
122 }
123
125
126 const OffsetIndices points_by_curve = curves.points_by_curve();
127 for (const int i : curves.curves_range()) {
128 const IndexRange points = points_by_curve[i];
129 MutableSpan<float3> curve_positions = positions.slice(points);
130 MutableSpan<float> curve_radii = radius.span.slice(points);
131
132 const float theta = 2.0f * M_PI * rng.get_float();
133 const float phi = safe_acosf(2.0f * rng.get_float() - 1.0f);
134
135 float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
136 no = math::normalize(no);
137
138 float3 co = no;
139 for (int key = 0; key < points_per_curve; key++) {
140 float t = key / float(points_per_curve - 1);
141 curve_positions[key] = co;
142 curve_radii[key] = 0.02f * (1.0f - t);
143
144 float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
145 co += (offset + no) / points_per_curve;
146 }
147 }
148
149 radius.finish();
150
151 return curves;
152}
153
154} // namespace blender::ed::curves
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
Low-level operations for curves.
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#define LISTBASE_FOREACH(type, var, list)
#define M_PI
MINLINE float safe_acosf(float a)
#define DATA_(msgid)
@ eModifierType_Nodes
@ GEO_NODE_ASSET_MODIFIER
@ SOCK_OUT
@ SOCK_IN
Object is a sort of wrapper for general info.
void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *ntree)
Definition node_edit.cc:492
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:574
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
draw_view in_light_buf[] float
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
Definition node.cc:2642
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
bNodeTree * node_tree_add_tree(Main *bmain, const char *name, const char *idname)
Definition node.cc:3226
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
static bool has_surface_deformation_node(const bNodeTree &ntree)
Definition curves_add.cc:29
bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int points_per_curve)
void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob)
Definition curves_add.cc:61
ModifierData * modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< float, 3 > float3
void * first
struct bNodeTree * node_group
ListBase modifiers
struct GeometryNodeAssetTraits * geometry_node_asset_traits
bNodeTreeInterface tree_interface
ListBase inputs
float locx
ListBase outputs