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_curve_render.h38
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/curve.c3
-rw-r--r--source/blender/blenkernel/intern/curve_render.c641
-rw-r--r--source/blender/blenkernel/intern/object_update.c6
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/intern/draw_cache.c44
-rw-r--r--source/blender/draw/intern/draw_cache.h5
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c108
-rw-r--r--source/blender/draw/modes/object_mode.c12
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl26
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl39
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c9
-rw-r--r--source/blender/makesdna/DNA_curve_types.h1
15 files changed, 904 insertions, 33 deletions
diff --git a/source/blender/blenkernel/BKE_curve_render.h b/source/blender/blenkernel/BKE_curve_render.h
new file mode 100644
index 00000000000..f05dc691d06
--- /dev/null
+++ b/source/blender/blenkernel/BKE_curve_render.h
@@ -0,0 +1,38 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_CURVE_RENDER_H__
+#define __BKE_CURVE_RENDER_H__
+
+/** \file BKE_curve_render.h
+ * \ingroup bke
+ */
+
+struct Batch;
+struct Curve;
+
+void BKE_curve_batch_cache_dirty(struct Curve *cu);
+void BKE_curve_batch_selection_dirty(struct Curve *cu);
+void BKE_curve_batch_cache_clear(struct Curve *cu);
+void BKE_curve_batch_cache_free(struct Curve *cu);
+struct Batch *BKE_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache);
+struct Batch *BKE_curve_batch_cache_get_overlay_edges(struct Curve *cu);
+struct Batch *BKE_curve_batch_cache_get_overlay_verts(struct Curve *cu);
+
+#endif /* __BKE_CURVE_RENDER_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 770e4ab3479..d8cba908f4a 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -93,6 +93,7 @@ set(SRC
intern/context.c
intern/crazyspace.c
intern/curve.c
+ intern/curve_render.c
intern/customdata.c
intern/customdata_file.c
intern/data_transfer.c
@@ -225,6 +226,7 @@ set(SRC
BKE_context.h
BKE_crazyspace.h
BKE_curve.h
+ BKE_curve_render.h
BKE_customdata.h
BKE_customdata_file.h
BKE_data_transfer.h
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 8a08c32f31b..10da97f5761 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -52,6 +52,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
+#include "BKE_curve_render.h"
#include "BKE_displist.h"
#include "BKE_font.h"
#include "BKE_global.h"
@@ -127,6 +128,8 @@ void BKE_curve_free(Curve *cu)
{
BKE_animdata_free((ID *)cu, false);
+ BKE_curve_batch_cache_free(cu);
+
BKE_nurbList_free(&cu->nurb);
BKE_curve_editfont_free(cu);
diff --git a/source/blender/blenkernel/intern/curve_render.c b/source/blender/blenkernel/intern/curve_render.c
new file mode 100644
index 00000000000..36ddbc48131
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve_render.c
@@ -0,0 +1,641 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/curve_render.c
+ * \ingroup bke
+ *
+ * \brief Curve API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_curve_types.h"
+
+#include "BKE_curve.h"
+#include "BKE_curve_render.h"
+
+#include "GPU_batch.h"
+
+#define SELECT 1
+
+/**
+ * TODO
+ * - Ensure `CurveCache`, `SEQUENCER_DAG_WORKAROUND`.
+ * - Check number of verts/edges to see if cache is valid.
+ * - Check if 'overlay_edges' can use single attribyte per edge, not 2 (for selection drawing).
+ */
+
+/* ---------------------------------------------------------------------- */
+/* Curve Interface, direct access to basic data. */
+
+static void curve_render_overlay_verts_edges_len_get(
+ ListBase *lb, bool hide_handles,
+ int *r_vert_len, int *r_edge_len)
+{
+ BLI_assert(r_vert_len || r_edge_len);
+ int vert_len = 0;
+ int edge_len = 0;
+ for (Nurb *nu = lb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ vert_len += hide_handles ? nu->pntsu : (nu->pntsu * 3);
+ /* 2x handles per point*/
+ edge_len += 2 * nu->pntsu;
+ }
+ else if (nu->bp) {
+ vert_len += nu->pntsu;
+ /* segments between points */
+ edge_len += nu->pntsu - 1;
+ }
+ }
+ if (r_vert_len) {
+ *r_vert_len = vert_len;
+ }
+ if (r_edge_len) {
+ *r_edge_len = edge_len;
+ }
+}
+
+static void curve_render_wire_verts_edges_len_get(
+ const CurveCache *ob_curve_cache,
+ int *r_vert_len, int *r_edge_len)
+{
+ BLI_assert(r_vert_len || r_edge_len);
+ int vert_len = 0;
+ int edge_len = 0;
+ for (const BevList *bl = ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr > 0) {
+ const bool is_cyclic = bl->poly != -1;
+
+ /* verts */
+ vert_len += bl->nr;
+
+ /* edges */
+ edge_len += bl->nr;
+ if (!is_cyclic) {
+ edge_len -= 1;
+ }
+ }
+ }
+ if (r_vert_len) {
+ *r_vert_len = vert_len;
+ }
+ if (r_edge_len) {
+ *r_edge_len = edge_len;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Curve Interface, indirect, partially cached access to complex data. */
+
+typedef struct CurveRenderData {
+ int types;
+
+ struct {
+ int vert_len;
+ int edge_len;
+ } overlay;
+
+ struct {
+ int vert_len;
+ int edge_len;
+ } wire;
+
+ bool hide_handles;
+
+ /* borrow from 'Object' */
+ CurveCache *ob_curve_cache;
+
+ /* borrow from 'Curve' */
+ struct EditNurb *edit_latt;
+ ListBase *nurbs;
+
+ /* edit, index in nurb list */
+ int actnu;
+ /* edit, index in active nurb (BPoint or BezTriple) */
+ int actvert;
+} CurveRenderData;
+
+enum {
+ /* Wire center-line */
+ CU_DATATYPE_WIRE = 1 << 0,
+ /* Edit-mode verts and optionally handles */
+ CU_DATATYPE_OVERLAY = 1 << 1,
+};
+
+/*
+ * ob_curve_cache can be NULL, only needed for CU_DATATYPE_WIRE
+ */
+static CurveRenderData *curve_render_data_create(Curve *cu, CurveCache *ob_curve_cache, const int types)
+{
+ CurveRenderData *lrdata = MEM_callocN(sizeof(*lrdata), __func__);
+ lrdata->types = types;
+ ListBase *nurbs;
+
+ lrdata->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
+ lrdata->actnu = cu->actnu;
+ lrdata->actvert = cu->actvert;
+
+ lrdata->ob_curve_cache = ob_curve_cache;
+
+ if (types & CU_DATATYPE_WIRE) {
+ curve_render_wire_verts_edges_len_get(
+ lrdata->ob_curve_cache,
+ &lrdata->wire.vert_len, &lrdata->wire.edge_len);
+ }
+
+ if (cu->editnurb) {
+ EditNurb *editnurb = cu->editnurb;
+ nurbs = &editnurb->nurbs;
+
+ lrdata->edit_latt = editnurb;
+
+ if (types & CU_DATATYPE_OVERLAY) {
+ curve_render_overlay_verts_edges_len_get(
+ nurbs, lrdata->hide_handles,
+ &lrdata->overlay.vert_len,
+ lrdata->hide_handles ? NULL : &lrdata->overlay.edge_len);
+
+ lrdata->actnu = cu->actnu;
+ lrdata->actvert = cu->actvert;
+ }
+ }
+ else {
+ nurbs = &cu->nurb;
+ }
+
+ lrdata->nurbs = nurbs;
+
+ return lrdata;
+}
+
+static void curve_render_data_free(CurveRenderData *lrdata)
+{
+#if 0
+ if (lrdata->loose_verts) {
+ MEM_freeN(lrdata->loose_verts);
+ }
+#endif
+ MEM_freeN(lrdata);
+}
+
+static int curve_render_data_overlay_verts_len_get(const CurveRenderData *lrdata)
+{
+ BLI_assert(lrdata->types & CU_DATATYPE_OVERLAY);
+ return lrdata->overlay.vert_len;
+}
+
+static int curve_render_data_overlay_edges_len_get(const CurveRenderData *lrdata)
+{
+ BLI_assert(lrdata->types & CU_DATATYPE_OVERLAY);
+ return lrdata->overlay.edge_len;
+}
+
+static int curve_render_data_wire_verts_len_get(const CurveRenderData *lrdata)
+{
+ BLI_assert(lrdata->types & CU_DATATYPE_WIRE);
+ return lrdata->wire.vert_len;
+}
+
+static int curve_render_data_wire_edges_len_get(const CurveRenderData *lrdata)
+{
+ BLI_assert(lrdata->types & CU_DATATYPE_WIRE);
+ return lrdata->wire.edge_len;
+}
+
+#if 0
+static const BPoint *curve_render_data_vert_bpoint(const CurveRenderData *lrdata, const int vert_idx)
+{
+ BLI_assert(lrdata->types & CU_DATATYPE_VERT);
+ return &lrdata->bp[vert_idx];
+}
+#endif
+
+enum {
+ VFLAG_VERTEX_SELECTED = 1 << 0,
+ VFLAG_VERTEX_ACTIVE = 1 << 1,
+};
+
+/* ---------------------------------------------------------------------- */
+/* Curve Batch Cache */
+
+typedef struct CurveBatchCache {
+ VertexBuffer *wire_verts;
+ VertexBuffer *wire_edges;
+ Batch *wire_batch;
+
+ ElementList *wire_elem;
+
+ /* control handles and vertices */
+ Batch *overlay_edges;
+ Batch *overlay_verts;
+
+ /* settings to determine if cache is invalid */
+ bool is_dirty;
+
+ bool hide_handles;
+
+ bool is_editmode;
+} CurveBatchCache;
+
+/* Batch cache management. */
+
+static bool curve_batch_cache_valid(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ if (cache->is_editmode != (cu->editnurb != NULL)) {
+ return false;
+ }
+
+ if (cache->is_dirty == false) {
+ return true;
+ }
+ else {
+ /* TODO: check number of vertices/edges? */
+ if (cache->is_editmode) {
+ return false;
+ }
+ else if ((cache->hide_handles != ((cu->drawflag & CU_HIDE_HANDLES) != 0))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void curve_batch_cache_init(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+
+ if (!cache) {
+ cache = cu->batch_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->hide_handles = (cu->flag & CU_HIDE_HANDLES) != 0;
+
+#if 0
+ ListBase *nurbs;
+ if (cu->editnurb) {
+ EditNurb *editnurb = cu->editnurb;
+ nurbs = &editnurb->nurbs;
+ }
+ else {
+ nurbs = &cu->nurb;
+ }
+#endif
+
+ cache->is_editmode = cu->editnurb != NULL;
+
+ cache->is_dirty = false;
+}
+
+static CurveBatchCache *curve_batch_cache_get(Curve *cu)
+{
+ if (!curve_batch_cache_valid(cu)) {
+ BKE_curve_batch_cache_clear(cu);
+ curve_batch_cache_init(cu);
+ }
+ return cu->batch_cache;
+}
+
+void BKE_curve_batch_cache_dirty(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+ if (cache) {
+ cache->is_dirty = true;
+ }
+}
+
+void BKE_curve_batch_selection_dirty(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+ if (cache) {
+ BATCH_DISCARD_ALL_SAFE(cache->overlay_verts);
+ BATCH_DISCARD_ALL_SAFE(cache->overlay_edges);
+ }
+}
+
+void BKE_curve_batch_cache_clear(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ BATCH_DISCARD_ALL_SAFE(cache->overlay_verts);
+ BATCH_DISCARD_ALL_SAFE(cache->overlay_edges);
+
+ if (cache->wire_batch) {
+ /* Also handles: 'cache->wire_verts', 'cache->wire_edges', 'cache->wire_elem' */
+ BATCH_DISCARD_ALL_SAFE(cache->wire_batch);
+ }
+ else {
+ VERTEXBUFFER_DISCARD_SAFE(cache->wire_verts);
+ VERTEXBUFFER_DISCARD_SAFE(cache->wire_edges);
+ ELEMENTLIST_DISCARD_SAFE(cache->wire_elem);
+ }
+}
+
+void BKE_curve_batch_cache_free(Curve *cu)
+{
+ BKE_curve_batch_cache_clear(cu);
+ MEM_SAFE_FREE(cu->batch_cache);
+}
+
+/* Batch cache usage. */
+static VertexBuffer *curve_batch_cache_get_wire_verts(CurveRenderData *lrdata, CurveBatchCache *cache)
+{
+ BLI_assert(lrdata->types & CU_DATATYPE_WIRE);
+ BLI_assert(lrdata->ob_curve_cache != NULL);
+
+ if (cache->wire_verts == NULL) {
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ }
+
+ const int vert_len = curve_render_data_wire_verts_len_get(lrdata);
+
+ VertexBuffer *vbo = cache->wire_verts = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, vert_len);
+ int vbo_len_used = 0;
+ for (const BevList *bl = lrdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr > 0) {
+ const int i_end = vbo_len_used + bl->nr;
+ for (const BevPoint *bevp = bl->bevpoints; vbo_len_used < i_end; vbo_len_used++, bevp++) {
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bevp->vec);
+ }
+ }
+ }
+ BLI_assert(vbo_len_used == vert_len);
+ }
+
+ return cache->wire_verts;
+}
+
+static ElementList *curve_batch_cache_get_wire_edges(CurveRenderData *lrdata, CurveBatchCache *cache)
+{
+ BLI_assert(lrdata->types & CU_DATATYPE_WIRE);
+ BLI_assert(lrdata->ob_curve_cache != NULL);
+
+ if (cache->wire_edges == NULL) {
+ const int vert_len = curve_render_data_wire_verts_len_get(lrdata);
+ const int edge_len = curve_render_data_wire_edges_len_get(lrdata);
+ int edge_len_real = 0;
+
+ ElementListBuilder elb;
+ ElementListBuilder_init(&elb, PRIM_LINES, edge_len, vert_len);
+
+ int i = 0;
+ for (const BevList *bl = lrdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr > 0) {
+ const bool is_cyclic = bl->poly != -1;
+ const int i_end = i + (bl->nr);
+ int i_prev;
+ if (is_cyclic) {
+ i_prev = i + (bl->nr - 1);
+ }
+ else {
+ i_prev = i;
+ i += 1;
+ }
+ for (; i < i_end; i_prev = i++) {
+ add_line_vertices(&elb, i_prev, i);
+ edge_len_real += 1;
+ }
+ }
+ }
+
+ if (lrdata->hide_handles) {
+ BLI_assert(edge_len_real <= edge_len);
+ }
+ else {
+ BLI_assert(edge_len_real == edge_len);
+ }
+
+ cache->wire_elem = ElementList_build(&elb);
+ }
+
+ return cache->wire_elem;
+}
+
+static void curve_batch_cache_create_overlay_batches(Curve *cu)
+{
+ /* Since CU_DATATYPE_OVERLAY is slow to generate, generate them all at once */
+ int options = CU_DATATYPE_OVERLAY;
+
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+ CurveRenderData *lrdata = curve_render_data_create(cu, NULL, options);
+
+ if (cache->overlay_verts == NULL) {
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, data_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ data_id = VertexFormat_add_attrib(&format, "data", COMP_U8, 1, KEEP_INT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ const int vbo_len_capacity = curve_render_data_overlay_verts_len_get(lrdata);
+ int vbo_len_used = 0;
+ VertexBuffer_allocate_data(vbo, vbo_len_capacity);
+ int i = 0;
+ for (Nurb *nu = lrdata->nurbs->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ int a = 0;
+ for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == false) {
+ const bool is_active = (i == lrdata->actvert);
+ char vflag;
+
+ if (lrdata->hide_handles) {
+ vflag = (bezt->f2 & SELECT) ?
+ (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bezt->vec[1]);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ else {
+ for (int j = 0; j < 3; j++) {
+ vflag = ((&bezt->f1)[j] & SELECT) ?
+ (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bezt->vec[j]);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ }
+ }
+ i += 1;
+ }
+ }
+ else if (nu->bp) {
+ int a = 0;
+ for (const BPoint *bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ if (bp->hide == false) {
+ const bool is_active = (i == lrdata->actvert);
+ char vflag;
+ vflag = (bp->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bp->vec);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ i += 1;
+ }
+ }
+ i += nu->pntsu;
+ }
+ if (vbo_len_capacity != vbo_len_used) {
+ VertexBuffer_resize_data(vbo, vbo_len_used);
+ }
+
+ cache->overlay_verts = Batch_create(PRIM_POINTS, vbo, NULL);
+ }
+
+
+ if ((cache->overlay_edges == NULL) && (lrdata->hide_handles == false)) {
+ /* Note: we could reference indices to vertices (above) */
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, data_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ data_id = VertexFormat_add_attrib(&format, "data", COMP_U8, 1, KEEP_INT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ const int edge_len = curve_render_data_overlay_edges_len_get(lrdata);
+ const int vbo_len_capacity = edge_len * 2;
+ int vbo_len_used = 0;
+ VertexBuffer_allocate_data(vbo, vbo_len_capacity);
+ int i = 0;
+ for (Nurb *nu = lrdata->nurbs->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ int a = 0;
+ for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == false) {
+ const bool is_active = (i == lrdata->actvert);
+ char vflag;
+
+ vflag = (bezt->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bezt->vec[0]);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+
+ /* same vertex twice, only check different selection */
+ for (int j = 0; j < 2; j++) {
+ vflag = ((j ? bezt->f3 : bezt->f1) & SELECT) ?
+ (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bezt->vec[1]);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+
+ vflag = (bezt->f3 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bezt->vec[2]);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ i += 1;
+ }
+ }
+ else if (nu->bp) {
+ int a = 1;
+ for (const BPoint *bp_prev = nu->bp, *bp_curr = &nu->bp[1]; a < nu->pntsu; a++, bp_prev = bp_curr++) {
+ if ((bp_prev->hide == false) && (bp_curr->hide == false)) {
+ char vflag;
+ vflag = ((bp_prev->f1 & SELECT) && (bp_curr->f1 & SELECT)) ? VFLAG_VERTEX_SELECTED : 0;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bp_prev->vec);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, bp_curr->vec);
+ VertexBuffer_set_attrib(vbo, data_id, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+
+ }
+ }
+ }
+ }
+ if (vbo_len_capacity != vbo_len_used) {
+ VertexBuffer_resize_data(vbo, vbo_len_used);
+ }
+
+ cache->overlay_edges = Batch_create(PRIM_LINES, vbo, NULL);
+ }
+
+ curve_render_data_free(lrdata);
+}
+
+Batch *BKE_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->wire_batch == NULL) {
+ /* create batch from Curve */
+ CurveRenderData *lrdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_WIRE);
+
+ cache->wire_batch = Batch_create(
+ PRIM_LINES,
+ curve_batch_cache_get_wire_verts(lrdata, cache),
+ curve_batch_cache_get_wire_edges(lrdata, cache));
+
+ curve_render_data_free(lrdata);
+ }
+
+ return cache->wire_batch;
+}
+
+Batch *BKE_curve_batch_cache_get_overlay_edges(Curve *cu)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->overlay_edges == NULL) {
+ curve_batch_cache_create_overlay_batches(cu);
+ }
+
+ return cache->overlay_edges;
+}
+
+Batch *BKE_curve_batch_cache_get_overlay_verts(Curve *cu)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->overlay_verts == NULL) {
+ curve_batch_cache_create_overlay_batches(cu);
+ }
+
+ return cache->overlay_verts;
+}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 374da48c648..495857bc21b 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -58,8 +58,9 @@
#include "BKE_material.h"
#include "BKE_image.h"
-#include "BKE_mesh_render.h"
+#include "BKE_curve_render.h"
#include "BKE_lattice_render.h"
+#include "BKE_mesh_render.h"
#include "DEG_depsgraph.h"
@@ -351,6 +352,9 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
case OB_LATTICE:
BKE_lattice_batch_cache_dirty(ob->data);
break;
+ case OB_CURVE:
+ BKE_curve_batch_cache_dirty(ob->data);
+ break;
}
ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index a1718b5d84d..e5d5e20c8f2 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3854,6 +3854,7 @@ static void direct_link_curve(FileData *fd, Curve *cu)
cu->editnurb = NULL;
cu->editfont = NULL;
+ cu->batch_cache = NULL;
for (nu = cu->nurb.first; nu; nu = nu->next) {
nu->bezt = newdataadr(fd, nu->bezt);
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 75dc9cadb60..87c42caf541 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -130,6 +130,8 @@ data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_curve_overlay_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_lattice_overlay_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_lattice_overlay_loosevert_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC)
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 8e6c64943bd..92acc8073df 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -31,8 +31,9 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BKE_mesh_render.h"
+#include "BKE_curve_render.h"
#include "BKE_lattice_render.h"
+#include "BKE_mesh_render.h"
#include "GPU_batch.h"
@@ -1592,6 +1593,47 @@ Batch *DRW_cache_mesh_verts_get(Object *ob)
/* -------------------------------------------------------------------- */
+/** \name Curve
+ * \{ */
+
+Batch *DRW_cache_curve_edge_wire_get(Object *ob)
+{
+ Batch *surface = NULL;
+
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ surface = BKE_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
+
+ return surface;
+}
+
+Batch *DRW_cache_curve_edge_overlay_get(Object *ob)
+{
+ Batch *surface = NULL;
+
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ surface = BKE_curve_batch_cache_get_overlay_edges(cu);
+
+ return surface;
+}
+
+Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
+{
+ Batch *surface = NULL;
+
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ surface = BKE_curve_batch_cache_get_overlay_verts(cu);
+
+ return surface;
+}
+
+/* -------------------------------------------------------------------- */
+
/** \name Lattice
* \{ */
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index b4f6590b5dd..daf807a27ea 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -88,6 +88,11 @@ struct Batch *DRW_cache_mesh_surface_get(struct Object *ob);
struct Batch *DRW_cache_mesh_surface_verts_get(struct Object *ob);
struct Batch *DRW_cache_mesh_verts_get(struct Object *ob);
+/* Curve */
+struct Batch *DRW_cache_curve_edge_wire_get(struct Object *ob);
+struct Batch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
+struct Batch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
+
/* Lattice */
struct Batch *DRW_cache_lattice_verts_get(struct Object *ob);
struct Batch *DRW_cache_lattice_wire_get(struct Object *ob);
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
index 084550a0445..8aabae588a3 100644
--- a/source/blender/draw/modes/edit_curve_mode.c
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -39,6 +39,14 @@
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
extern struct GlobalsUboStorage ts; /* draw_common.c */
+extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[];
+extern char datatoc_edit_curve_overlay_frag_glsl[];
+
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
+
/* *********** LISTS *********** */
/* All lists are per viewport specific datas.
* They are all free when viewport changes engines
@@ -50,7 +58,9 @@ typedef struct EDIT_CURVE_PassList {
/* Declare all passes here and init them in
* EDIT_CURVE_cache_init().
* Only contains (DRWPass *) */
- struct DRWPass *pass;
+ struct DRWPass *wire_pass;
+ struct DRWPass *overlay_edge_pass;
+ struct DRWPass *overlay_vert_pass;
} EDIT_CURVE_PassList;
typedef struct EDIT_CURVE_FramebufferList {
@@ -93,15 +103,22 @@ static struct {
* Add sources to source/blender/draw/modes/shaders
* init in EDIT_CURVE_engine_init();
* free in EDIT_CURVE_engine_free(); */
- struct GPUShader *custom_shader;
-} e_data = {NULL}; /* Engine data */
+ struct GPUShader *wire_sh;
-typedef struct g_data {
+ struct GPUShader *overlay_edge_sh; /* handles and nurbs control cage */
+ struct GPUShader *overlay_vert_sh;
+} e_data = {NULL}; /* Engine data */
+typedef struct g_data {
/* This keeps the references of the shading groups for
* easy access in EDIT_CURVE_cache_populate() */
- DRWShadingGroup *group;
+
+ /* resulting curve as 'wire' for curves (and optionally normals) */
+ DRWShadingGroup *wire_shgrp;
+
+ DRWShadingGroup *overlay_edge_shgrp;
+ DRWShadingGroup *overlay_vert_shgrp;
} g_data; /* Transient data */
/* *********** FUNCTIONS *********** */
@@ -132,8 +149,19 @@ static void EDIT_CURVE_engine_init(void *vedata)
* tex, 2);
*/
- if (!e_data.custom_shader) {
- e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (!e_data.wire_sh) {
+ e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!e_data.overlay_edge_sh) {
+ e_data.overlay_edge_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!e_data.overlay_vert_sh) {
+ e_data.overlay_vert_sh = DRW_shader_create_with_lib(
+ datatoc_edit_curve_overlay_loosevert_vert_glsl, NULL,
+ datatoc_edit_curve_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
}
}
@@ -150,22 +178,28 @@ static void EDIT_CURVE_cache_init(void *vedata)
}
{
- /* Create a pass */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
- psl->pass = DRW_pass_create("My Pass", state);
-
- /* Create a shadingGroup using a function in draw_common.c or custom one */
- /*
- * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
- * -- or --
- * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
- */
- stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
-
- /* Uniforms need a pointer to it's value so be sure it's accessible at
- * any given time (i.e. use static vars) */
- static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
- DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ /* Center-Line (wire) */
+ psl->wire_pass = DRW_pass_create(
+ "Curve Wire",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
+ stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass);
+
+
+ /* TODO: following handle theme colors,
+ * For now use overlay vert shader for handles (we want them colored):
+ * TH_NURB_ULINE, TH_NURB_SEL_ULINE, TH_HANDLE_* */
+ psl->overlay_edge_pass = DRW_pass_create(
+ "Curve Handle Overlay",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_WIRE);
+ /* TODO: following handle theme colors,
+ * For now use overlay vert shader for handles (we want them colored) */
+ stl->g_data->overlay_edge_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_edge_pass);
+
+ psl->overlay_vert_pass = DRW_pass_create(
+ "Curve Vert Overlay",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH);
+
+ stl->g_data->overlay_vert_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_vert_pass);
}
}
@@ -175,15 +209,29 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
{
EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+ const struct bContext *C = DRW_get_context();
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = scene->obedit;
UNUSED_VARS(psl, stl);
- if (ob->type == OB_MESH) {
- /* Get geometry cache */
- struct Batch *geom = DRW_cache_mesh_surface_get(ob);
+ if (ob->type == OB_CURVE) {
+ if (ob == obedit) {
+ /* Get geometry cache */
+ struct Batch *geom;
+
+// geom = DRW_cache_mesh_surface_get(ob);
+
+ geom = DRW_cache_curve_edge_wire_get(ob);
+ DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+
+ /* Add geom to a shading group */
+ geom = DRW_cache_curve_edge_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat);
- /* Add geom to a shading group */
- DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ geom = DRW_cache_curve_vert_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat);
+ }
}
}
@@ -219,7 +267,9 @@ static void EDIT_CURVE_draw_scene(void *vedata)
*/
/* ... or just render passes on default framebuffer. */
- DRW_draw_pass(psl->pass);
+ DRW_draw_pass(psl->wire_pass);
+ DRW_draw_pass(psl->overlay_edge_pass);
+ DRW_draw_pass(psl->overlay_vert_pass);
/* If you changed framebuffer, double check you rebind
* the default one with its textures attached before finishing */
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 3162189b411..cda5e5a9617 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -1190,6 +1190,18 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
}
break;
}
+
+ case OB_CURVE:
+ {
+ Object *obedit = scene->obedit;
+ if (ob != obedit) {
+ struct Batch *geom = DRW_cache_curve_edge_wire_get(ob);
+ int theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_shgroup_or(stl, theme_id, stl->g_data->wire);
+ DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ }
+ break;
+ }
case OB_LAMP:
DRW_shgroup_lamp(stl, ob, sl);
break;
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl
new file mode 100644
index 00000000000..57e96143c75
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl
@@ -0,0 +1,26 @@
+
+flat in int vertFlag;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_ACTIVE (1 << 1)
+
+#if __VERSION__ == 120
+ #define FragColor gl_FragColor
+#else
+ out vec4 FragColor;
+#endif
+
+void main()
+{
+ /* TODO: vertex size */
+
+ if ((vertFlag & VERTEX_SELECTED) != 0) {
+ FragColor = colorVertexSelect;
+ }
+ else if ((vertFlag & VERTEX_ACTIVE) != 0) {
+ FragColor = colorEditMeshActive;
+ }
+ else {
+ FragColor = colorVertex;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
new file mode 100644
index 00000000000..1af529e5482
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
@@ -0,0 +1,39 @@
+
+/* Draw Curve Vertices */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec3 pos;
+in int data;
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out int vertFlag;
+flat out int clipCase;
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ clipCase = 0;
+
+ vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* only verterx position 0 is used */
+ eData1 = eData2 = vec4(1e10);
+ eData2.zw = proj(pPos);
+
+ vertFlag = data;
+
+ gl_PointSize = sizeEdgeFix;
+ gl_Position = pPos;
+}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 5c3b669d64e..97400335bfe 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -47,12 +47,14 @@
#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_main.h"
-#include "BKE_lattice_render.h"
-#include "BKE_mesh_render.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_curve_render.h"
+#include "BKE_lattice_render.h"
+#include "BKE_mesh_render.h"
+
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_transform.h"
@@ -932,6 +934,9 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case OB_MESH:
BKE_mesh_batch_selection_dirty(ob->data);
break;
+ case OB_CURVE:
+ BKE_curve_batch_selection_dirty(ob->data);
+ break;
case OB_LATTICE:
BKE_lattice_batch_selection_dirty(ob->data);
break;
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 902fa4ce987..e598c32173c 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -266,6 +266,7 @@ typedef struct Curve {
char pad2[2];
+ void *batch_cache;
} Curve;
#define CURVE_VFONT_ANY(cu) \