diff options
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, ¶ms); - 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; |