Blender  V3.3
node_geo_mesh_primitive_grid.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 "DNA_mesh_types.h"
6 #include "DNA_meshdata_types.h"
7 
8 #include "BKE_material.h"
9 #include "BKE_mesh.h"
10 
11 #include "UI_interface.h"
12 #include "UI_resources.h"
13 
14 #include "node_geometry_util.hh"
15 
16 namespace blender::nodes {
17 
18 static void calculate_uvs(
19  Mesh *mesh, Span<MVert> verts, Span<MLoop> loops, const float size_x, const float size_y)
20 {
22 
24  "uv_map", ATTR_DOMAIN_CORNER);
25 
26  const float dx = (size_x == 0.0f) ? 0.0f : 1.0f / size_x;
27  const float dy = (size_y == 0.0f) ? 0.0f : 1.0f / size_y;
28  threading::parallel_for(loops.index_range(), 1024, [&](IndexRange range) {
29  for (const int i : range) {
30  const float3 &co = verts[loops[i].v].co;
31  uv_attribute.span[i].x = (co.x + size_x * 0.5f) * dx;
32  uv_attribute.span[i].y = (co.y + size_y * 0.5f) * dy;
33  }
34  });
35 
36  uv_attribute.finish();
37 }
38 
39 Mesh *create_grid_mesh(const int verts_x,
40  const int verts_y,
41  const float size_x,
42  const float size_y)
43 {
44  BLI_assert(verts_x > 0 && verts_y > 0);
45  const int edges_x = verts_x - 1;
46  const int edges_y = verts_y - 1;
47  Mesh *mesh = BKE_mesh_new_nomain(verts_x * verts_y,
48  edges_x * verts_y + edges_y * verts_x,
49  0,
50  edges_x * edges_y * 4,
51  edges_x * edges_y);
56 
57  {
58  const float dx = edges_x == 0 ? 0.0f : size_x / edges_x;
59  const float dy = edges_y == 0 ? 0.0f : size_y / edges_y;
60  const float x_shift = edges_x / 2.0f;
61  const float y_shift = edges_y / 2.0f;
62  threading::parallel_for(IndexRange(verts_x), 512, [&](IndexRange x_range) {
63  for (const int x : x_range) {
64  const int y_offset = x * verts_y;
65  threading::parallel_for(IndexRange(verts_y), 512, [&](IndexRange y_range) {
66  for (const int y : y_range) {
67  const int vert_index = y_offset + y;
68  verts[vert_index].co[0] = (x - x_shift) * dx;
69  verts[vert_index].co[1] = (y - y_shift) * dy;
70  verts[vert_index].co[2] = 0.0f;
71  }
72  });
73  }
74  });
75  }
76 
77  const int y_edges_start = 0;
78  const int x_edges_start = verts_x * edges_y;
79  const short edge_flag = (edges_x == 0 || edges_y == 0) ? ME_LOOSEEDGE :
81 
82  /* Build the horizontal edges in the X direction. */
83  threading::parallel_for(IndexRange(verts_x), 512, [&](IndexRange x_range) {
84  for (const int x : x_range) {
85  const int y_vert_offset = x * verts_y;
86  const int y_edge_offset = y_edges_start + x * edges_y;
87  threading::parallel_for(IndexRange(edges_y), 512, [&](IndexRange y_range) {
88  for (const int y : y_range) {
89  const int vert_index = y_vert_offset + y;
90  MEdge &edge = edges[y_edge_offset + y];
91  edge.v1 = vert_index;
92  edge.v2 = vert_index + 1;
93  edge.flag = edge_flag;
94  }
95  });
96  }
97  });
98 
99  /* Build the vertical edges in the Y direction. */
100  threading::parallel_for(IndexRange(verts_y), 512, [&](IndexRange y_range) {
101  for (const int y : y_range) {
102  const int x_edge_offset = x_edges_start + y * edges_x;
103  threading::parallel_for(IndexRange(edges_x), 512, [&](IndexRange x_range) {
104  for (const int x : x_range) {
105  const int vert_index = x * verts_y + y;
106  MEdge &edge = edges[x_edge_offset + x];
107  edge.v1 = vert_index;
108  edge.v2 = vert_index + verts_y;
109  edge.flag = edge_flag;
110  }
111  });
112  }
113  });
114 
115  threading::parallel_for(IndexRange(edges_x), 512, [&](IndexRange x_range) {
116  for (const int x : x_range) {
117  const int y_offset = x * edges_y;
118  threading::parallel_for(IndexRange(edges_y), 512, [&](IndexRange y_range) {
119  for (const int y : y_range) {
120  const int poly_index = y_offset + y;
121  const int loop_index = poly_index * 4;
122  MPoly &poly = polys[poly_index];
123  poly.loopstart = loop_index;
124  poly.totloop = 4;
125  const int vert_index = x * verts_y + y;
126 
127  MLoop &loop_a = loops[loop_index];
128  loop_a.v = vert_index;
129  loop_a.e = x_edges_start + edges_x * y + x;
130  MLoop &loop_b = loops[loop_index + 1];
131  loop_b.v = vert_index + verts_y;
132  loop_b.e = y_edges_start + edges_y * (x + 1) + y;
133  MLoop &loop_c = loops[loop_index + 2];
134  loop_c.v = vert_index + verts_y + 1;
135  loop_c.e = x_edges_start + edges_x * (y + 1) + x;
136  MLoop &loop_d = loops[loop_index + 3];
137  loop_d.v = vert_index + 1;
138  loop_d.e = y_edges_start + edges_y * x + y;
139  }
140  });
141  }
142  });
143 
144  if (mesh->totpoly != 0) {
145  calculate_uvs(mesh, verts, loops, size_x, size_y);
146  }
147 
148  return mesh;
149 }
150 
151 } // namespace blender::nodes
152 
154 
156 {
157  b.add_input<decl::Float>(N_("Size X"))
158  .default_value(1.0f)
159  .min(0.0f)
160  .subtype(PROP_DISTANCE)
161  .description(N_("Side length of the plane in the X direction"));
162  b.add_input<decl::Float>(N_("Size Y"))
163  .default_value(1.0f)
164  .min(0.0f)
165  .subtype(PROP_DISTANCE)
166  .description(N_("Side length of the plane in the Y direction"));
167  b.add_input<decl::Int>(N_("Vertices X"))
168  .default_value(3)
169  .min(2)
170  .max(1000)
171  .description(N_("Number of vertices in the X direction"));
172  b.add_input<decl::Int>(N_("Vertices Y"))
173  .default_value(3)
174  .min(2)
175  .max(1000)
176  .description(N_("Number of vertices in the Y direction"));
177  b.add_output<decl::Geometry>(N_("Mesh"));
178 }
179 
181 {
182  const float size_x = params.extract_input<float>("Size X");
183  const float size_y = params.extract_input<float>("Size Y");
184  const int verts_x = params.extract_input<int>("Vertices X");
185  const int verts_y = params.extract_input<int>("Vertices Y");
186  if (verts_x < 1 || verts_y < 1) {
187  params.set_default_remaining_outputs();
188  return;
189  }
190 
191  Mesh *mesh = create_grid_mesh(verts_x, verts_y, size_x, size_y);
193 
194  params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
195 }
196 
197 } // namespace blender::nodes::node_geo_mesh_primitive_grid_cc
198 
200 {
202 
203  static bNodeType ntype;
204 
208  nodeRegisterType(&ntype);
209 }
@ ATTR_DOMAIN_CORNER
Definition: BKE_attribute.h:30
General operations, lookup, etc. for materials.
void BKE_id_material_eval_ensure_default_slot(struct ID *id)
Definition: material.c:784
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.cc:991
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
#define GEO_NODE_MESH_PRIMITIVE_GRID
Definition: BKE_node.h:1398
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define BLI_assert(a)
Definition: BLI_assert.h:46
@ ME_EDGEDRAW
@ ME_EDGERENDER
@ ME_LOOSEEDGE
_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
@ PROP_DISTANCE
Definition: RNA_types.h:149
constexpr IndexRange index_range() const
Definition: BLI_span.hh:401
GSpanAttributeWriter lookup_or_add_for_write_only_span(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type)
static float verts[][3]
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh)
static void calculate_uvs(Mesh *mesh, Span< MVert > verts, Span< MLoop > loops, const float size_x, const float size_y)
Mesh * create_grid_mesh(int verts_x, int verts_y, float size_x, float size_y)
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)
void register_node_type_geo_mesh_primitive_grid()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
static GeometrySet create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
unsigned int e
unsigned int v
struct MEdge * medge
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
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)