diff options
author | Hans Goudey <h.goudey@me.com> | 2021-05-27 17:08:40 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2021-05-27 17:08:40 +0300 |
commit | ac833108dbbaa5f2a6d62effe962eb289cc92291 (patch) | |
tree | 21bc3ac8a666de9ee0e8f355b6337dda649867d2 /source/blender/draw | |
parent | 5621a8ed7fbcd9067c576d4066e83d9640a80c49 (diff) |
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
Diffstat (limited to 'source/blender/draw')
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_curve.cc | 161 |
2 files changed, 120 insertions, 42 deletions
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)) { |