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:
authorHans Goudey <h.goudey@me.com>2022-02-28 18:46:34 +0300
committerHans Goudey <h.goudey@me.com>2022-02-28 18:46:34 +0300
commit9ec12c26f16ea3da1e6de95d5d5daf1057464830 (patch)
tree708e542d5d4de0efdda7b9a54def6b25b6b64039 /source/blender/blenkernel/intern/curve_eval.cc
parent81bb86c7506c0ae5f07780a63f954a8416a0d4e6 (diff)
Geometry Nodes: Begin conversion to new curves
This commit changes `CurveComponent` to store the new curve type by adding conversions to and from `CurveEval` in most nodes. This will temporarily make performance of curves in geometry nodes much worse, but as functionality is implemented for the new type and it is used in more places, performance will become better than before. We still use `CurveEval` for drawing curves, because the new `Curves` data-block has no evaluated points yet. So the `Curve` ID is still generated for rendering in the same way as before. It's also still needed for drawing curve object edit mode overlays. The old curve component isn't removed yet, because it is still used to implement the conversions to and from `CurveEval`. A few more attributes are added to make this possible: - `nurbs_weight`: The weight for each control point on NURBS curves. - `nurbs_order`: The order of the NURBS curve - `knots_mode`: Necessary for conversion, not defined yet. - `handle_type_{left/right}`: An 8 bit integer attribute. Differential Revision: https://developer.blender.org/D14145
Diffstat (limited to 'source/blender/blenkernel/intern/curve_eval.cc')
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc189
1 files changed, 189 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index 8529e7ad194..78dafe34b4f 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -13,6 +13,8 @@
#include "BKE_anonymous_attribute.hh"
#include "BKE_curve.h"
+#include "BKE_curves.hh"
+#include "BKE_geometry_set.hh"
#include "BKE_spline.hh"
using blender::Array;
@@ -23,8 +25,15 @@ using blender::Map;
using blender::MutableSpan;
using blender::Span;
using blender::StringRefNull;
+using blender::VArray;
+using blender::VArray_Span;
using blender::Vector;
using blender::bke::AttributeIDRef;
+using blender::bke::OutputAttribute;
+using blender::bke::OutputAttribute_Typed;
+using blender::bke::ReadAttributeLookup;
+using blender::fn::GVArray;
+using blender::fn::GVArray_GSpan;
blender::Span<SplinePtr> CurveEval::splines() const
{
@@ -336,6 +345,186 @@ std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
return curve_eval_from_dna_curve(dna_curve, *BKE_curve_nurbs_get_for_read(&dna_curve));
}
+static void copy_attributes_between_components(const GeometryComponent &src_component,
+ GeometryComponent &dst_component,
+ Span<std::string> skip)
+{
+ src_component.attribute_foreach(
+ [&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
+ if (id.is_named() && skip.contains(id.name())) {
+ return true;
+ }
+
+ GVArray src_attribute = src_component.attribute_try_get_for_read(
+ id, meta_data.domain, meta_data.data_type);
+ if (!src_attribute) {
+ return true;
+ }
+ GVArray_GSpan src_attribute_data{src_attribute};
+
+ OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ id, meta_data.domain, meta_data.data_type);
+ if (!dst_attribute) {
+ return true;
+ }
+ dst_attribute.varray().set_all(src_attribute_data.data());
+ dst_attribute.save();
+ return true;
+ });
+}
+
+std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
+{
+ CurveComponent src_component;
+ src_component.replace(&const_cast<Curves &>(curves), GeometryOwnershipType::ReadOnly);
+ const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(
+ curves.geometry);
+
+ VArray_Span<float> nurbs_weights{
+ src_component.attribute_get_for_read<float>("nurbs_weight", ATTR_DOMAIN_POINT, 0.0f)};
+ VArray_Span<int> nurbs_orders{
+ src_component.attribute_get_for_read<int>("nurbs_order", ATTR_DOMAIN_CURVE, 4)};
+ VArray_Span<int8_t> nurbs_knots_modes{
+ src_component.attribute_get_for_read<int8_t>("knots_mode", ATTR_DOMAIN_CURVE, 0)};
+
+ VArray_Span<int8_t> handle_types_right{
+ src_component.attribute_get_for_read<int8_t>("handle_type_right", ATTR_DOMAIN_POINT, 0)};
+ VArray_Span<int8_t> handle_types_left{
+ src_component.attribute_get_for_read<int8_t>("handle_type_left", ATTR_DOMAIN_POINT, 0)};
+
+ /* Create splines with the correct size and type. */
+ VArray<int8_t> curve_types = geometry.curve_types();
+ std::unique_ptr<CurveEval> curve_eval = std::make_unique<CurveEval>();
+ for (const int curve_index : curve_types.index_range()) {
+ const IndexRange point_range = geometry.range_for_curve(curve_index);
+
+ std::unique_ptr<Spline> spline;
+ switch (curve_types[curve_index]) {
+ case CURVE_TYPE_POLY: {
+ spline = std::make_unique<PolySpline>();
+ spline->resize(point_range.size());
+ break;
+ }
+ case CURVE_TYPE_BEZIER: {
+ std::unique_ptr<BezierSpline> bezier_spline = std::make_unique<BezierSpline>();
+ bezier_spline->resize(point_range.size());
+ bezier_spline->handle_types_left().copy_from(handle_types_left.slice(point_range));
+ bezier_spline->handle_types_right().copy_from(handle_types_right.slice(point_range));
+
+ spline = std::move(bezier_spline);
+ break;
+ }
+ case CURVE_TYPE_NURBS: {
+ std::unique_ptr<NURBSpline> nurb_spline = std::make_unique<NURBSpline>();
+ nurb_spline->resize(point_range.size());
+ nurb_spline->weights().copy_from(nurbs_weights.slice(point_range));
+ nurb_spline->set_order(nurbs_orders[curve_index]);
+ nurb_spline->knots_mode = static_cast<NURBSpline::KnotsMode>(
+ nurbs_knots_modes[curve_index]);
+
+ spline = std::move(nurb_spline);
+ break;
+ }
+ case CURVE_TYPE_CATMULL_ROM:
+ /* Not supported yet. */
+ BLI_assert_unreachable();
+ continue;
+ }
+ spline->positions().fill(float3(0));
+ spline->tilts().fill(0.0f);
+ spline->radii().fill(0.0f);
+ curve_eval->add_spline(std::move(spline));
+ }
+
+ CurveComponentLegacy dst_component;
+ dst_component.replace(curve_eval.get(), GeometryOwnershipType::Editable);
+
+ copy_attributes_between_components(src_component,
+ dst_component,
+ {"curve_type",
+ "nurbs_weight",
+ "nurbs_order",
+ "knots_mode",
+ "handle_type_right",
+ "handle_type_left"});
+
+ return curve_eval;
+}
+
+Curves *curve_eval_to_curves(const CurveEval &curve_eval)
+{
+ Curves *curves = blender::bke::curves_new_nomain(curve_eval.total_control_point_size(),
+ curve_eval.splines().size());
+ CurveComponent dst_component;
+ dst_component.replace(curves, GeometryOwnershipType::Editable);
+
+ blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(curves->geometry);
+ geometry.offsets().copy_from(curve_eval.control_point_offsets());
+ MutableSpan<int8_t> curve_types = geometry.curve_types();
+
+ OutputAttribute_Typed<float> nurbs_weight;
+ OutputAttribute_Typed<int> nurbs_order;
+ OutputAttribute_Typed<int8_t> nurbs_knots_mode;
+ if (curve_eval.has_spline_with_type(CURVE_TYPE_NURBS)) {
+ nurbs_weight = dst_component.attribute_try_get_for_output_only<float>("nurbs_weight",
+ ATTR_DOMAIN_POINT);
+ nurbs_order = dst_component.attribute_try_get_for_output_only<int>("nurbs_order",
+ ATTR_DOMAIN_CURVE);
+ nurbs_knots_mode = dst_component.attribute_try_get_for_output_only<int8_t>("knots_mode",
+ ATTR_DOMAIN_CURVE);
+ }
+ OutputAttribute_Typed<int8_t> handle_type_right;
+ OutputAttribute_Typed<int8_t> handle_type_left;
+ if (curve_eval.has_spline_with_type(CURVE_TYPE_BEZIER)) {
+ handle_type_right = dst_component.attribute_try_get_for_output_only<int8_t>(
+ "handle_type_right", ATTR_DOMAIN_POINT);
+ handle_type_left = dst_component.attribute_try_get_for_output_only<int8_t>("handle_type_left",
+ ATTR_DOMAIN_POINT);
+ }
+
+ for (const int curve_index : curve_eval.splines().index_range()) {
+ const Spline &spline = *curve_eval.splines()[curve_index];
+ curve_types[curve_index] = curve_eval.splines()[curve_index]->type();
+
+ const IndexRange point_range = geometry.range_for_curve(curve_index);
+
+ switch (spline.type()) {
+ case CURVE_TYPE_POLY:
+ break;
+ case CURVE_TYPE_BEZIER: {
+ const BezierSpline &src = static_cast<const BezierSpline &>(spline);
+ handle_type_right.as_span().slice(point_range).copy_from(src.handle_types_right());
+ handle_type_left.as_span().slice(point_range).copy_from(src.handle_types_left());
+ break;
+ }
+ case CURVE_TYPE_NURBS: {
+ const NURBSpline &src = static_cast<const NURBSpline &>(spline);
+ nurbs_knots_mode.as_span()[curve_index] = static_cast<int8_t>(src.knots_mode);
+ nurbs_order.as_span()[curve_index] = src.order();
+ nurbs_weight.as_span().slice(point_range).copy_from(src.weights());
+ break;
+ }
+ case CURVE_TYPE_CATMULL_ROM: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+ }
+
+ nurbs_weight.save();
+ nurbs_order.save();
+ nurbs_knots_mode.save();
+ handle_type_right.save();
+ handle_type_left.save();
+
+ CurveComponentLegacy src_component;
+ src_component.replace(&const_cast<CurveEval &>(curve_eval), GeometryOwnershipType::ReadOnly);
+
+ copy_attributes_between_components(src_component, dst_component, {});
+
+ return curves;
+}
+
void CurveEval::assert_valid_point_attributes() const
{
#ifdef DEBUG