diff options
6 files changed, 459 insertions, 410 deletions
diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index 9dcacb13536..cf89426bfc4 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -7,6 +7,7 @@ set(INC ../blenlib ../blentranslation ../functions + ../guardedalloc ../makesdna ../makesrna ../../../intern/eigen @@ -16,6 +17,7 @@ set(INC set(SRC intern/mesh_merge_by_distance.cc + intern/mesh_primitive_cuboid.cc intern/mesh_to_curve_convert.cc intern/point_merge_by_distance.cc intern/realize_instances.cc @@ -23,6 +25,7 @@ set(SRC intern/uv_parametrizer.c GEO_mesh_merge_by_distance.hh + GEO_mesh_primitive_cuboid.hh GEO_mesh_to_curve.hh GEO_point_merge_by_distance.hh GEO_realize_instances.hh diff --git a/source/blender/geometry/GEO_mesh_primitive_cuboid.hh b/source/blender/geometry/GEO_mesh_primitive_cuboid.hh new file mode 100644 index 00000000000..d8f16065e2b --- /dev/null +++ b/source/blender/geometry/GEO_mesh_primitive_cuboid.hh @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +struct Mesh; +struct float3; +namespace blender { +namespace bke { +class AttributeIDRef; +} +} // namespace blender + +namespace blender::geometry { + +Mesh *create_cuboid_mesh( + const float3 &size, int verts_x, int verts_y, int verts_z, const bke::AttributeIDRef &uv_id); + +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/mesh_primitive_cuboid.cc b/source/blender/geometry/intern/mesh_primitive_cuboid.cc new file mode 100644 index 00000000000..e41516d0486 --- /dev/null +++ b/source/blender/geometry/intern/mesh_primitive_cuboid.cc @@ -0,0 +1,423 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_index_range.hh" +#include "BLI_math_vector.h" +#include "BLI_math_vector.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_attribute_access.hh" +#include "BKE_geometry_set.hh" +#include "BKE_mesh.h" + +#include "GEO_mesh_primitive_cuboid.hh" + +namespace blender::geometry { + +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)) { + if (ELEM(z, 0, config.edges_z)) { + /* Fill bottom and top. */ + const float z_pos = z_bottom + z_delta * z; + for (const int y : IndexRange(config.verts_y)) { + const float y_pos = y_front + y_delta * y; + for (const int x : IndexRange(config.verts_x)) { + const float x_pos = x_left + x_delta * x; + copy_v3_v3(verts[vert_index++].co, float3(x_pos, y_pos, z_pos)); + } + } + } + else { + for (const int y : IndexRange(config.verts_y)) { + if (ELEM(y, 0, config.edges_y)) { + /* Fill y-sides. */ + const float y_pos = y_front + y_delta * y; + const float z_pos = z_bottom + z_delta * z; + for (const int x : IndexRange(config.verts_x)) { + const float x_pos = x_left + x_delta * x; + copy_v3_v3(verts[vert_index++].co, float3(x_pos, y_pos, z_pos)); + } + } + else { + /* Fill x-sides. */ + const float x_pos = x_left; + 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)); + const float x_pos2 = x_left + x_delta * config.edges_x; + copy_v3_v3(verts[vert_index++].co, float3(x_pos2, y_pos, z_pos)); + } + } + } + } +} + +/* 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 ([[maybe_unused]] const int 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 ([[maybe_unused]] const int 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 ([[maybe_unused]] const int 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 bke::AttributeIDRef &uv_id) +{ + MeshComponent mesh_component; + mesh_component.replace(mesh, GeometryOwnershipType::Editable); + bke::OutputAttribute_Typed<float2> uv_attribute = + mesh_component.attribute_try_get_for_output_only<float2>(uv_id, 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 bke::AttributeIDRef &uv_id) +{ + 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); + + 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); + + if (uv_id) { + calculate_uvs(config, mesh, uv_id); + } + + return mesh; +} + +} // namespace blender::geometry diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 5b7211e44b4..8f20da66c3b 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -57,8 +57,6 @@ Mesh *create_cylinder_or_cone_mesh(float radius_top, GeometryNodeMeshCircleFillType fill_type, ConeAttributeOutputs &attribute_outputs); -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 558129fb384..00b10cc8a2f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "GEO_mesh_primitive_cuboid.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_bounding_box_cc { @@ -53,7 +55,7 @@ static void node_geo_exec(GeoNodeExecParams params) else { const float3 scale = sub_max - sub_min; const float3 center = sub_min + scale / 2.0f; - Mesh *mesh = create_cuboid_mesh(scale, 2, 2, 2); + Mesh *mesh = geometry::create_cuboid_mesh(scale, 2, 2, 2, "uv_map"); transform_mesh(*mesh, center, float3(0), float3(1)); sub_geometry.replace_mesh(mesh); sub_geometry.keep_only({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_INSTANCES}); 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 636ecb8ab41..0029b547375 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 @@ -6,414 +6,9 @@ #include "BKE_material.h" #include "BKE_mesh.h" -#include "node_geometry_util.hh" - -namespace blender::nodes { - -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)) { - if (ELEM(z, 0, config.edges_z)) { - /* Fill bottom and top. */ - const float z_pos = z_bottom + z_delta * z; - for (const int y : IndexRange(config.verts_y)) { - const float y_pos = y_front + y_delta * y; - for (const int x : IndexRange(config.verts_x)) { - const float x_pos = x_left + x_delta * x; - copy_v3_v3(verts[vert_index++].co, float3(x_pos, y_pos, z_pos)); - } - } - } - else { - for (const int y : IndexRange(config.verts_y)) { - if (ELEM(y, 0, config.edges_y)) { - /* Fill y-sides. */ - const float y_pos = y_front + y_delta * y; - const float z_pos = z_bottom + z_delta * z; - for (const int x : IndexRange(config.verts_x)) { - const float x_pos = x_left + x_delta * x; - copy_v3_v3(verts[vert_index++].co, float3(x_pos, y_pos, z_pos)); - } - } - else { - /* Fill x-sides. */ - const float x_pos = x_left; - 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)); - const float x_pos2 = x_left + x_delta * config.edges_x; - copy_v3_v3(verts[vert_index++].co, float3(x_pos2, y_pos, z_pos)); - } - } - } - } -} - -/* 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); +#include "GEO_mesh_primitive_cuboid.hh" - /* Calculate polys for Bottom faces. */ - int vert_1_start = 0; - - for ([[maybe_unused]] const int 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 ([[maybe_unused]] const int 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 ([[maybe_unused]] const int 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) -{ - 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); - - 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); - - calculate_uvs(config, mesh); - - return mesh; -} - -} // namespace blender::nodes +#include "node_geometry_util.hh" namespace blender::nodes::node_geo_mesh_primitive_cube_cc { @@ -442,6 +37,16 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output<decl::Geometry>(N_("Mesh")); } +static Mesh *create_cuboid_mesh(const float3 &size, + const int verts_x, + const int verts_y, + const int verts_z) +{ + Mesh *mesh = geometry::create_cuboid_mesh(size, verts_x, verts_y, verts_z, "uv_map"); + BKE_id_material_eval_ensure_default_slot(&mesh->id); + return mesh; +} + static Mesh *create_cube_mesh(const float3 size, const int verts_x, const int verts_y, |