Blender V5.0
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
8
9#include "BLI_listbase.h"
10#include "BLI_math_base_safe.h"
11#include "BLI_rand.hh"
12
13#include "BKE_attribute.hh"
14#include "BKE_context.hh"
15#include "BKE_curves.hh"
18#include "BKE_node_runtime.hh"
19
20#include "BLT_translation.hh"
21
22#include "ED_curves.hh"
23#include "ED_node.hh"
24#include "ED_object.hh"
25
26#include "DNA_modifier_types.h"
27#include "DNA_node_types.h"
28#include "DNA_object_types.h"
29
31
32static bool has_surface_deformation_node(const bNodeTree &ntree)
33{
34 if (!ntree.nodes_by_type("GeometryNodeDeformCurvesOnSurface").is_empty()) {
35 return true;
36 }
37 for (const bNode *node : ntree.group_nodes()) {
38 if (const bNodeTree *sub_tree = reinterpret_cast<const bNodeTree *>(node->id)) {
39 if (has_surface_deformation_node(*sub_tree)) {
40 return true;
41 }
42 }
43 }
44 return false;
45}
46
47static bool has_surface_deformation_node(const Object &curves_ob)
48{
49 LISTBASE_FOREACH (const ModifierData *, md, &curves_ob.modifiers) {
50 if (md->type != eModifierType_Nodes) {
51 continue;
52 }
53 const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
54 if (nmd->node_group == nullptr) {
55 continue;
56 }
58 return true;
59 }
60 }
61 return false;
62}
63
65{
66 if (has_surface_deformation_node(curves_ob)) {
67 return;
68 }
69
70 Main *bmain = CTX_data_main(&C);
71 Scene *scene = CTX_data_scene(&C);
72
74 nullptr, bmain, scene, &curves_ob, DATA_("Surface Deform"), eModifierType_Nodes);
75 NodesModifierData &nmd = *reinterpret_cast<NodesModifierData *>(md);
76 nmd.node_group = bke::node_tree_add_tree(bmain, DATA_("Surface Deform"), "GeometryNodeTree");
77
80 }
81
83
84 bNodeTree *ntree = nmd.node_group;
85 ntree->tree_interface.add_socket(
86 "Geometry", "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_OUTPUT, nullptr);
87 ntree->tree_interface.add_socket(
88 "Geometry", "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_INPUT, nullptr);
89 bNode *group_input = bke::node_add_static_node(&C, *ntree, NODE_GROUP_INPUT);
90 bNode *group_output = bke::node_add_static_node(&C, *ntree, NODE_GROUP_OUTPUT);
92
94
95 bke::node_add_link(*ntree,
96 *group_input,
97 *static_cast<bNodeSocket *>(group_input->outputs.first),
98 *deform_node,
99 *bke::node_find_socket(*deform_node, SOCK_IN, "Curves"));
100 bke::node_add_link(*ntree,
101 *deform_node,
102 *bke::node_find_socket(*deform_node, SOCK_OUT, "Curves"),
103 *group_output,
104 *static_cast<bNodeSocket *>(group_output->inputs.first));
105
106 group_input->location[0] = -200;
107 group_output->location[0] = 200;
108 deform_node->location[0] = 0;
109
111}
112
113bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int points_per_curve)
114{
115 bke::CurvesGeometry curves(points_per_curve * curves_size, curves_size);
116
117 MutableSpan<int> offsets = curves.offsets_for_write();
118 MutableSpan<float3> positions = curves.positions_for_write();
119 bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
121 "radius", bke::AttrDomain::Point);
122
123 for (const int i : offsets.index_range()) {
124 offsets[i] = points_per_curve * i;
125 }
126
128
129 const OffsetIndices points_by_curve = curves.points_by_curve();
130 for (const int i : curves.curves_range()) {
131 const IndexRange points = points_by_curve[i];
132 MutableSpan<float3> curve_positions = positions.slice(points);
133 MutableSpan<float> curve_radii = radius.span.slice(points);
134
135 const float theta = 2.0f * M_PI * rng.get_float();
136 const float phi = safe_acosf(2.0f * rng.get_float() - 1.0f);
137
138 float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
139 no = math::normalize(no);
140
141 float3 co = no;
142 for (int key = 0; key < points_per_curve; key++) {
143 float t = key / float(points_per_curve - 1);
144 curve_positions[key] = co;
145 curve_radii[key] = 0.02f * (1.0f - t);
146
147 float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
148 co += (offset + no) / points_per_curve;
149 }
150 }
151
152 radius.finish();
153
154 return curves;
155}
156
157} // namespace blender::ed::curves
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
Low-level operations for curves.
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:815
#define NODE_GROUP_INPUT
Definition BKE_node.hh:814
#define GEO_NODE_DEFORM_CURVES_ON_SURFACE
#define LISTBASE_FOREACH(type, var, list)
MINLINE float safe_acosf(float a)
#define M_PI
#define DATA_(msgid)
@ eModifierType_Nodes
@ GEO_NODE_ASSET_MODIFIER
@ SOCK_OUT
@ SOCK_IN
Object is a sort of wrapper for general info.
#define C
Definition RandGen.cpp:29
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:573
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
nullptr float
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2532
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
Definition node.cc:3500
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:3810
bNodeTree * node_tree_add_tree(Main *bmain, StringRef name, StringRef idname)
Definition node.cc:4085
static bool has_surface_deformation_node(const bNodeTree &ntree)
Definition curves_add.cc:32
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:64
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
float location[2]
ListBase inputs
ListBase outputs
i
Definition text_draw.cc:230