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
path: root/source
diff options
context:
space:
mode:
authorRajesh Advani <rajeshja>2021-08-30 06:08:57 +0300
committerHans Goudey <h.goudey@me.com>2021-08-30 06:08:57 +0300
commitb44406f9634a35ebe0b4fd334715d63e75af08a0 (patch)
tree490b61de96e341c5c5eb66621e2e36c7ea5cc34d /source
parentb42354672e804be79315315855d105e7d9e11899 (diff)
Geometry Nodes: Enhance the cube mesh primitive as a cuboid
This mesh primitive enhances the Cube mesh primitive and allows the creation of a cuboid with a configurable size and number of vertices in all 3 directions. The Cube primitive is now similar to the Grid primitive except that it works in 3 dimensions. Previously it was possible to create a cube and scale it arbitrarily along each axis. You could also subdivide the mesh, but the number of subdivisions was equal along all axes. This meant that making the basic frame for something like modular buildings wasn't trivial. Inspired by tutorials and files for modular building creation. The cuboid is created as a `Mesh` so that large meshes with millions of faces are created quickly. Though edge calculation could be faster if implemented here, edges are calculated using `BKE_mesh_calc_edges` to reduce complexity, and in hopes that they may be calculated lazily for `Mesh` in the future like vertex normals. See the differential revision for more information. Differential Revision: https://developer.blender.org/D11810
Diffstat (limited to 'source')
-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;