Draw Manager: curve support

Draws the curve centerline and editmode verts/handles.

Handle theme colors, and normal display still need adding.
This commit is contained in:
Campbell Barton
2017-04-15 16:46:17 +10:00
parent ce6b01f203
commit cdba73c8fa
15 changed files with 902 additions and 31 deletions

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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
* \{ */

View File

@@ -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);

View File

@@ -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;
struct GPUShader *wire_sh;
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);
/* 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);
/* 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);
/* 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;
/* Add geom to a shading group */
DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
// 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);
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 */

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -266,6 +266,7 @@ typedef struct Curve {
char pad2[2];
void *batch_cache;
} Curve;
#define CURVE_VFONT_ANY(cu) \