[Bf-blender-cvs] [c324cf15392] master: Curves: Further implementation of new curves data structure

Hans Goudey noreply at git.blender.org
Wed Feb 16 18:32:55 CET 2022


Commit: c324cf153924ae2ec5b7c59eabff71652847aeae
Author: Hans Goudey
Date:   Wed Feb 16 11:32:37 2022 -0600
Branches: master
https://developer.blender.org/rBc324cf153924ae2ec5b7c59eabff71652847aeae

Curves: Further implementation of new curves data structure

The general idea here is to wrap the `CurvesGeometry` DNA struct
with a C++ class that can do most of the heavy lifting for the curve
geometry. Using a C++ class allows easier ways to group methods, easier
const correctness, and code that's more readable and faster to write.
This way, it works much more like a version of `CurveEval` that uses
more efficient attribute storage.

This commit adds the structure of some yet-to-be-implemented code,
the largest thing being mutexes and vectors meant to hold lazily
calculated evaluated positions, tangents, and normals. That part might
change slightly, but it's helpful to be able to see the direction this
commit is aiming in. In particular, the inherently single-threaded
accumulated lengths and Bezier evaluated point offsets might be cached.

Ref T95355

Differential Revision: https://developer.blender.org/D14054

===================================================================

M	source/blender/blenkernel/BKE_curves.h
A	source/blender/blenkernel/BKE_curves.hh
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/curves.cc
A	source/blender/blenkernel/intern/curves_geometry.cc
M	source/blender/blenkernel/intern/object.cc
M	source/blender/draw/intern/draw_cache_impl_curves.cc
M	source/blender/makesdna/DNA_curves_types.h
M	source/blender/makesrna/intern/rna_curves.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_curves.h b/source/blender/blenkernel/BKE_curves.h
index 2cce15fbfd6..88bb1c67fd1 100644
--- a/source/blender/blenkernel/BKE_curves.h
+++ b/source/blender/blenkernel/BKE_curves.h
@@ -2,9 +2,11 @@
 
 #pragma once
 
+#include "DNA_curves_types.h"
+
 /** \file
  * \ingroup bke
- * \brief Low-level operations for curves.
+ * \brief Low-level operations for curves that cannot be defined in the C++ header yet.
  */
 
 #ifdef __cplusplus
@@ -23,14 +25,10 @@ void *BKE_curves_add(struct Main *bmain, const char *name);
 
 struct BoundBox *BKE_curves_boundbox_get(struct Object *ob);
 
-void BKE_curves_update_customdata_pointers(struct Curves *curves);
 bool BKE_curves_customdata_required(struct Curves *curves, struct CustomDataLayer *layer);
 
 /* Depsgraph */
 
-struct Curves *BKE_curves_new_for_eval(const struct Curves *curves_src,
-                                       int totpoint,
-                                       int totcurve);
 struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src, bool reference);
 
 void BKE_curves_data_update(struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
new file mode 100644
index 00000000000..6bcbb0f6e66
--- /dev/null
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+#include "BKE_curves.h"
+
+/** \file
+ * \ingroup bke
+ * \brief Low-level operations for curves.
+ */
+
+#include <mutex>
+
+#include "BLI_float4x4.hh"
+#include "BLI_index_mask.hh"
+#include "BLI_math_vec_types.hh"
+#include "BLI_span.hh"
+#include "BLI_task.hh"
+#include "BLI_vector.hh"
+#include "BLI_virtual_array.hh"
+
+#include "BKE_attribute_access.hh"
+
+#include "FN_generic_virtual_array.hh"
+
+namespace blender::bke {
+
+/**
+ * Contains derived data, caches, and other information not saved in files, besides a few pointers
+ * to arrays that are kept in the non-runtime struct to avoid dereferencing this whenever they are
+ * accessed.
+ */
+class CurvesGeometryRuntime {
+ public:
+  /** Cache of evaluated positions. */
+  mutable Vector<float3> evaluated_position_cache;
+  mutable std::mutex position_cache_mutex;
+  mutable bool position_cache_dirty = true;
+
+  /** Direction of the spline at each evaluated point. */
+  mutable Vector<float3> evaluated_tangents_cache;
+  mutable std::mutex tangent_cache_mutex;
+  mutable bool tangent_cache_dirty = true;
+
+  /** Normal direction vectors for each evaluated point. */
+  mutable Vector<float3> evaluated_normals_cache;
+  mutable std::mutex normal_cache_mutex;
+  mutable bool normal_cache_dirty = true;
+};
+
+/**
+ * A C++ class that wraps the DNA struct for better encapsulation and ease of use. It inherits
+ * directly from the struct rather than storing a pointer to avoid more complcated ownership
+ * handling.
+ */
+class CurvesGeometry : public ::CurvesGeometry {
+ public:
+  CurvesGeometry();
+  /**
+   * Create curves with the given size. Only the position attribute is created, along with the
+   * offsets.
+   */
+  CurvesGeometry(int point_size, int curve_size);
+  CurvesGeometry(const CurvesGeometry &other);
+  CurvesGeometry &operator=(const CurvesGeometry &other);
+  ~CurvesGeometry();
+
+  static CurvesGeometry &wrap(::CurvesGeometry &dna_struct)
+  {
+    CurvesGeometry *geometry = reinterpret_cast<CurvesGeometry *>(&dna_struct);
+    return *geometry;
+  }
+  static const CurvesGeometry &wrap(const ::CurvesGeometry &dna_struct)
+  {
+    const CurvesGeometry *geometry = reinterpret_cast<const CurvesGeometry *>(&dna_struct);
+    return *geometry;
+  }
+
+  /* --------------------------------------------------------------------
+   * Accessors.
+   */
+
+  int points_size() const;
+  int curves_size() const;
+
+  /**
+   * The total number of points in the evaluated poly curve.
+   * This can depend on the resolution attribute if it exists.
+   */
+  int evaluated_points_size() const;
+
+  /**
+   * Access a range of indices of point data for a specific curve.
+   */
+  IndexRange range_for_curve(int index) const;
+
+  /** The type (#CurveType) of each curve, or potentially a single if all are the same type. */
+  VArray<int8_t> curve_types() const;
+  /** Mutable access to curve types. Call #tag_topology_changed after changing any type. */
+  MutableSpan<int8_t> curve_types();
+
+  MutableSpan<float3> positions();
+  Span<float3> positions() const;
+
+  /**
+   * Calculate the largest and smallest position values, only including control points
+   * (rather than evaluated points). The existing values of `min` and `max` are taken into account.
+   *
+   * \return Whether there are any points. If the curve is empty, the inputs will be unaffected.
+   */
+  bool bounds_min_max(float3 &min, float3 &max) const;
+
+  /**
+   * The index of the first point in every curve. The size of this span is one larger than the
+   * number of curves. Consider using #range_for_curve rather than using the offsets directly.
+   */
+  Span<int> offsets() const;
+  MutableSpan<int> offsets();
+
+  /* --------------------------------------------------------------------
+   * Operations.
+   */
+
+  /**
+   * Change the number of elements. New values for existing attributes should be properly
+   * initialized afterwards.
+   */
+  void resize(int point_size, int curve_size);
+
+  /** Call after deforming the position attribute. */
+  void tag_positions_changed();
+  /**
+   * Call after any operation that changes the topology
+   * (number of points, evaluated points, or the total count).
+   */
+  void tag_topology_changed();
+  /** Call after changing the "tilt" or "up" attributes. */
+  void tag_normals_changed();
+
+  void translate(const float3 &translation);
+  void transform(const float4x4 &matrix);
+
+  void update_customdata_pointers();
+
+  /* --------------------------------------------------------------------
+   * Attributes.
+   */
+
+  fn::GVArray adapt_domain(const fn::GVArray &varray,
+                           AttributeDomain from,
+                           AttributeDomain to) const;
+};
+
+Curves *curves_new_nomain(int point_size, int curves_size);
+
+}  // namespace blender::bke
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index bf720fa1341..78a145335b4 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -103,6 +103,7 @@ set(SRC
   intern/cryptomatte.cc
   intern/curve.cc
   intern/curves.cc
+  intern/curves_geometry.cc
   intern/curve_bevel.c
   intern/curve_convert.c
   intern/curve_decimate.c
@@ -341,6 +342,7 @@ set(SRC
   BKE_cryptomatte.hh
   BKE_curve.h
   BKE_curves.h
+  BKE_curves.hh
   BKE_curve_to_mesh.hh
   BKE_curveprofile.h
   BKE_customdata.h
diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc
index ccc20d5118a..e4a57ee1897 100644
--- a/source/blender/blenkernel/intern/curves.cc
+++ b/source/blender/blenkernel/intern/curves.cc
@@ -14,16 +14,18 @@
 #include "DNA_material_types.h"
 #include "DNA_object_types.h"
 
+#include "BLI_bounds.hh"
 #include "BLI_index_range.hh"
 #include "BLI_listbase.h"
 #include "BLI_math_base.h"
 #include "BLI_math_vector.hh"
 #include "BLI_rand.hh"
+#include "BLI_span.hh"
 #include "BLI_string.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_anim_data.h"
-#include "BKE_curves.h"
+#include "BKE_curves.hh"
 #include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_idtype.h"
@@ -44,11 +46,12 @@ using blender::float3;
 using blender::IndexRange;
 using blender::MutableSpan;
 using blender::RandomNumberGenerator;
+using blender::Span;
 
 static const char *ATTR_POSITION = "position";
-static const char *ATTR_RADIUS = "radius";
 
 static void curves_random(Curves *curves);
+static void update_custom_data_pointers(Curves &curves);
 
 static void curves_init_data(ID *id)
 {
@@ -57,50 +60,38 @@ static void curves_init_data(ID *id)
 
   MEMCPY_STRUCT_AFTER(curves, DNA_struct_default_get(Curves), id);
 
-  CustomData_reset(&curves->geometry.point_data);
-  CustomData_reset(&curves->geometry.curve_data);
-
-  CustomData_add_layer_named(&curves->geometry.point_data,
-                             CD_PROP_FLOAT3,
-                             CD_CALLOC,
-                             nullptr,
-                             curves->geometry.point_size,
-                             ATTR_POSITION);
-  CustomData_add_layer_named(&curves->geometry.point_data,
-                             CD_PROP_FLOAT,
-                             CD_CALLOC,
-                             nullptr,
-                             curves->geometry.point_size,
-                             ATTR_RADIUS);
-
-  BKE_curves_update_customdata_pointers(curves);
+  new (&curves->geometry) blender::bke::CurvesGeometry();
 
   curves_random(curves);
 }
 
 static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
 {
+  using namespace blender;
+
   Curves *curves_dst = (Curves *)id_dst;
   const Curves *curves_src = (const Curves *)id_src;
   curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
 
-  curves_dst->geometry.point_size = curves_src->geometry.point_size;
-  curves_dst->geometry.curve_size = curves_src->geometry.curve_size;
+  const bke::CurvesGeometry &src = bke::CurvesGeometry::wrap(curves_src->geometry);
+  bke::CurvesGeometry &dst = bke::CurvesGeometry::wrap(curves_dst->geometry);
+
+  /* We need special handling here because the generic ID management code has already done a
+   * shallow copy from the source to the destination, and because the copy-on-write functionality
+   * isn't supported more generically yet. */
+
+  dst.point_size = src.point_size;
+  dst.curve_size = src.curve_size;
 
   const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
-  CustomData_copy(&curves_src->geometry.point_data,
-                  &curves_dst->geometry.point_data,
-                  CD_MASK_ALL,
-                  alloc_type,
-                  curves_dst->geometry.point_size);
-  CustomData_copy(&curves_src->geometry.curve_da

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list