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/geometry')
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc155
1 files changed, 103 insertions, 52 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index fc8558dfd2f..c0d817385e2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -16,7 +16,7 @@
#include "BLI_array.hh"
#include "BLI_float4x4.hh"
-#include "BLI_timeit.hh"
+#include "BLI_task.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -47,8 +47,8 @@ static void vert_extrude_to_mesh_data(const Spline &spline,
const float3 profile_vert,
MutableSpan<MVert> r_verts,
MutableSpan<MEdge> r_edges,
- int &vert_offset,
- int &edge_offset)
+ int vert_offset,
+ int edge_offset)
{
Span<float3> positions = spline.evaluated_positions();
@@ -85,10 +85,10 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
MutableSpan<MEdge> r_edges,
MutableSpan<MLoop> r_loops,
MutableSpan<MPoly> r_polys,
- int &vert_offset,
- int &edge_offset,
- int &loop_offset,
- int &poly_offset)
+ int vert_offset,
+ int edge_offset,
+ int loop_offset,
+ int poly_offset)
{
const int spline_vert_len = spline.evaluated_points_size();
const int spline_edge_len = spline.evaluated_edges_size();
@@ -207,63 +207,114 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
}
}
-static Mesh *curve_to_mesh_calculate(const CurveEval &curve, const CurveEval &profile_curve)
+static inline int spline_extrude_vert_size(const Spline &curve, const Spline &profile)
{
- int profile_vert_total = 0;
- int profile_edge_total = 0;
- for (const SplinePtr &profile_spline : profile_curve.splines()) {
- profile_vert_total += profile_spline->evaluated_points_size();
- profile_edge_total += profile_spline->evaluated_edges_size();
- }
+ return curve.evaluated_points_size() * profile.evaluated_points_size();
+}
- int vert_total = 0;
- int edge_total = 0;
- int poly_total = 0;
- for (const SplinePtr &spline : curve.splines()) {
- const int spline_vert_len = spline->evaluated_points_size();
- const int spline_edge_len = spline->evaluated_edges_size();
- vert_total += spline_vert_len * profile_vert_total;
- poly_total += spline_edge_len * profile_edge_total;
-
- /* Add the ring edges, with one ring for every curve vertex, and the edge loops
- * that run along the length of the curve, starting on the first profile. */
- edge_total += profile_edge_total * spline_vert_len + profile_vert_total * spline_edge_len;
- }
- const int corner_total = poly_total * 4;
+static inline int spline_extrude_edge_size(const Spline &curve, const Spline &profile)
+{
+ /* Add the ring edges, with one ring for every curve vertex, and the edge loops
+ * that run along the length of the curve, starting on the first profile. */
+ return curve.evaluated_points_size() * profile.evaluated_edges_size() +
+ curve.evaluated_edges_size() * profile.evaluated_points_size();
+}
- if (vert_total == 0) {
- return nullptr;
- }
+static inline int spline_extrude_loop_size(const Spline &curve, const Spline &profile)
+{
+ return curve.evaluated_edges_size() * profile.evaluated_edges_size() * 4;
+}
- Mesh *mesh = BKE_mesh_new_nomain(vert_total, edge_total, 0, corner_total, poly_total);
- BKE_id_material_eval_ensure_default_slot(&mesh->id);
- MutableSpan<MVert> verts{mesh->mvert, mesh->totvert};
- MutableSpan<MEdge> edges{mesh->medge, mesh->totedge};
- MutableSpan<MLoop> loops{mesh->mloop, mesh->totloop};
- MutableSpan<MPoly> polys{mesh->mpoly, mesh->totpoly};
- mesh->flag |= ME_AUTOSMOOTH;
- mesh->smoothresh = DEG2RADF(180.0f);
+static inline int spline_extrude_poly_size(const Spline &curve, const Spline &profile)
+{
+ return curve.evaluated_edges_size() * profile.evaluated_edges_size();
+}
+struct ResultOffsets {
+ Array<int> vert;
+ Array<int> edge;
+ Array<int> loop;
+ Array<int> poly;
+};
+static ResultOffsets calculate_result_offsets(Span<SplinePtr> profiles, Span<SplinePtr> curves)
+{
+ const int total = profiles.size() * curves.size();
+ Array<int> vert(total + 1);
+ Array<int> edge(total + 1);
+ Array<int> loop(total + 1);
+ Array<int> poly(total + 1);
+
+ int mesh_index = 0;
int vert_offset = 0;
int edge_offset = 0;
int loop_offset = 0;
int poly_offset = 0;
- for (const SplinePtr &spline : curve.splines()) {
- for (const SplinePtr &profile_spline : profile_curve.splines()) {
- spline_extrude_to_mesh_data(*spline,
- *profile_spline,
- verts,
- edges,
- loops,
- polys,
- vert_offset,
- edge_offset,
- loop_offset,
- poly_offset);
+ for (const int i_spline : curves.index_range()) {
+ for (const int i_profile : profiles.index_range()) {
+ vert[mesh_index] = vert_offset;
+ edge[mesh_index] = edge_offset;
+ loop[mesh_index] = loop_offset;
+ poly[mesh_index] = poly_offset;
+ vert_offset += spline_extrude_vert_size(*curves[i_spline], *profiles[i_profile]);
+ edge_offset += spline_extrude_edge_size(*curves[i_spline], *profiles[i_profile]);
+ loop_offset += spline_extrude_loop_size(*curves[i_spline], *profiles[i_profile]);
+ poly_offset += spline_extrude_poly_size(*curves[i_spline], *profiles[i_profile]);
+ mesh_index++;
}
}
+ vert.last() = vert_offset;
+ edge.last() = edge_offset;
+ loop.last() = loop_offset;
+ poly.last() = poly_offset;
+
+ return {std::move(vert), std::move(edge), std::move(loop), std::move(poly)};
+}
+
+/**
+ * \note Normal calculation is by far the slowest part of calculations relating to the result mesh.
+ * Although it would be a sensible decision to use the better topology information available while
+ * generating the mesh to also generate the normals, that work may wasted if the output mesh is
+ * changed anyway in a way that affects the normals. So currently this code uses the safer /
+ * simpler solution of not calculating normals.
+ */
+static Mesh *curve_to_mesh_calculate(const CurveEval &curve, const CurveEval &profile)
+{
+ Span<SplinePtr> profiles = profile.splines();
+ Span<SplinePtr> curves = curve.splines();
+
+ const ResultOffsets offsets = calculate_result_offsets(profiles, curves);
+ if (offsets.vert.last() == 0) {
+ return nullptr;
+ }
- BKE_mesh_calc_normals(mesh);
+ Mesh *mesh = BKE_mesh_new_nomain(
+ offsets.vert.last(), offsets.edge.last(), 0, offsets.loop.last(), offsets.poly.last());
+ BKE_id_material_eval_ensure_default_slot(&mesh->id);
+ mesh->flag |= ME_AUTOSMOOTH;
+ mesh->smoothresh = DEG2RADF(180.0f);
+ mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+ mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL;
+
+ threading::parallel_for(curves.index_range(), 128, [&](IndexRange curves_range) {
+ for (const int i_spline : curves_range) {
+ const int spline_start_index = i_spline * profiles.size();
+ threading::parallel_for(profiles.index_range(), 128, [&](IndexRange profiles_range) {
+ for (const int i_profile : profiles_range) {
+ const int i_mesh = spline_start_index + i_profile;
+ spline_extrude_to_mesh_data(*curves[i_spline],
+ *profiles[i_profile],
+ {mesh->mvert, mesh->totvert},
+ {mesh->medge, mesh->totedge},
+ {mesh->mloop, mesh->totloop},
+ {mesh->mpoly, mesh->totpoly},
+ offsets.vert[i_mesh],
+ offsets.edge[i_mesh],
+ offsets.loop[i_mesh],
+ offsets.poly[i_mesh]);
+ }
+ });
+ }
+ });
return mesh;
}