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:
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/CMakeLists.txt3
-rw-r--r--source/blender/nodes/NOD_geometry.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc273
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc69
5 files changed, 93 insertions, 254 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index f748c89c005..850c5fbffff 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC
../bmesh
../depsgraph
../functions
+ ../geometry
../gpu
../imbuf
../makesdna
@@ -248,6 +249,7 @@ set(SRC
geometry/nodes/node_geo_mesh_primitive_line.cc
geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
geometry/nodes/node_geo_mesh_subdivide.cc
+ geometry/nodes/node_geo_mesh_to_curve.cc
geometry/nodes/node_geo_mesh_to_points.cc
geometry/nodes/node_geo_object_info.cc
geometry/nodes/node_geo_points_to_vertices.cc
@@ -446,6 +448,7 @@ set(SRC
set(LIB
bf_bmesh
bf_functions
+ bf_geometry
bf_intern_sky
)
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index d34acd6e9aa..3b78912fbaa 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -34,6 +34,7 @@ void register_node_type_geo_legacy_attribute_proximity(void);
void register_node_type_geo_legacy_attribute_randomize(void);
void register_node_type_geo_legacy_delete_geometry(void);
void register_node_type_geo_legacy_material_assign(void);
+void register_node_type_geo_legacy_mesh_to_curve(void);
void register_node_type_geo_legacy_points_to_volume(void);
void register_node_type_geo_legacy_select_by_material(void);
void register_node_type_geo_legacy_curve_spline_type(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index b5640207d04..f3435079563 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -376,6 +376,7 @@ DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, 0, "MESH_PRIMITIVE_ICO
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Mesh Line", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, 0, "MESH_PRIMITIVE_UV_SPHERE", MeshUVSphere, "UV Sphere", "")
DefNode(GeometryNode, GEO_NODE_MESH_SUBDIVIDE, 0, "MESH_SUBDIVIDE", MeshSubdivide, "Subdivide Mesh", "")
+DefNode(GeometryNode, GEO_NODE_MESH_TO_CURVE, 0, "MESH_TO_CURVE", MeshToCurve, "Mesh to Curve", "")
DefNode(GeometryNode, GEO_NODE_MESH_TO_POINTS, def_geo_mesh_to_points, "MESH_TO_POINTS", MeshToPoints, "Mesh to Points", "")
DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO", ObjectInfo, "Object Info", "")
DefNode(GeometryNode, GEO_NODE_POINTS_TO_VERTICES, 0, "POINTS_TO_VERTICES", PointsToVertices, "Points to Vertices", "")
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
index 11349dc7d42..7a27e856cef 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
@@ -14,248 +14,31 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "BLI_array.hh"
-#include "BLI_task.hh"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-
-#include "BKE_attribute_math.hh"
-#include "BKE_spline.hh"
+#include "GEO_mesh_to_curve.hh"
#include "node_geometry_util.hh"
-using blender::Array;
-
namespace blender::nodes {
-static void geo_node_mesh_to_curve_declare(NodeDeclarationBuilder &b)
+static void geo_node_legacy_mesh_to_curve_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Mesh");
b.add_input<decl::String>("Selection");
b.add_output<decl::Geometry>("Curve");
}
-template<typename T>
-static void copy_attribute_to_points(const VArray<T> &source_data,
- Span<int> map,
- MutableSpan<T> dest_data)
-{
- for (const int point_index : map.index_range()) {
- const int vert_index = map[point_index];
- dest_data[point_index] = source_data[vert_index];
- }
-}
-
-static void copy_attributes_to_points(CurveEval &curve,
- const MeshComponent &mesh_component,
- Span<Vector<int>> point_to_vert_maps)
-{
- MutableSpan<SplinePtr> splines = curve.splines();
- Set<AttributeIDRef> source_attribute_ids = mesh_component.attribute_ids();
-
- /* Copy builtin control point attributes. */
- if (source_attribute_ids.contains("tilt")) {
- const GVArray_Typed<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
- "tilt", ATTR_DOMAIN_POINT, 0.0f);
- threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
- for (const int i : range) {
- copy_attribute_to_points<float>(
- *tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
- }
- });
- source_attribute_ids.remove_contained("tilt");
- }
- if (source_attribute_ids.contains("radius")) {
- const GVArray_Typed<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
- "radius", ATTR_DOMAIN_POINT, 1.0f);
- threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
- for (const int i : range) {
- copy_attribute_to_points<float>(
- *radius_attribute, point_to_vert_maps[i], splines[i]->radii());
- }
- });
- source_attribute_ids.remove_contained("radius");
- }
-
- /* Don't copy other builtin control point attributes. */
- source_attribute_ids.remove("position");
-
- /* Copy dynamic control point attributes. */
- for (const AttributeIDRef &attribute_id : source_attribute_ids) {
- const GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read(attribute_id,
- ATTR_DOMAIN_POINT);
- /* Some attributes might not exist if they were builtin attribute on domains that don't
- * have any elements, i.e. a face attribute on the output of the line primitive node. */
- if (!mesh_attribute) {
- continue;
- }
-
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute->type());
-
- threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- /* Create attribute on the spline points. */
- splines[i]->attributes.create(attribute_id, data_type);
- std::optional<GMutableSpan> spline_attribute = splines[i]->attributes.get_for_write(
- attribute_id);
- BLI_assert(spline_attribute);
-
- /* Copy attribute based on the map for this spline. */
- attribute_math::convert_to_static_type(mesh_attribute->type(), [&](auto dummy) {
- using T = decltype(dummy);
- copy_attribute_to_points<T>(
- mesh_attribute->typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
- });
- }
- });
- }
-
- curve.assert_valid_point_attributes();
-}
-
-struct CurveFromEdgesOutput {
- std::unique_ptr<CurveEval> curve;
- Vector<Vector<int>> point_to_vert_maps;
-};
-
-static CurveFromEdgesOutput mesh_to_curve(Span<MVert> verts, Span<std::pair<int, int>> edges)
+static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
{
- std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
- Vector<Vector<int>> point_to_vert_maps;
-
- /* Compute the number of edges connecting to each vertex. */
- Array<int> neighbor_count(verts.size(), 0);
- for (const std::pair<int, int> &edge : edges) {
- neighbor_count[edge.first]++;
- neighbor_count[edge.second]++;
- }
-
- /* Compute an offset into the array of neighbor edges based on the counts. */
- Array<int> neighbor_offsets(verts.size());
- int start = 0;
- for (const int i : verts.index_range()) {
- neighbor_offsets[i] = start;
- start += neighbor_count[i];
- }
-
- /* Use as an index into the "neighbor group" for each vertex. */
- Array<int> used_slots(verts.size(), 0);
- /* Calculate the indices of each vertex's neighboring edges. */
- Array<int> neighbors(edges.size() * 2);
- for (const int i : edges.index_range()) {
- const int v1 = edges[i].first;
- const int v2 = edges[i].second;
- neighbors[neighbor_offsets[v1] + used_slots[v1]] = v2;
- neighbors[neighbor_offsets[v2] + used_slots[v2]] = v1;
- used_slots[v1]++;
- used_slots[v2]++;
- }
-
- /* Now use the neighbor group offsets calculated above as a count used edges at each vertex. */
- Array<int> unused_edges = std::move(used_slots);
-
- for (const int start_vert : verts.index_range()) {
- /* The vertex will be part of a cyclic spline. */
- if (neighbor_count[start_vert] == 2) {
- continue;
- }
-
- /* The vertex has no connected edges, or they were already used. */
- if (unused_edges[start_vert] == 0) {
- continue;
- }
-
- for (const int i : IndexRange(neighbor_count[start_vert])) {
- int current_vert = start_vert;
- int next_vert = neighbors[neighbor_offsets[current_vert] + i];
-
- if (unused_edges[next_vert] == 0) {
- continue;
- }
-
- std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
- Vector<int> point_to_vert_map;
-
- spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
- point_to_vert_map.append(current_vert);
-
- /* Follow connected edges until we read a vertex with more than two connected edges. */
- while (true) {
- int last_vert = current_vert;
- current_vert = next_vert;
-
- spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
- point_to_vert_map.append(current_vert);
- unused_edges[current_vert]--;
- unused_edges[last_vert]--;
-
- if (neighbor_count[current_vert] != 2) {
- break;
- }
-
- const int offset = neighbor_offsets[current_vert];
- const int next_a = neighbors[offset];
- const int next_b = neighbors[offset + 1];
- next_vert = (last_vert == next_a) ? next_b : next_a;
- }
-
- spline->attributes.reallocate(spline->size());
- curve->add_spline(std::move(spline));
- point_to_vert_maps.append(std::move(point_to_vert_map));
- }
- }
-
- /* All remaining edges are part of cyclic splines (we skipped vertices with two edges before). */
- for (const int start_vert : verts.index_range()) {
- if (unused_edges[start_vert] != 2) {
- continue;
- }
-
- int current_vert = start_vert;
- int next_vert = neighbors[neighbor_offsets[current_vert]];
-
- std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
- Vector<int> point_to_vert_map;
- spline->set_cyclic(true);
-
- spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
- point_to_vert_map.append(current_vert);
-
- /* Follow connected edges until we loop back to the start vertex. */
- while (next_vert != start_vert) {
- const int last_vert = current_vert;
- current_vert = next_vert;
-
- spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
- point_to_vert_map.append(current_vert);
- unused_edges[current_vert]--;
- unused_edges[last_vert]--;
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
- const int offset = neighbor_offsets[current_vert];
- const int next_a = neighbors[offset];
- const int next_b = neighbors[offset + 1];
- next_vert = (last_vert == next_a) ? next_b : next_a;
- }
+ geometry_set = bke::geometry_set_realize_instances(geometry_set);
- spline->attributes.reallocate(spline->size());
- curve->add_spline(std::move(spline));
- point_to_vert_maps.append(std::move(point_to_vert_map));
+ if (!geometry_set.has_mesh()) {
+ params.set_output("Curve", GeometrySet());
+ return;
}
- curve->attributes.reallocate(curve->splines().size());
- return {std::move(curve), std::move(point_to_vert_maps)};
-}
-
-/**
- * Get a separate array of the indices for edges in a selection (a boolean attribute).
- * This helps to make the above algorithm simpler by removing the need to check for selection
- * in many places.
- */
-static Vector<std::pair<int, int>> get_selected_edges(GeoNodeExecParams params,
- const MeshComponent &component)
-{
- const Mesh &mesh = *component.get_for_read();
+ const MeshComponent &component = *geometry_set.get_component_for_read<MeshComponent>();
const std::string selection_name = params.extract_input<std::string>("Selection");
if (!selection_name.empty() && !component.attribute_exists(selection_name)) {
params.error_message_add(NodeWarningType::Error,
@@ -264,51 +47,33 @@ static Vector<std::pair<int, int>> get_selected_edges(GeoNodeExecParams params,
GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
selection_name, ATTR_DOMAIN_EDGE, true);
- Vector<std::pair<int, int>> selected_edges;
- for (const int i : IndexRange(mesh.totedge)) {
+ Vector<int64_t> selected_edge_indices;
+ for (const int64_t i : IndexRange(component.attribute_domain_size(ATTR_DOMAIN_EDGE))) {
if (selection[i]) {
- selected_edges.append({mesh.medge[i].v1, mesh.medge[i].v2});
+ selected_edge_indices.append(i);
}
}
- return selected_edges;
-}
-
-static void geo_node_mesh_to_curve_exec(GeoNodeExecParams params)
-{
- GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
-
- geometry_set = bke::geometry_set_realize_instances(geometry_set);
-
- if (!geometry_set.has_mesh()) {
- params.set_output("Curve", GeometrySet());
- return;
- }
-
- const MeshComponent &component = *geometry_set.get_component_for_read<MeshComponent>();
- const Mesh &mesh = *component.get_for_read();
- Span<MVert> verts = Span{mesh.mvert, mesh.totvert};
- Vector<std::pair<int, int>> selected_edges = get_selected_edges(params, component);
- if (selected_edges.size() == 0) {
+ if (selected_edge_indices.size() == 0) {
params.set_output("Curve", GeometrySet());
return;
}
- CurveFromEdgesOutput output = mesh_to_curve(verts, selected_edges);
- copy_attributes_to_points(*output.curve, component, output.point_to_vert_maps);
+ std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert(
+ component, IndexMask(selected_edge_indices));
- params.set_output("Curve", GeometrySet::create_with_curve(output.curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
} // namespace blender::nodes
-void register_node_type_geo_mesh_to_curve()
+void register_node_type_geo_legacy_mesh_to_curve()
{
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_MESH_TO_CURVE, "Mesh to Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_to_curve_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_to_curve_exec;
+ ntype.declare = blender::nodes::geo_node_legacy_mesh_to_curve_declare;
+ ntype.geometry_node_execute = blender::nodes::geo_node_legacy_mesh_to_curve_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
new file mode 100644
index 00000000000..7bca9ec141b
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
@@ -0,0 +1,69 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "GEO_mesh_to_curve.hh"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes {
+
+static void geo_node_legacy_mesh_to_curve_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Mesh");
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Curve");
+}
+
+static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (!geometry_set.has_mesh()) {
+ geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
+ return;
+ }
+
+ const MeshComponent &component = *geometry_set.get_component_for_read<MeshComponent>();
+ GeometryComponentFieldContext context{component, ATTR_DOMAIN_EDGE};
+ fn::FieldEvaluator evaluator{context, component.attribute_domain_size(ATTR_DOMAIN_EDGE)};
+ evaluator.add(params.get_input<Field<bool>>("Selection"));
+ evaluator.evaluate();
+ const IndexMask selection = evaluator.get_evaluated_as_mask(0);
+ if (selection.size() == 0) {
+ geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
+ return;
+ }
+
+ std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert(component, selection);
+ geometry_set.replace_curve(curve.release());
+ geometry_set.keep_only({GEO_COMPONENT_TYPE_CURVE, GEO_COMPONENT_TYPE_INSTANCES});
+ });
+
+ params.set_output("Curve", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_mesh_to_curve()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_MESH_TO_CURVE, "Mesh to Curve", NODE_CLASS_GEOMETRY, 0);
+ ntype.declare = blender::nodes::geo_node_legacy_mesh_to_curve_declare;
+ ntype.geometry_node_execute = blender::nodes::geo_node_legacy_mesh_to_curve_exec;
+ nodeRegisterType(&ntype);
+}