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:
authorFabian Schempp <fabianschempp@googlemail.com>2022-02-05 01:39:06 +0300
committerFabian Schempp <fabianschempp@googlemail.com>2022-02-05 01:39:06 +0300
commit06dadc78a7ea879d296b6d3f4d906069550765f6 (patch)
treef27b445dd045155d3000044616764fd2c8972934
parentc1ae3b850c9c1b43ce6928add5362bcea63d7223 (diff)
-rw-r--r--source/blender/geometry/intern/solidify_nonmanifold.c62
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c30
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/geometry/CMakeLists.txt1
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_solidify.cc241
5 files changed, 184 insertions, 151 deletions
diff --git a/source/blender/geometry/intern/solidify_nonmanifold.c b/source/blender/geometry/intern/solidify_nonmanifold.c
index 936c7f157b2..5d08648e17c 100644
--- a/source/blender/geometry/intern/solidify_nonmanifold.c
+++ b/source/blender/geometry/intern/solidify_nonmanifold.c
@@ -140,12 +140,14 @@ static int comp_float_int_pair(const void *a, const void *b)
}
/* NOLINTNEXTLINE: readability-function-size */
-Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
- const ModifierEvalContext *ctx,
- Mesh *mesh)
+Mesh *solidify_nonmanifold(const SolidifyData *solidify_data,
+ Mesh *mesh,
+ bool **r_shell_verts,
+ bool **r_rim_verts,
+ bool **r_shell_faces,
+ bool **r_rim_faces)
{
Mesh *result;
- const SolidifyModifierData *smd = (SolidifyModifierData *)md;
MVert *mv, *mvert, *orig_mvert;
MEdge *ed, *medge, *orig_medge;
@@ -154,39 +156,28 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
const uint numVerts = (uint)mesh->totvert;
const uint numEdges = (uint)mesh->totedge;
const uint numPolys = (uint)mesh->totpoly;
+ const uint numLoops = (uint)mesh->totloop;
if (numPolys == 0 && numVerts != 0) {
return mesh;
}
- /* Only use material offsets if we have 2 or more materials. */
- const short mat_nrs = ctx->object->totcol > 1 ? ctx->object->totcol : 1;
- const short mat_nr_max = mat_nrs - 1;
- const short mat_ofs = mat_nrs > 1 ? smd->mat_ofs : 0;
- const short mat_ofs_rim = mat_nrs > 1 ? smd->mat_ofs_rim : 0;
-
- /* #ofs_front and #ofs_back are the offset from the original
- * surface along the normal, where #oft_front is along the positive
- * and #oft_back is along the negative normal. */
- const float ofs_front = (smd->offset_fac + 1.0f) * 0.5f * smd->offset;
- const float ofs_back = ofs_front - smd->offset * smd->offset_fac;
- /* #ofs_front_clamped and #ofs_back_clamped are the same as
- * #ofs_front and #ofs_back, but never zero. */
- const float ofs_front_clamped = clamp_nonzero(ofs_front, 1e-5f);
- const float ofs_back_clamped = clamp_nonzero(ofs_back, 1e-5f);
- const float offset_fac_vg = smd->offset_fac_vg;
- const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg;
- const float offset = fabsf(smd->offset) * smd->offset_clamp;
- const bool do_angle_clamp = smd->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP;
- /* #do_flip, flips the normals of the result. This is inverted if negative thickness
- * is used, since simple solidify with negative thickness keeps the faces facing outside. */
- const bool do_flip = ((smd->flag & MOD_SOLIDIFY_FLIP) != 0) == (smd->offset > 0);
- const bool do_rim = smd->flag & MOD_SOLIDIFY_RIM;
- const bool do_shell = ((smd->flag & MOD_SOLIDIFY_RIM) && (smd->flag & MOD_SOLIDIFY_NOSHELL)) ==
- 0;
- const bool do_clamp = (smd->offset_clamp != 0.0f);
-
- const float bevel_convex = smd->bevel_convex;
+ float(*poly_nors)[3] = NULL;
+
+ const float ofs_front = (solidify_data->offset_fac + 1.0f) * 0.5f * solidify_data->offset;
+ const float ofs_back = ofs_front - solidify_data->offset * solidify_data->offset_fac;
+ const float ofs_front_clamped = max_ff(1e-5f,
+ fabsf(solidify_data->offset > 0 ? ofs_front : ofs_back));
+ const float ofs_back_clamped = max_ff(1e-5f,
+ fabsf(solidify_data->offset > 0 ? ofs_back : ofs_front));
+ const float offset_fac_vg = solidify_data->offset_fac_vg;
+ const float offset_fac_vg_inv = 1.0f - solidify_data->offset_fac_vg;
+ const float offset = fabsf(solidify_data->offset) * solidify_data->offset_clamp;
+ const bool do_angle_clamp = solidify_data->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP;
+ const bool do_flip = (solidify_data->flag & MOD_SOLIDIFY_FLIP) != 0;
+ const bool do_rim = solidify_data->flag & MOD_SOLIDIFY_RIM;
+ const bool do_shell = solidify_data->flag & MOD_SOLIDIFY_SHELL;
+ const bool do_clamp = (solidify_data->offset_clamp != 0.0f);
const float bevel_convex = solidify_data->bevel_convex;
@@ -204,9 +195,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
#define MOD_SOLIDIFY_EMPTY_TAG ((uint)-1)
- /* Calculate only face normals. Copied because they are modified directly below. */
- float(*poly_nors)[3] = MEM_malloc_arrayN(numPolys, sizeof(float[3]), __func__);
- memcpy(poly_nors, BKE_mesh_poly_normals_ensure(mesh), sizeof(float[3]) * numPolys);
+ /* Calculate only face normals. */
+ poly_nors = MEM_malloc_arrayN(numPolys, sizeof(*poly_nors), __func__);
+ BKE_mesh_calc_normals_poly(
+ orig_mvert, (int)numVerts, orig_mloop, (int)numLoops, orig_mpoly, (int)numPolys, poly_nors);
NewFaceRef *face_sides_arr = MEM_malloc_arrayN(
numPolys * 2, sizeof(*face_sides_arr), "face_sides_arr in solidify");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 86bae61258c..57624a4a0cd 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -10485,6 +10485,36 @@ static void def_geo_point_scale(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static const EnumPropertyItem nonmanifold_thickness_mode_items[] = {
+ {MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_FIXED,
+ "FIXED",
+ 0,
+ "Fixed",
+ "Most basic thickness calculation"},
+ {MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN,
+ "EVEN",
+ 0,
+ "Even",
+ "Even thickness calculation which takes the angle between faces into account"},
+ {MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS,
+ "CONSTRAINTS",
+ 0,
+ "Constraints",
+ "Thickness calculation using constraints, most advanced"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static const EnumPropertyItem nonmanifold_boundary_mode_items[] = {
+ {MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE, "NONE", 0, "None", "No shape correction"},
+ {MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_ROUND,
+ "ROUND",
+ 0,
+ "Round",
+ "Round open perimeter shape"},
+ {MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT, "FLAT", 0, "Flat", "Flat open perimeter shape"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static void def_geo_solidify(StructRNA *srna)
{
PropertyRNA *prop;
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index d41d294a371..816e492bc49 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -434,7 +434,6 @@ DefNode(GeometryNode, GEO_NODE_STRING_TO_CURVES, def_geo_string_to_curves, "STRI
DefNode(GeometryNode, GEO_NODE_SUBDIVIDE_CURVE, 0, "SUBDIVIDE_CURVE", SubdivideCurve, "Subdivide Curve", "")
DefNode(GeometryNode, GEO_NODE_SUBDIVIDE_MESH, 0, "SUBDIVIDE_MESH", SubdivideMesh, "Subdivide Mesh", "")
DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, def_geo_subdivision_surface, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "")
-DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "")
DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "")
DefNode(GeometryNode, GEO_NODE_TRANSFER_ATTRIBUTE, def_geo_transfer_attribute, "ATTRIBUTE_TRANSFER", AttributeTransfer, "Transfer Attribute", "")
DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "")
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
index 2a8faf65a6d..a8ad9d3e0e4 100644
--- a/source/blender/nodes/geometry/CMakeLists.txt
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -184,6 +184,7 @@ set(SRC
nodes/node_geo_set_shade_smooth.cc
nodes/node_geo_set_spline_cyclic.cc
nodes/node_geo_set_spline_resolution.cc
+ nodes/node_geo_solidify.cc
nodes/node_geo_string_join.cc
nodes/node_geo_string_to_curves.cc
nodes/node_geo_subdivision_surface.cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_solidify.cc b/source/blender/nodes/geometry/nodes/node_geo_solidify.cc
index 197aa0a09c1..41448a37d34 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_solidify.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_solidify.cc
@@ -27,31 +27,36 @@
#include "node_geometry_util.hh"
-static bNodeSocketTemplate geo_node_solidify_in[] = {
- {SOCK_GEOMETRY, N_("Geometry")},
- {SOCK_STRING, N_("Thickness")},
- {SOCK_FLOAT, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
- {SOCK_FLOAT, N_("Clamp"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR},
- {SOCK_FLOAT, N_("Offset"), -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR},
- {SOCK_BOOLEAN, N_("Fill"), true},
- {SOCK_BOOLEAN, N_("Rim"), true},
- {SOCK_STRING, N_("Fill Faces")},
- {SOCK_STRING, N_("Rim Faces")},
- {-1, ""},
-};
-
-static bNodeSocketTemplate geo_node_solidify_out[] = {
- {SOCK_GEOMETRY, N_("Geometry")},
- {-1, ""},
-};
-
-namespace blender::nodes {
-
-static void geo_node_solidify_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+namespace blender::nodes::node_geo_solidify {
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
+ b.add_input<decl::Float>(N_("Thickness"))
+ .default_value(0.0f)
+ .subtype(PROP_DISTANCE)
+ .supports_field();
+ b.add_input<decl::Float>(N_("Clamp"))
+ .default_value(0.0f)
+ .min(0.0f)
+ .max(2.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Offset"))
+ .default_value(0.0f)
+ .min(-1.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Bool>(N_("Fill")).default_value(true);
+ b.add_input<decl::Bool>(N_("Rim")).default_value(true);
+
+ b.add_output<decl::Geometry>(N_("Mesh"));
+ b.add_output<decl::Bool>(N_("Fill Faces")).field_source();
+ b.add_output<decl::Bool>(N_("Rim Faces")).field_source();
+}
+
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
- uiItemR(layout, ptr, "thickness_mode", 0, nullptr, ICON_NONE);
uiItemR(layout, ptr, "nonmanifold_offset_mode", 0, nullptr, ICON_NONE);
uiItemR(layout, ptr, "nonmanifold_boundary_mode", 0, nullptr, ICON_NONE);
}
@@ -62,126 +67,132 @@ static void geo_node_solidify_init(bNodeTree *UNUSED(tree), bNode *node)
sizeof(NodeGeometrySolidify), __func__);
node->storage = node_storage;
- node_storage->thickness_mode = GEO_NODE_ATTRIBUTE_INPUT_FLOAT;
-}
-
-static void geo_node_solidify_update(bNodeTree *UNUSED(ntree), bNode *node)
-{
- const NodeGeometrySolidify *node_storage = (NodeGeometrySolidify *)node->storage;
-
- update_attribute_input_socket_availabilities(
- *node, "Thickness", (GeometryNodeAttributeInputMode)node_storage->thickness_mode, true);
}
-static void geo_node_solidify_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const bNode &node = params.node();
NodeGeometrySolidify &node_storage = *(NodeGeometrySolidify *)node.storage;
const Object *self_object = params.self_object();
- GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
bool add_fill = params.extract_input<bool>("Fill");
bool add_rim = params.extract_input<bool>("Rim");
-
- char flag = 0;
-
- if (add_fill) {
- flag |= MOD_SOLIDIFY_SHELL;
- }
-
- if (add_rim) {
- flag |= MOD_SOLIDIFY_RIM;
- }
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
float offset = params.extract_input<float>("Offset");
float offset_clamp = params.extract_input<float>("Clamp");
- geometry_set = geometry_set_realize_instances(geometry_set);
+ bke::StrongAnonymousAttributeID fill_id;
+ bke::StrongAnonymousAttributeID rim_id;
if (geometry_set.has<MeshComponent>()) {
- MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
- Mesh *input_mesh = mesh_component.get_for_write();
-
- const float default_thickness = 0;
- GVArray_Typed<float> thickness_attribute = params.get_input_attribute<float>(
-
- "Thickness", mesh_component, ATTR_DOMAIN_POINT, default_thickness);
- VArray_Span<float> thickness{thickness_attribute};
-
- SolidifyData solidify_node_data = {
- self_object,
- 1,
- offset,
- 0.0f,
- offset_clamp,
- node_storage.nonmanifold_offset_mode,
- node_storage.nonmanifold_boundary_mode,
- flag,
- 0.01f,
- 0.0f,
- thickness.data(),
- };
-
- bool *shell_verts = nullptr;
- bool *rim_verts = nullptr;
- bool *shell_faces = nullptr;
- bool *rim_faces = nullptr;
-
- Mesh *output_mesh = solidify_nonmanifold(
- &solidify_node_data, input_mesh, &shell_verts, &rim_verts, &shell_faces, &rim_faces);
-
- if (output_mesh != input_mesh) {
- geometry_set.replace_mesh(output_mesh);
- }
-
- const AttributeDomain result_face_domain = ATTR_DOMAIN_FACE;
-
- const std::string shell_faces_attribute_name = params.get_input<std::string>("Fill Faces");
- const std::string rim_faces_attribute_name = params.get_input<std::string>("Rim Faces");
-
- if (solidify_node_data.flag & MOD_SOLIDIFY_SHELL) {
- if (!shell_faces_attribute_name.empty()) {
- OutputAttribute_Typed<bool> shell_faces_attribute =
- mesh_component.attribute_try_get_for_output_only<bool>(shell_faces_attribute_name,
- result_face_domain);
- Span<bool> shell_faces_span(shell_faces, shell_faces_attribute->size());
- shell_faces_attribute->set_all(shell_faces_span);
- shell_faces_attribute.save();
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ MeshComponent &component = geometry_set.get_component_for_write<MeshComponent>();
+ Mesh *input_mesh = component.get_for_write();
+
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ GeometryComponentFieldContext context{component, ATTR_DOMAIN_POINT};
+
+ Field<float> thickness_field = params.extract_input<Field<float>>("Thickness");
+ FieldEvaluator thickness_evaluator{context, domain_size};
+ thickness_evaluator.add(thickness_field);
+ thickness_evaluator.evaluate();
+ Array<float> thickness(domain_size);
+ thickness_evaluator.get_evaluated<float>(0).materialize(thickness);
+
+ char flag = 0;
+
+ if (add_fill) {
+ flag |= MOD_SOLIDIFY_SHELL;
+ }
+
+ if (add_rim) {
+ flag |= MOD_SOLIDIFY_RIM;
}
- }
-
- if (solidify_node_data.flag & MOD_SOLIDIFY_RIM) {
- if (!rim_faces_attribute_name.empty()) {
- OutputAttribute_Typed<bool> rim_faces_attribute =
- mesh_component.attribute_try_get_for_output_only<bool>(rim_faces_attribute_name,
- result_face_domain);
- Span<bool> rim_faces_span(rim_faces, rim_faces_attribute->size());
- rim_faces_attribute->set_all(rim_faces_span);
- rim_faces_attribute.save();
+
+ SolidifyData solidify_node_data = {
+ self_object,
+ 1,
+ offset,
+ 0.0f,
+ offset_clamp,
+ node_storage.nonmanifold_offset_mode,
+ node_storage.nonmanifold_boundary_mode,
+ flag,
+ 0.01f,
+ 0.0f,
+ thickness.begin(),
+ };
+
+ bool *shell_verts = nullptr;
+ bool *rim_verts = nullptr;
+ bool *shell_faces = nullptr;
+ bool *rim_faces = nullptr;
+
+ Mesh *output_mesh = solidify_nonmanifold(
+ &solidify_node_data, input_mesh, &shell_verts, &rim_verts, &shell_faces, &rim_faces);
+
+ if (output_mesh != input_mesh) {
+ component.replace(output_mesh, GeometryOwnershipType::Editable);
+
+ if (params.output_is_required("Fill Faces")) {
+ fill_id = StrongAnonymousAttributeID("fill_faces");
+ if (add_fill) {
+ OutputAttribute_Typed<bool> shell_faces_attribute =
+ component.attribute_try_get_for_output_only<bool>(fill_id.get(), ATTR_DOMAIN_FACE);
+ Span<bool> shell_faces_span(shell_faces, shell_faces_attribute->size());
+ shell_faces_attribute->set_all(shell_faces_span);
+ shell_faces_attribute.save();
+ }
+ }
+
+ if (params.output_is_required("Rim Faces")) {
+ rim_id = StrongAnonymousAttributeID("rim_faces");
+ if (add_rim) {
+ OutputAttribute_Typed<bool> rim_faces_attribute =
+ component.attribute_try_get_for_output_only<bool>(rim_id.get(), ATTR_DOMAIN_FACE);
+ Span<bool> rim_faces_span(rim_faces, rim_faces_attribute->size());
+ rim_faces_attribute->set_all(rim_faces_span);
+ rim_faces_attribute.save();
+ }
+ }
}
- }
- MEM_freeN(shell_verts);
- MEM_freeN(rim_verts);
- MEM_freeN(shell_faces);
- MEM_freeN(rim_faces);
+ MEM_freeN(shell_verts);
+ MEM_freeN(rim_verts);
+ MEM_freeN(shell_faces);
+ MEM_freeN(rim_faces);
+ });
+ }
+ if (fill_id) {
+ params.set_output("Fill Faces",
+ AnonymousAttributeFieldInput::Create<bool>(
+ std::move(fill_id), params.attribute_producer_name()));
+ }
+ if (rim_id) {
+ params.set_output("Rim Faces",
+ AnonymousAttributeFieldInput::Create<bool>(
+ std::move(rim_id), params.attribute_producer_name()));
}
- params.set_output("Geometry", geometry_set);
+
+ params.set_output("Mesh", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_solidify
void register_node_type_geo_solidify()
{
+ namespace file_ns = blender::nodes::node_geo_solidify;
+
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_SOLIDIFY, "Solidify", NODE_CLASS_GEOMETRY, 0);
- node_type_socket_templates(&ntype, geo_node_solidify_in, geo_node_solidify_out);
+
+ geo_node_type_base(&ntype, GEO_NODE_SOLIDIFY, "Solidify", NODE_CLASS_GEOMETRY);
+ ntype.declare = file_ns::node_declare;
node_type_storage(
&ntype, "NodeGeometrySolidify", node_free_standard_storage, node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_solidify_init);
+ node_type_init(&ntype, file_ns::geo_node_solidify_init);
node_type_size(&ntype, 172, 100, 600);
- node_type_update(&ntype, blender::nodes::geo_node_solidify_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_solidify_exec;
- ntype.draw_buttons = blender::nodes::geo_node_solidify_layout;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}