Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenloader/intern/versioning_300.c51
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh9
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc467
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc2
7 files changed, 508 insertions, 35 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 315a77499e5..5dc4ebaa7a4 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 19
+#define BLENDER_FILE_SUBVERSION 20
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 2456b22f046..136ea786903 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -636,6 +636,20 @@ static void do_version_constraints_spline_ik_joint_bindings(ListBase *lb)
}
}
+static bNodeSocket *do_version_replace_float_size_with_vector(bNodeTree *ntree,
+ bNode *node,
+ bNodeSocket *socket)
+{
+ const bNodeSocketValueFloat *socket_value = (const bNodeSocketValueFloat *)socket->default_value;
+ const float old_value = socket_value->value;
+ nodeRemoveSocket(ntree, node, socket);
+ bNodeSocket *new_socket = nodeAddSocket(
+ ntree, node, SOCK_IN, nodeStaticSocketType(SOCK_VECTOR, PROP_TRANSLATION), "Size", "Size");
+ bNodeSocketValueVector *value_vector = (bNodeSocketValueVector *)new_socket->default_value;
+ copy_v3_fl(value_vector->value, old_value);
+ return new_socket;
+}
+
/* NOLINTNEXTLINE: readability-function-size */
void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
@@ -1052,6 +1066,43 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 20)) {
+ /* Use new vector Size socket in Cube Mesh Primitive node. */
+ LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+ if (ntree->type != NTREE_GEOMETRY) {
+ continue;
+ }
+
+ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->tonode->type == GEO_NODE_MESH_PRIMITIVE_CUBE) {
+ bNode *node = link->tonode;
+ if (STREQ(link->tosock->identifier, "Size") && link->tosock->type == SOCK_FLOAT) {
+ bNode *link_fromnode = link->fromnode;
+ bNodeSocket *link_fromsock = link->fromsock;
+ bNodeSocket *socket = link->tosock;
+ BLI_assert(socket);
+
+ bNodeSocket *new_socket = do_version_replace_float_size_with_vector(
+ ntree, node, socket);
+ nodeAddLink(ntree, link_fromnode, link_fromsock, node, new_socket);
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type != GEO_NODE_MESH_PRIMITIVE_CUBE) {
+ continue;
+ }
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
+ if (STREQ(socket->identifier, "Size") && (socket->type == SOCK_FLOAT)) {
+ do_version_replace_float_size_with_vector(ntree, node, socket);
+ break;
+ }
+ }
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index 956b7b8a005..3251f9977bc 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -54,13 +54,20 @@ void transform_mesh(Mesh *mesh,
const float3 rotation,
const float3 scale);
+Mesh *create_line_mesh(const float3 start, const float3 delta, const int count);
+
+Mesh *create_grid_mesh(const int verts_x,
+ const int verts_y,
+ const float size_x,
+ const float size_y);
+
Mesh *create_cylinder_or_cone_mesh(const float radius_top,
const float radius_bottom,
const float depth,
const int verts_num,
const GeometryNodeMeshCircleFillType fill_type);
-Mesh *create_cube_mesh(const float size);
+Mesh *create_cuboid_mesh(float3 size, int verts_x, int verts_y, int verts_z);
/**
* Copies the point domain attributes from `in_component` that are in the mask to `out_component`.
diff --git a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
index 83d3558a7cd..6276849bc94 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
@@ -156,8 +156,8 @@ static void geo_node_bounding_box_exec(GeoNodeExecParams params)
else {
const float3 scale = max - min;
const float3 center = min + scale / 2.0f;
- Mesh *mesh = create_cube_mesh(1.0f);
- transform_mesh(mesh, center, float3(0), scale);
+ Mesh *mesh = create_cuboid_mesh(scale, 2, 2, 2);
+ transform_mesh(mesh, center, float3(0), float3(1));
params.set_output("Bounding Box", GeometrySet::create_with_mesh(mesh));
params.set_output("Min", min);
params.set_output("Max", max);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
index 3a93bc22b7e..ccf7065f7b0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
@@ -15,17 +15,18 @@
*/
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
-#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
-#include "bmesh.h"
-
#include "node_geometry_util.hh"
static bNodeSocketTemplate geo_node_mesh_primitive_cube_in[] = {
- {SOCK_FLOAT, N_("Size"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
+ {SOCK_VECTOR, N_("Size"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, FLT_MAX, PROP_TRANSLATION},
+ {SOCK_INT, N_("Vertices X"), 2, 0.0f, 0.0f, 0.0f, 2, 1000},
+ {SOCK_INT, N_("Vertices Y"), 2, 0.0f, 0.0f, 0.0f, 2, 1000},
+ {SOCK_INT, N_("Vertices Z"), 2, 0.0f, 0.0f, 0.0f, 2, 1000},
{-1, ""},
};
@@ -36,37 +37,451 @@ static bNodeSocketTemplate geo_node_mesh_primitive_cube_out[] = {
namespace blender::nodes {
-Mesh *create_cube_mesh(const float size)
+struct CuboidConfig {
+ float3 size;
+ int verts_x;
+ int verts_y;
+ int verts_z;
+ int edges_x;
+ int edges_y;
+ int edges_z;
+ int vertex_count;
+ int poly_count;
+ int loop_count;
+
+ CuboidConfig(float3 size, int verts_x, int verts_y, int verts_z)
+ : size(size),
+ verts_x(verts_x),
+ verts_y(verts_y),
+ verts_z(verts_z),
+ edges_x(verts_x - 1),
+ edges_y(verts_y - 1),
+ edges_z(verts_z - 1)
+ {
+ BLI_assert(edges_x > 0 && edges_y > 0 && edges_z > 0);
+ this->vertex_count = this->get_vertex_count();
+ this->poly_count = this->get_poly_count();
+ this->loop_count = this->poly_count * 4;
+ }
+
+ private:
+ int get_vertex_count()
+ {
+ const int inner_position_count = (verts_x - 2) * (verts_y - 2) * (verts_z - 2);
+ return verts_x * verts_y * verts_z - inner_position_count;
+ }
+
+ int get_poly_count()
+ {
+ return 2 * (edges_x * edges_y + edges_y * edges_z + edges_z * edges_x);
+ }
+};
+
+static void calculate_vertices(const CuboidConfig &config, MutableSpan<MVert> verts)
+{
+ const float z_bottom = -config.size.z / 2.0f;
+ const float z_delta = config.size.z / config.edges_z;
+
+ const float x_left = -config.size.x / 2.0f;
+ const float x_delta = config.size.x / config.edges_x;
+
+ const float y_front = -config.size.y / 2.0f;
+ const float y_delta = config.size.y / config.edges_y;
+
+ int vert_index = 0;
+
+ for (const int z : IndexRange(config.verts_z)) {
+ for (const int y : IndexRange(config.verts_y)) {
+ for (const int x : IndexRange(config.verts_x)) {
+ /* Only plot vertices on the surface of the cuboid. */
+ if (ELEM(z, 0, config.edges_z) || ELEM(x, 0, config.edges_x) ||
+ ELEM(y, 0, config.edges_y)) {
+
+ const float x_pos = x_left + x_delta * x;
+ const float y_pos = y_front + y_delta * y;
+ const float z_pos = z_bottom + z_delta * z;
+ copy_v3_v3(verts[vert_index].co, float3(x_pos, y_pos, z_pos));
+
+ vert_index++;
+ }
+ }
+ }
+ }
+}
+
+/* vert_1 = bottom left, vert_2 = bottom right, vert_3 = top right, vert_4 = top left.
+ * Hence they are passed as 1,4,3,2 when calculating polys clockwise, and 1,2,3,4 for
+ * anti-clockwise.
+ */
+static void define_quad(MutableSpan<MPoly> polys,
+ MutableSpan<MLoop> loops,
+ const int poly_index,
+ const int loop_index,
+ const int vert_1,
+ const int vert_2,
+ const int vert_3,
+ const int vert_4)
+{
+ MPoly &poly = polys[poly_index];
+ poly.loopstart = loop_index;
+ poly.totloop = 4;
+
+ MLoop &loop_1 = loops[loop_index];
+ loop_1.v = vert_1;
+ MLoop &loop_2 = loops[loop_index + 1];
+ loop_2.v = vert_2;
+ MLoop &loop_3 = loops[loop_index + 2];
+ loop_3.v = vert_3;
+ MLoop &loop_4 = loops[loop_index + 3];
+ loop_4.v = vert_4;
+}
+
+static void calculate_polys(const CuboidConfig &config,
+ MutableSpan<MPoly> polys,
+ MutableSpan<MLoop> loops)
+{
+ int loop_index = 0;
+ int poly_index = 0;
+
+ /* Number of vertices in an XY cross-section of the cube (barring top and bottom faces). */
+ const int xy_cross_section_vert_count = config.verts_x * config.verts_y -
+ (config.verts_x - 2) * (config.verts_y - 2);
+
+ /* Calculate polys for Bottom faces. */
+ int vert_1_start = 0;
+
+ for (const int UNUSED(y) : IndexRange(config.edges_y)) {
+ for (const int x : IndexRange(config.edges_x)) {
+ const int vert_1 = vert_1_start + x;
+ const int vert_2 = vert_1_start + config.verts_x + x;
+ const int vert_3 = vert_2 + 1;
+ const int vert_4 = vert_1 + 1;
+
+ define_quad(polys, loops, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4);
+ loop_index += 4;
+ poly_index++;
+ }
+ vert_1_start += config.verts_x;
+ }
+
+ /* Calculate polys for Front faces. */
+ vert_1_start = 0;
+ int vert_2_start = config.verts_x * config.verts_y;
+
+ for (const int UNUSED(z) : IndexRange(config.edges_z)) {
+ for (const int x : IndexRange(config.edges_x)) {
+ define_quad(polys,
+ loops,
+ poly_index,
+ loop_index,
+ vert_1_start + x,
+ vert_1_start + x + 1,
+ vert_2_start + x + 1,
+ vert_2_start + x);
+ loop_index += 4;
+ poly_index++;
+ }
+ vert_1_start = vert_2_start;
+ vert_2_start += config.verts_x * config.verts_y - (config.verts_x - 2) * (config.verts_y - 2);
+ }
+
+ /* Calculate polys for Top faces. */
+ vert_1_start = config.verts_x * config.verts_y +
+ (config.verts_z - 2) * (config.verts_x * config.verts_y -
+ (config.verts_x - 2) * (config.verts_y - 2));
+ vert_2_start = vert_1_start + config.verts_x;
+
+ for (const int UNUSED(y) : IndexRange(config.edges_y)) {
+ for (const int x : IndexRange(config.edges_x)) {
+ define_quad(polys,
+ loops,
+ poly_index,
+ loop_index,
+ vert_1_start + x,
+ vert_1_start + x + 1,
+ vert_2_start + x + 1,
+ vert_2_start + x);
+ loop_index += 4;
+ poly_index++;
+ }
+ vert_2_start += config.verts_x;
+ vert_1_start += config.verts_x;
+ }
+
+ /* Calculate polys for Back faces. */
+ vert_1_start = config.verts_x * config.edges_y;
+ vert_2_start = vert_1_start + xy_cross_section_vert_count;
+
+ for (const int z : IndexRange(config.edges_z)) {
+ if (z == (config.edges_z - 1)) {
+ vert_2_start += (config.verts_x - 2) * (config.verts_y - 2);
+ }
+ for (const int x : IndexRange(config.edges_x)) {
+ define_quad(polys,
+ loops,
+ poly_index,
+ loop_index,
+ vert_1_start + x,
+ vert_2_start + x,
+ vert_2_start + x + 1,
+ vert_1_start + x + 1);
+ loop_index += 4;
+ poly_index++;
+ }
+ vert_2_start += xy_cross_section_vert_count;
+ vert_1_start += xy_cross_section_vert_count;
+ }
+
+ /* Calculate polys for Left faces. */
+ vert_1_start = 0;
+ vert_2_start = config.verts_x * config.verts_y;
+
+ for (const int z : IndexRange(config.edges_z)) {
+ for (const int y : IndexRange(config.edges_y)) {
+ int vert_1;
+ int vert_2;
+ int vert_3;
+ int vert_4;
+
+ if (z == 0 || y == 0) {
+ vert_1 = vert_1_start + config.verts_x * y;
+ vert_4 = vert_1 + config.verts_x;
+ }
+ else {
+ vert_1 = vert_1_start + 2 * y;
+ vert_1 += config.verts_x - 2;
+ vert_4 = vert_1 + 2;
+ }
+
+ if (y == 0 || z == (config.edges_z - 1)) {
+ vert_2 = vert_2_start + config.verts_x * y;
+ vert_3 = vert_2 + config.verts_x;
+ }
+ else {
+ vert_2 = vert_2_start + 2 * y;
+ vert_2 += config.verts_x - 2;
+ vert_3 = vert_2 + 2;
+ }
+
+ define_quad(polys, loops, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4);
+ loop_index += 4;
+ poly_index++;
+ }
+ if (z == 0) {
+ vert_1_start += config.verts_x * config.verts_y;
+ }
+ else {
+ vert_1_start += xy_cross_section_vert_count;
+ }
+ vert_2_start += xy_cross_section_vert_count;
+ }
+
+ /* Calculate polys for Right faces. */
+ vert_1_start = config.edges_x;
+ vert_2_start = vert_1_start + config.verts_x * config.verts_y;
+
+ for (const int z : IndexRange(config.edges_z)) {
+ for (const int y : IndexRange(config.edges_y)) {
+ int vert_1 = vert_1_start;
+ int vert_2 = vert_2_start;
+ int vert_3 = vert_2_start + 2;
+ int vert_4 = vert_1 + config.verts_x;
+
+ if (z == 0) {
+ vert_1 = vert_1_start + config.verts_x * y;
+ vert_4 = vert_1 + config.verts_x;
+ }
+ else {
+ vert_1 = vert_1_start + 2 * y;
+ vert_4 = vert_1 + 2;
+ }
+
+ if (z == (config.edges_z - 1)) {
+ vert_2 = vert_2_start + config.verts_x * y;
+ vert_3 = vert_2 + config.verts_x;
+ }
+ else {
+ vert_2 = vert_2_start + 2 * y;
+ vert_3 = vert_2 + 2;
+ }
+
+ if (y == (config.edges_y - 1)) {
+ vert_3 = vert_2 + config.verts_x;
+ vert_4 = vert_1 + config.verts_x;
+ }
+
+ define_quad(polys, loops, poly_index, loop_index, vert_1, vert_4, vert_3, vert_2);
+ loop_index += 4;
+ poly_index++;
+ }
+ if (z == 0) {
+ vert_1_start += config.verts_x * config.verts_y;
+ }
+ else {
+ vert_1_start += xy_cross_section_vert_count;
+ }
+ vert_2_start += xy_cross_section_vert_count;
+ }
+}
+
+static void calculate_uvs(const CuboidConfig &config, Mesh *mesh)
{
- const float4x4 transform = float4x4::identity();
-
- const BMeshCreateParams bmcp = {true};
- const BMAllocTemplate allocsize = {8, 12, 24, 6};
- BMesh *bm = BM_mesh_create(&allocsize, &bmcp);
- BM_data_layer_add_named(bm, &bm->ldata, CD_MLOOPUV, nullptr);
-
- BMO_op_callf(bm,
- BMO_FLAG_DEFAULTS,
- "create_cube matrix=%m4 size=%f calc_uvs=%b",
- transform.values,
- size,
- true);
-
- BMeshToMeshParams params{};
- params.calc_object_remap = false;
- Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
+ MeshComponent mesh_component;
+ mesh_component.replace(mesh, GeometryOwnershipType::Editable);
+ OutputAttribute_Typed<float2> uv_attribute =
+ mesh_component.attribute_try_get_for_output_only<float2>("uv_map", ATTR_DOMAIN_CORNER);
+ MutableSpan<float2> uvs = uv_attribute.as_span();
+
+ int loop_index = 0;
+
+ const float x_delta = 0.25f / static_cast<float>(config.edges_x);
+ const float y_delta = 0.25f / static_cast<float>(config.edges_y);
+ const float z_delta = 0.25f / static_cast<float>(config.edges_z);
+
+ /* Calculate bottom face UVs. */
+ for (const int y : IndexRange(config.edges_y)) {
+ for (const int x : IndexRange(config.edges_x)) {
+ uvs[loop_index++] = float2(0.25f + x * x_delta, 0.375f - y * y_delta);
+ uvs[loop_index++] = float2(0.25f + x * x_delta, 0.375f - (y + 1) * y_delta);
+ uvs[loop_index++] = float2(0.25f + (x + 1) * x_delta, 0.375f - (y + 1) * y_delta);
+ uvs[loop_index++] = float2(0.25f + (x + 1) * x_delta, 0.375f - y * y_delta);
+ }
+ }
+
+ /* Calculate front face UVs. */
+ for (const int z : IndexRange(config.edges_z)) {
+ for (const int x : IndexRange(config.edges_x)) {
+ uvs[loop_index++] = float2(0.25f + x * x_delta, 0.375f + z * z_delta);
+ uvs[loop_index++] = float2(0.25f + (x + 1) * x_delta, 0.375f + z * z_delta);
+ uvs[loop_index++] = float2(0.25f + (x + 1) * x_delta, 0.375f + (z + 1) * z_delta);
+ uvs[loop_index++] = float2(0.25f + x * x_delta, 0.375f + (z + 1) * z_delta);
+ }
+ }
+
+ /* Calculate top face UVs. */
+ for (const int y : IndexRange(config.edges_y)) {
+ for (const int x : IndexRange(config.edges_x)) {
+ uvs[loop_index++] = float2(0.25f + x * x_delta, 0.625f + y * y_delta);
+ uvs[loop_index++] = float2(0.25f + (x + 1) * x_delta, 0.625f + y * y_delta);
+ uvs[loop_index++] = float2(0.25f + (x + 1) * x_delta, 0.625f + (y + 1) * y_delta);
+ uvs[loop_index++] = float2(0.25f + x * x_delta, 0.625f + (y + 1) * y_delta);
+ }
+ }
+
+ /* Calculate back face UVs. */
+ for (const int z : IndexRange(config.edges_z)) {
+ for (const int x : IndexRange(config.edges_x)) {
+ uvs[loop_index++] = float2(1.0f - x * x_delta, 0.375f + z * z_delta);
+ uvs[loop_index++] = float2(1.0f - x * x_delta, 0.375f + (z + 1) * z_delta);
+ uvs[loop_index++] = float2(1.0f - (x + 1) * x_delta, 0.375f + (z + 1) * z_delta);
+ uvs[loop_index++] = float2(1.0f - (x + 1) * x_delta, 0.375f + z * z_delta);
+ }
+ }
+
+ /* Calculate left face UVs. */
+ for (const int z : IndexRange(config.edges_z)) {
+ for (const int y : IndexRange(config.edges_y)) {
+ uvs[loop_index++] = float2(0.25f - y * y_delta, 0.375f + z * z_delta);
+ uvs[loop_index++] = float2(0.25f - y * y_delta, 0.375f + (z + 1) * z_delta);
+ uvs[loop_index++] = float2(0.25f - (y + 1) * y_delta, 0.375f + (z + 1) * z_delta);
+ uvs[loop_index++] = float2(0.25f - (y + 1) * y_delta, 0.375f + z * z_delta);
+ }
+ }
+
+ /* Calculate right face UVs. */
+ for (const int z : IndexRange(config.edges_z)) {
+ for (const int y : IndexRange(config.edges_y)) {
+ uvs[loop_index++] = float2(0.50f + y * y_delta, 0.375f + z * z_delta);
+ uvs[loop_index++] = float2(0.50f + (y + 1) * y_delta, 0.375f + z * z_delta);
+ uvs[loop_index++] = float2(0.50f + (y + 1) * y_delta, 0.375f + (z + 1) * z_delta);
+ uvs[loop_index++] = float2(0.50f + y * y_delta, 0.375f + (z + 1) * z_delta);
+ }
+ }
+
+ uv_attribute.save();
+}
+
+Mesh *create_cuboid_mesh(const float3 size,
+ const int verts_x,
+ const int verts_y,
+ const int verts_z)
+{
+ const CuboidConfig config(size, verts_x, verts_y, verts_z);
+
+ Mesh *mesh = BKE_mesh_new_nomain(
+ config.vertex_count, 0, 0, config.loop_count, config.poly_count);
BKE_id_material_eval_ensure_default_slot(&mesh->id);
- BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
- BM_mesh_free(bm);
+
+ calculate_vertices(config, {mesh->mvert, mesh->totvert});
+
+ calculate_polys(config, {mesh->mpoly, mesh->totpoly}, {mesh->mloop, mesh->totloop});
+ BKE_mesh_calc_edges(mesh, false, false);
+ BKE_mesh_normals_tag_dirty(mesh);
+
+ calculate_uvs(config, mesh);
return mesh;
}
+static Mesh *create_cube_mesh(const float3 size,
+ const int verts_x,
+ const int verts_y,
+ const int verts_z)
+{
+ const int dimensions = (verts_x - 1 > 0) + (verts_y - 1 > 0) + (verts_z - 1 > 0);
+ if (dimensions == 0) {
+ return create_line_mesh(float3(0), float3(0), 1);
+ }
+ if (dimensions == 1) {
+ float3 start;
+ float3 delta;
+ if (verts_x > 1) {
+ start = {-size.x / 2.0f, 0, 0};
+ delta = {size.x / (verts_x - 1), 0, 0};
+ }
+ else if (verts_y > 1) {
+ start = {0, -size.y / 2.0f, 0};
+ delta = {0, size.y / (verts_y - 1), 0};
+ }
+ else {
+ start = {0, 0, -size.z / 2.0f};
+ delta = {0, 0, size.z / (verts_z - 1)};
+ }
+
+ return create_line_mesh(start, delta, verts_x * verts_y * verts_z);
+ }
+ if (dimensions == 2) {
+ if (verts_z == 1) { /* XY plane. */
+ return create_grid_mesh(verts_x, verts_y, size.x, size.y);
+ }
+ if (verts_y == 1) { /* XZ plane. */
+ Mesh *mesh = create_grid_mesh(verts_x, verts_z, size.x, size.z);
+ transform_mesh(mesh, float3(0), float3(M_PI_2, 0.0f, 0.0f), float3(1));
+ return mesh;
+ }
+ /* YZ plane. */
+ Mesh *mesh = create_grid_mesh(verts_z, verts_y, size.z, size.y);
+ transform_mesh(mesh, float3(0), float3(0.0f, M_PI_2, 0.0f), float3(1));
+ return mesh;
+ }
+
+ return create_cuboid_mesh(size, verts_x, verts_y, verts_z);
+}
+
static void geo_node_mesh_primitive_cube_exec(GeoNodeExecParams params)
{
- const float size = params.extract_input<float>("Size");
+ const float3 size = params.extract_input<float3>("Size");
+ const int verts_x = params.extract_input<int>("Vertices X");
+ const int verts_y = params.extract_input<int>("Vertices Y");
+ const int verts_z = params.extract_input<int>("Vertices Z");
+ if (verts_x < 1 || verts_y < 1 || verts_z < 1) {
+ params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 1"));
+ params.set_output("Geometry", GeometrySet());
+ return;
+ }
+
+ Mesh *mesh = create_cube_mesh(size, verts_x, verts_y, verts_z);
- Mesh *mesh = create_cube_mesh(size);
params.set_output("Geometry", GeometrySet::create_with_mesh(mesh));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
index ca1dafbdf5b..ad963898138 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
@@ -60,10 +60,10 @@ static void calculate_uvs(
uv_attribute.save();
}
-static Mesh *create_grid_mesh(const int verts_x,
- const int verts_y,
- const float size_x,
- const float size_y)
+Mesh *create_grid_mesh(const int verts_x,
+ const int verts_y,
+ const float size_x,
+ const float size_y)
{
BLI_assert(verts_x > 0 && verts_y > 0);
const int edges_x = verts_x - 1;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
index 2e6d8ca34c8..ad0bd854a8f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
@@ -104,7 +104,7 @@ static void fill_edge_data(MutableSpan<MEdge> edges)
}
}
-static Mesh *create_line_mesh(const float3 start, const float3 delta, const int count)
+Mesh *create_line_mesh(const float3 start, const float3 delta, const int count)
{
if (count < 1) {
return nullptr;