Blender V4.3
node_geo_mesh_primitive_circle.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
5#include "BKE_material.h"
6#include "BKE_mesh.hh"
7
8#include "NOD_rna_define.hh"
9
10#include "UI_interface.hh"
11#include "UI_resources.hh"
12
13#include "BLI_array_utils.hh"
14
16
17#include "node_geometry_util.hh"
18
19#include "RNA_enum_types.hh"
20
22
24
26{
27 b.add_input<decl::Int>("Vertices")
28 .default_value(32)
29 .min(3)
30 .description("Number of vertices on the circle");
31 b.add_input<decl::Float>("Radius")
32 .default_value(1.0f)
33 .min(0.0f)
35 .description("Distance of the vertices from the origin");
36 b.add_output<decl::Geometry>("Mesh");
37}
38
39static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
40{
41 uiLayoutSetPropSep(layout, true);
42 uiLayoutSetPropDecorate(layout, false);
43 uiItemR(layout, ptr, "fill_type", UI_ITEM_NONE, nullptr, ICON_NONE);
44}
45
46static void node_init(bNodeTree * /*tree*/, bNode *node)
47{
48 NodeGeometryMeshCircle *node_storage = MEM_cnew<NodeGeometryMeshCircle>(__func__);
49
51
52 node->storage = node_storage;
53}
54
55static int circle_vert_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
56{
57 switch (fill_type) {
60 return verts_num;
62 return verts_num + 1;
63 }
65 return 0;
66}
67
68static int circle_edge_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
69{
70 switch (fill_type) {
73 return verts_num;
75 return verts_num * 2;
76 }
78 return 0;
79}
80
81static int circle_corner_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
82{
83 switch (fill_type) {
85 return 0;
87 return verts_num;
89 return verts_num * 3;
90 }
92 return 0;
93}
94
95static int circle_face_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
96{
97 switch (fill_type) {
99 return 0;
101 return 1;
103 return verts_num;
104 }
106 return 0;
107}
108
109static Bounds<float3> calculate_bounds_circle(const float radius, const int verts_num)
110{
111 return geometry::calculate_bounds_radial_primitive(0.0f, radius, verts_num, 0.0f);
112}
113
114static Mesh *create_circle_mesh(const float radius,
115 const int verts_num,
116 const GeometryNodeMeshCircleFillType fill_type)
117{
118 Mesh *mesh = BKE_mesh_new_nomain(circle_vert_total(fill_type, verts_num),
119 circle_edge_total(fill_type, verts_num),
120 circle_face_total(fill_type, verts_num),
121 circle_corner_total(fill_type, verts_num));
123 MutableSpan<float3> positions = mesh->vert_positions_for_write();
124 MutableSpan<int2> edges = mesh->edges_for_write();
125 MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
126 MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
127 MutableSpan<int> corner_edges = mesh->corner_edges_for_write();
128 bke::mesh_smooth_set(*mesh, false);
129
130 /* Assign vertex coordinates. */
131 const float angle_delta = 2.0f * (M_PI / float(verts_num));
132 for (const int i : IndexRange(verts_num)) {
133 const float angle = i * angle_delta;
134 positions[i] = float3(std::cos(angle) * radius, std::sin(angle) * radius, 0.0f);
135 }
137 positions.last() = float3(0);
138 }
139
140 /* Create outer edges. */
141 for (const int i : IndexRange(verts_num)) {
142 int2 &edge = edges[i];
143 edge[0] = i;
144 edge[1] = (i + 1) % verts_num;
145 }
146
147 /* Create triangle fan edges. */
149 for (const int i : IndexRange(verts_num)) {
150 int2 &edge = edges[verts_num + i];
151 edge[0] = verts_num;
152 edge[1] = i;
153 }
154 }
155
156 /* Create corners and faces. */
157 if (fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) {
158 face_offsets.first() = 0;
159 face_offsets.last() = corner_verts.size();
160
163
164 mesh->tag_loose_edges_none();
165 }
166 else if (fill_type == GEO_NODE_MESH_CIRCLE_FILL_TRIANGLE_FAN) {
167 for (const int i : face_offsets.index_range()) {
168 face_offsets[i] = 3 * i;
169 }
170 for (const int i : IndexRange(verts_num)) {
171 corner_verts[3 * i] = i;
172 corner_edges[3 * i] = i;
173
174 corner_verts[3 * i + 1] = (i + 1) % verts_num;
175 corner_edges[3 * i + 1] = verts_num + ((i + 1) % verts_num);
176
177 corner_verts[3 * i + 2] = verts_num;
178 corner_edges[3 * i + 2] = verts_num + i;
179 }
180 }
181
182 mesh->tag_loose_verts_none();
183 mesh->tag_overlapping_none();
184 mesh->bounds_set_eager(calculate_bounds_circle(radius, verts_num));
185
186 return mesh;
187}
188
190{
191 const NodeGeometryMeshCircle &storage = node_storage(params.node());
193
194 const float radius = params.extract_input<float>("Radius");
195 const int verts_num = params.extract_input<int>("Vertices");
196 if (verts_num < 3) {
197 params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3"));
198 params.set_default_remaining_outputs();
199 return;
200 }
201
202 Mesh *mesh = create_circle_mesh(radius, verts_num, fill);
203
204 params.set_output("Mesh", GeometrySet::from_mesh(mesh));
205}
206
207static void node_rna(StructRNA *srna)
208{
210 "fill_type",
211 "Fill Type",
212 "",
216 nullptr,
217 true);
218}
219
220static void node_register()
221{
222 static blender::bke::bNodeType ntype;
223
224 geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Mesh Circle", NODE_CLASS_GEOMETRY);
225 ntype.initfunc = node_init;
227 &ntype, "NodeGeometryMeshCircle", node_free_standard_storage, node_copy_standard_storage);
230 ntype.declare = node_declare;
232
233 node_rna(ntype.rna_ext.srna);
234}
236
237} // namespace blender::nodes::node_geo_mesh_primitive_circle_cc
General operations, lookup, etc. for materials.
void BKE_id_material_eval_ensure_default_slot(struct ID *id)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:418
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define M_PI
#define TIP_(msgid)
GeometryNodeMeshCircleFillType
@ GEO_NODE_MESH_CIRCLE_FILL_NGON
@ GEO_NODE_MESH_CIRCLE_FILL_TRIANGLE_FAN
@ GEO_NODE_MESH_CIRCLE_FILL_NONE
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
@ PROP_DISTANCE
Definition RNA_types.hh:159
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr T & first() const
Definition BLI_span.hh:680
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:690
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void fill_index_range(MutableSpan< T > span, const T start=0)
void mesh_smooth_set(Mesh &mesh, bool use_smooth, bool keep_sharp_edges=false)
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
Bounds< float3 > calculate_bounds_radial_primitive(float radius_top, float radius_bottom, int segments, float height)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static int circle_edge_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
static int circle_corner_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
static int circle_vert_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
static Mesh * create_circle_mesh(const float radius, const int verts_num, const GeometryNodeMeshCircleFillType fill_type)
static int circle_face_total(const GeometryNodeMeshCircleFillType fill_type, const int verts_num)
static Bounds< float3 > calculate_bounds_circle(const float radius, const int verts_num)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
const EnumPropertyItem rna_enum_node_geometry_mesh_circle_fill_type_items[]
StructRNA * srna
Definition RNA_types.hh:780
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Defines a node type.
Definition BKE_node.hh:218
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:339
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
PointerRNA * ptr
Definition wm_files.cc:4126