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:
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh12
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curve.cc33
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc23
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.cc161
-rw-r--r--source/blender/makesdna/DNA_curve_types.h7
6 files changed, 195 insertions, 42 deletions
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_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]);
+ }
}
}
+ BLI_assert(v_idx == vert_len);
}
- BLI_assert(v_idx == vert_len);
}
static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
{
- BLI_assert(rdata->ob_curve_cache != nullptr);
-
const int vert_len = curve_render_data_wire_verts_len_get(rdata);
const int edge_len = curve_render_data_wire_edges_len_get(rdata);
const int curve_len = curve_render_data_wire_curve_len_get(rdata);
@@ -603,34 +655,56 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
- int v_idx = 0;
- LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
- if (bl->nr <= 0) {
- continue;
- }
- const bool is_cyclic = bl->poly != -1;
- if (is_cyclic) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1));
- }
- for (int i = 0; i < bl->nr; i++) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
+ 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()) {
+ const int eval_size = splines[i_spline]->evaluated_points_size();
+ if (splines[i_spline]->is_cyclic()) {
+ GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + eval_size - 1);
+ }
+ for (const int i_point : IndexRange(eval_size)) {
+ GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + i_point);
+ }
+ GPU_indexbuf_add_primitive_restart(&elb);
}
- GPU_indexbuf_add_primitive_restart(&elb);
- v_idx += bl->nr;
}
- LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
- if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
- const bool is_cyclic = dl->type == DL_POLY;
+ 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 bool is_cyclic = bl->poly != -1;
if (is_cyclic) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1));
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1));
}
- for (int i = 0; i < dl->nr; i++) {
+ for (int i = 0; i < bl->nr; i++) {
GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
}
GPU_indexbuf_add_primitive_restart(&elb);
- v_idx += dl->nr;
+ v_idx += bl->nr;
+ }
+ LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
+ if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
+ const bool is_cyclic = dl->type == DL_POLY;
+ if (is_cyclic) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1));
+ }
+ for (int i = 0; i < dl->nr; i++) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
+ }
+ GPU_indexbuf_add_primitive_restart(&elb);
+ v_idx += dl->nr;
+ }
}
}
+
GPU_indexbuf_build_in_place(&elb, ibo_curve_lines);
}
@@ -1070,8 +1144,11 @@ void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scen
CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime.curve_cache, mr_flag);
- /* DispLists */
- ListBase *lb = &rdata->ob_curve_cache->disp;
+ /* The object's curve cache can be empty (in one case because we use #CurveEval's cache instead),
+ * If so, point to an empty DispList list to avoid the need to check for null in the following
+ * functions. */
+ ListBase empty_lb = {nullptr, nullptr};
+ ListBase *lb = rdata->ob_curve_cache == nullptr ? &empty_lb : &rdata->ob_curve_cache->disp;
/* Generate VBOs */
if (DRW_vbo_requested(cache->ordered.pos_nor)) {
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 716c480bab8..f6242679808 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -43,6 +43,7 @@ struct Key;
struct Material;
struct Object;
struct VFont;
+struct CurveEval;
/* These two Lines with # tell makesdna this struct can be excluded. */
#
@@ -300,6 +301,12 @@ typedef struct Curve {
char _pad2[6];
float fsize_realtime;
+ /**
+ * A pointer to curve data from geometry nodes, currently only set for evaluated
+ * objects by the dependency graph iterator, and owned by #geometry_set_eval.
+ */
+ struct CurveEval *curve_eval;
+
void *batch_cache;
} Curve;