[Bf-blender-cvs] [ac833108dbb] master: Geometry Nodes: Draw curve data in the viewport

Hans Goudey noreply at git.blender.org
Thu May 27 16:09:44 CEST 2021


Commit: ac833108dbbaa5f2a6d62effe962eb289cc92291
Author: Hans Goudey
Date:   Thu May 27 10:08:40 2021 -0400
Branches: master
https://developer.blender.org/rBac833108dbbaa5f2a6d62effe962eb289cc92291

Geometry Nodes: Draw curve data in the viewport

This patch adds relatively small changes to the curve draw
cache implementation in order to draw the curve data in the
viewport. The dependency graph iterator is also modified
so that it iterates over the curve geometry component, which
is presented to users as `Curve` data with a pointer to the
`CurveEval`

The idea with the spline data type in geometry nodes is that
curve data itself is only the control points, and any evaluated
data with faces is a mesh. That is mostly expected elsewhere in
Blender anyway. This means it's only necessary to implement
wire edge drawing of `CurveEval` data.

Adding a `CurveEval` pointer to `Curve` is in line with changes
I'd like to make in the future like using `CurveEval` in more places
such as edit mode.

An alternate solution involves converting the curve wire data
to a mesh, however, that requires copying all of the data, and
since avoiding it is rather simple and is in-line with future plans
anyway, I think doing it this way is better.

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

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/geometry_component_curve.cc
M	source/blender/depsgraph/intern/depsgraph_query_iter.cc
M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/intern/draw_cache_impl_curve.cc
M	source/blender/makesdna/DNA_curve_types.h

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 0ed6eea7954..9b50a9042eb 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -39,6 +39,7 @@ struct Mesh;
 struct Object;
 struct PointCloud;
 struct Volume;
+struct Curve;
 class CurveEval;
 
 enum class GeometryOwnershipType {
@@ -406,6 +407,15 @@ class CurveComponent : public GeometryComponent {
   CurveEval *curve_ = nullptr;
   GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned;
 
+  /**
+   * Curve data necessary to hold the draw cache for rendering, consistent over multiple redraws.
+   * This is necessary because Blender assumes that objects evaluate to an object data type, and
+   * we use #CurveEval rather than #Curve here. It also allows us to mostly reuse the same
+   * batch cache implementation.
+   */
+  mutable Curve *curve_for_render_ = nullptr;
+  mutable std::mutex curve_for_render_mutex_;
+
  public:
   CurveComponent();
   ~CurveComponent();
@@ -430,6 +440,8 @@ class CurveComponent : public GeometryComponent {
   bool owns_direct_data() const override;
   void ensure_owns_direct_data() override;
 
+  const Curve *get_curve_for_render() const;
+
   static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_CURVE;
 
  private:
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index be3fdf26cb3..de8dc355557 100644
--- a/source/blender/blenkernel/intern/geometry_component_curve.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curve.cc
@@ -14,9 +14,14 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include "DNA_ID_enums.h"
+#include "DNA_curve_types.h"
+
 #include "BKE_attribute_access.hh"
 #include "BKE_attribute_math.hh"
+#include "BKE_curve.h"
 #include "BKE_geometry_set.hh"
+#include "BKE_lib_id.h"
 #include "BKE_spline.hh"
 
 #include "attribute_access_intern.hh"
@@ -58,6 +63,11 @@ void CurveComponent::clear()
     if (ownership_ == GeometryOwnershipType::Owned) {
       delete curve_;
     }
+    if (curve_for_render_ != nullptr) {
+      BKE_id_free(nullptr, curve_for_render_);
+      curve_for_render_ = nullptr;
+    }
+
     curve_ = nullptr;
   }
 }
@@ -118,6 +128,29 @@ void CurveComponent::ensure_owns_direct_data()
   }
 }
 
+/**
+ * Create empty curve data used for rendering the spline's wire edges.
+ * \note See comment on #curve_for_render_ for further explanation.
+ */
+const Curve *CurveComponent::get_curve_for_render() const
+{
+  if (curve_ == nullptr) {
+    return nullptr;
+  }
+  if (curve_for_render_ != nullptr) {
+    return curve_for_render_;
+  }
+  std::lock_guard lock{curve_for_render_mutex_};
+  if (curve_for_render_ != nullptr) {
+    return curve_for_render_;
+  }
+
+  curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU, nullptr);
+  curve_for_render_->curve_eval = curve_;
+
+  return curve_for_render_;
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index ed002321729..df1cf8cc771 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -219,6 +219,29 @@ bool deg_iterator_components_step(BLI_Iterator *iter)
     }
   }
 
+  /* The curve component. */
+  if (data->geometry_component_id == 3) {
+    data->geometry_component_id++;
+
+    const CurveComponent *component = geometry_set->get_component_for_read<CurveComponent>();
+    if (component != nullptr) {
+      const Curve *curve = component->get_curve_for_render();
+
+      if (curve != nullptr) {
+        Object *temp_object = &data->temp_geometry_component_object;
+        *temp_object = *data->geometry_component_owner;
+        temp_object->type = OB_CURVE;
+        temp_object->data = (void *)curve;
+        /* Assign data_eval here too, because curve rendering code tries
+         * to use a mesh if it can find one in this pointer. */
+        temp_object->runtime.data_eval = (ID *)curve;
+        temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id;
+        iter->current = temp_object;
+        return true;
+      }
+    }
+  }
+
   data->geometry_component_owner = nullptr;
   return false;
 }
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 045adf4b380..afb0f613290 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
   ../depsgraph
   ../editors/include
   ../editors/space_view3d
+  ../functions
   ../gpu
   ../imbuf
   ../makesdna
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc
index ddafc7205bb..5cf99db5485 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curve.cc
@@ -25,8 +25,11 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_array.hh"
+#include "BLI_float3.hh"
 #include "BLI_listbase.h"
 #include "BLI_math_vector.h"
+#include "BLI_span.hh"
 #include "BLI_utildefines.h"
 
 #include "DNA_curve_types.h"
@@ -34,6 +37,8 @@
 #include "BKE_curve.h"
 #include "BKE_displist.h"
 #include "BKE_font.h"
+#include "BKE_geometry_set.hh"
+#include "BKE_spline.hh"
 
 #include "GPU_batch.h"
 #include "GPU_capabilities.h"
@@ -48,6 +53,11 @@
 
 #include "draw_cache_impl.h" /* own include */
 
+using blender::Array;
+using blender::float3;
+using blender::IndexRange;
+using blender::Span;
+
 /* See: edit_curve_point_vert.glsl for duplicate includes. */
 #define SELECT 1
 #define ACTIVE_NURB (1 << 2)
@@ -139,6 +149,21 @@ static void curve_render_wire_verts_edges_len_get(const CurveCache *ob_curve_cac
   }
 }
 
+static void curve_eval_render_wire_verts_edges_len_get(const CurveEval &curve_eval,
+                                                       int *r_curve_len,
+                                                       int *r_vert_len,
+                                                       int *r_edge_len)
+{
+  Span<SplinePtr> splines = curve_eval.splines();
+  *r_curve_len = splines.size();
+  *r_vert_len = 0;
+  *r_edge_len = 0;
+  for (const SplinePtr &spline : splines) {
+    *r_vert_len += spline->evaluated_points_size();
+    *r_edge_len += spline->evaluated_edges_size();
+  }
+}
+
 static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
 {
   int normal_len = 0;
@@ -192,6 +217,9 @@ struct CurveRenderData {
   /* borrow from 'Object' */
   CurveCache *ob_curve_cache;
 
+  /* Owned by the evaluated object's geometry set (#geometry_set_eval). */
+  const CurveEval *curve_eval;
+
   /* borrow from 'Curve' */
   ListBase *nurbs;
 
@@ -230,11 +258,21 @@ static CurveRenderData *curve_render_data_create(Curve *cu,
 
   rdata->ob_curve_cache = ob_curve_cache;
 
+  rdata->curve_eval = cu->curve_eval;
+
   if (types & CU_DATATYPE_WIRE) {
-    curve_render_wire_verts_edges_len_get(rdata->ob_curve_cache,
-                                          &rdata->wire.curve_len,
-                                          &rdata->wire.vert_len,
-                                          &rdata->wire.edge_len);
+    if (rdata->curve_eval != nullptr) {
+      curve_eval_render_wire_verts_edges_len_get(*rdata->curve_eval,
+                                                 &rdata->wire.curve_len,
+                                                 &rdata->wire.vert_len,
+                                                 &rdata->wire.edge_len);
+    }
+    else {
+      curve_render_wire_verts_edges_len_get(rdata->ob_curve_cache,
+                                            &rdata->wire.curve_len,
+                                            &rdata->wire.vert_len,
+                                            &rdata->wire.edge_len);
+    }
   }
 
   if (cu->editnurb) {
@@ -556,8 +594,6 @@ void DRW_curve_batch_cache_free(Curve *cu)
 /* GPUBatch cache usage. */
 static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos)
 {
-  BLI_assert(rdata->ob_curve_cache != nullptr);
-
   static GPUVertFormat format = {0};
   static struct {
     uint pos;
@@ -570,30 +606,46 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv
   GPU_vertbuf_init_with_format(vbo_curves_pos, &format);
   GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len);
 
-  int v_idx = 0;
-  LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
-    if (bl->nr <= 0) {
-      continue;
-    }
-    const int i_end = v_idx + bl->nr;
-    for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) {
-      GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec);
+  if (rdata->curve_eval != nullptr) {
+    const CurveEval &curve_eval = *rdata->curve_eval;
+    Span<SplinePtr> splines = curve_eval.splines();
+    Array<int> offsets = curve_eval.evaluated_point_offsets();
+    BLI_assert(offsets.last() == vert_len);
+
+    for (const int i_spline : splines.index_range()) {
+      Span<float3> positions = splines[i_spline]->evaluated_positions();
+      for (const int i_point : positions.index_range()) {
+        GPU_vertbuf_attr_set(
+            vbo_curves_pos, attr_id.pos, offsets[i_spline] + i_point, positions[i_point]);
+      }
     }
   }
-  LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
-    if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
-      for (int i = 0; i < dl->nr; v_idx++, i++) {
-        GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]);
+  else {
+    BLI_assert(rdata->ob_curve_cache != nullptr);
+
+    int v_idx = 0;
+    LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
+      if (bl->nr <= 0) {
+        continue;
+      }
+      const int i_end = v_idx + bl->nr;
+      for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) {
+        GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec);
+      }
+    }
+    LISTBASE_F

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list