2017-04-15 16:46:17 +10:00
|
|
|
/*
|
|
|
|
* ***** 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 *****
|
|
|
|
*/
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
/** \file draw_cache_impl_curve.c
|
|
|
|
* \ingroup draw
|
2017-04-15 16:46:17 +10:00
|
|
|
*
|
|
|
|
* \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"
|
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
#include "BKE_font.h"
|
2017-04-21 02:18:14 +10:00
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
#include "GPU_batch.h"
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
#include "draw_cache_impl.h" /* own include */
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
#define SELECT 1
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO
|
|
|
|
* - Ensure `CurveCache`, `SEQUENCER_DAG_WORKAROUND`.
|
|
|
|
* - Check number of verts/edges to see if cache is valid.
|
2017-04-20 02:08:02 +10:00
|
|
|
* - Check if 'overlay.edges' can use single attribyte per edge, not 2 (for selection drawing).
|
2017-04-15 16:46:17 +10:00
|
|
|
*/
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
static void curve_batch_cache_clear(Curve *cu);
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-20 05:23:48 +10:00
|
|
|
static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
|
|
|
|
{
|
|
|
|
int normal_len = 0;
|
|
|
|
const BevList *bl;
|
|
|
|
const Nurb *nu;
|
|
|
|
for (bl = ob_curve_cache->bev.first, nu = lb->first; nu && bl; bl = bl->next, nu = nu->next) {
|
|
|
|
int nr = bl->nr;
|
|
|
|
int skip = nu->resolu / 16;
|
|
|
|
#if 0
|
|
|
|
while (nr-- > 0) { /* accounts for empty bevel lists */
|
|
|
|
normal_len += 1;
|
|
|
|
nr -= skip;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
normal_len += max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return normal_len;
|
|
|
|
}
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* 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;
|
|
|
|
|
2017-04-20 05:23:48 +10:00
|
|
|
/* edit mode normal's */
|
|
|
|
struct {
|
|
|
|
/* 'edge_len == len * 2'
|
|
|
|
* 'vert_len == len * 3' */
|
|
|
|
int len;
|
|
|
|
} normal;
|
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
struct {
|
|
|
|
EditFont *edit_font;
|
|
|
|
} text;
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
bool hide_handles;
|
2017-04-20 05:23:48 +10:00
|
|
|
bool hide_normals;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
/* borrow from 'Object' */
|
|
|
|
CurveCache *ob_curve_cache;
|
|
|
|
|
|
|
|
/* borrow from 'Curve' */
|
|
|
|
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,
|
2017-04-20 05:23:48 +10:00
|
|
|
/* Edit-mode normals */
|
|
|
|
CU_DATATYPE_NORMAL = 1 << 2,
|
2017-04-21 02:18:14 +10:00
|
|
|
/* Geometry */
|
|
|
|
CU_DATATYPE_SURFACE = 1 << 3,
|
2017-04-21 17:58:18 +10:00
|
|
|
/* Text */
|
|
|
|
CU_DATATYPE_TEXT_SELECT = 1 << 4,
|
2017-04-15 16:46:17 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
CurveRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
|
|
|
|
rdata->types = types;
|
2017-04-15 16:46:17 +10:00
|
|
|
ListBase *nurbs;
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
|
|
|
|
rdata->hide_normals = (cu->drawflag & CU_HIDE_NORMALS) != 0;
|
2017-04-20 05:23:48 +10:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->actnu = cu->actnu;
|
|
|
|
rdata->actvert = cu->actvert;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->ob_curve_cache = ob_curve_cache;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
if (types & CU_DATATYPE_WIRE) {
|
|
|
|
curve_render_wire_verts_edges_len_get(
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->ob_curve_cache,
|
|
|
|
&rdata->wire.vert_len, &rdata->wire.edge_len);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cu->editnurb) {
|
|
|
|
EditNurb *editnurb = cu->editnurb;
|
|
|
|
nurbs = &editnurb->nurbs;
|
|
|
|
|
|
|
|
if (types & CU_DATATYPE_OVERLAY) {
|
|
|
|
curve_render_overlay_verts_edges_len_get(
|
2017-04-20 16:24:35 +10:00
|
|
|
nurbs, rdata->hide_handles,
|
|
|
|
&rdata->overlay.vert_len,
|
|
|
|
rdata->hide_handles ? NULL : &rdata->overlay.edge_len);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->actnu = cu->actnu;
|
|
|
|
rdata->actvert = cu->actvert;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
2017-04-20 05:23:48 +10:00
|
|
|
if (types & CU_DATATYPE_NORMAL) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->normal.len = curve_render_normal_len_get(nurbs, rdata->ob_curve_cache);
|
2017-04-20 05:23:48 +10:00
|
|
|
}
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
nurbs = &cu->nurb;
|
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->nurbs = nurbs;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
rdata->text.edit_font = cu->editfont;
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
return rdata;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static void curve_render_data_free(CurveRenderData *rdata)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
|
|
|
#if 0
|
2017-04-20 16:24:35 +10:00
|
|
|
if (rdata->loose_verts) {
|
|
|
|
MEM_freeN(rdata->loose_verts);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
#endif
|
2017-04-20 16:24:35 +10:00
|
|
|
MEM_freeN(rdata);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int curve_render_data_overlay_verts_len_get(const CurveRenderData *rdata)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_OVERLAY);
|
|
|
|
return rdata->overlay.vert_len;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int curve_render_data_overlay_edges_len_get(const CurveRenderData *rdata)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_OVERLAY);
|
|
|
|
return rdata->overlay.edge_len;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int curve_render_data_wire_verts_len_get(const CurveRenderData *rdata)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_WIRE);
|
|
|
|
return rdata->wire.vert_len;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_WIRE);
|
|
|
|
return rdata->wire.edge_len;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int curve_render_data_normal_len_get(const CurveRenderData *rdata)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
|
|
|
|
return rdata->normal.len;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
enum {
|
|
|
|
VFLAG_VERTEX_SELECTED = 1 << 0,
|
|
|
|
VFLAG_VERTEX_ACTIVE = 1 << 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
2017-06-19 20:18:04 +10:00
|
|
|
/* Curve Gwn_Batch Cache */
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
typedef struct CurveBatchCache {
|
2017-04-20 02:08:02 +10:00
|
|
|
/* center-line */
|
|
|
|
struct {
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *verts;
|
|
|
|
Gwn_VertBuf *edges;
|
|
|
|
Gwn_Batch *batch;
|
|
|
|
Gwn_IndexBuf *elem;
|
2017-04-20 02:08:02 +10:00
|
|
|
} wire;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-20 05:23:48 +10:00
|
|
|
/* normals */
|
|
|
|
struct {
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *verts;
|
|
|
|
Gwn_VertBuf *edges;
|
|
|
|
Gwn_Batch *batch;
|
|
|
|
Gwn_IndexBuf *elem;
|
2017-04-20 05:23:48 +10:00
|
|
|
} normal;
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
/* control handles and vertices */
|
2017-04-20 02:08:02 +10:00
|
|
|
struct {
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *edges;
|
|
|
|
Gwn_Batch *verts;
|
2017-04-20 02:08:02 +10:00
|
|
|
} overlay;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-21 02:18:14 +10:00
|
|
|
struct {
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *batch;
|
2017-04-21 02:18:14 +10:00
|
|
|
} surface;
|
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
/* 3d text */
|
|
|
|
struct {
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *select;
|
|
|
|
Gwn_Batch *cursor;
|
2017-04-21 17:58:18 +10:00
|
|
|
} text;
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
/* settings to determine if cache is invalid */
|
|
|
|
bool is_dirty;
|
|
|
|
|
|
|
|
bool hide_handles;
|
2017-04-20 05:23:48 +10:00
|
|
|
bool hide_normals;
|
|
|
|
|
|
|
|
float normal_size;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
bool is_editmode;
|
|
|
|
} CurveBatchCache;
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
/* Gwn_Batch cache management. */
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
static bool curve_batch_cache_valid(Curve *cu)
|
|
|
|
{
|
|
|
|
CurveBatchCache *cache = cu->batch_cache;
|
|
|
|
|
|
|
|
if (cache == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
if (cache->is_editmode != ((cu->editnurb != NULL) || (cu->editfont != NULL))) {
|
2017-04-15 16:46:17 +10:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-04-20 05:55:48 +10:00
|
|
|
if (cache->is_editmode) {
|
2017-04-21 17:58:18 +10:00
|
|
|
if (cu->editnurb) {
|
|
|
|
if ((cache->hide_handles != ((cu->drawflag & CU_HIDE_HANDLES) != 0))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ((cache->hide_normals != ((cu->drawflag & CU_HIDE_NORMALS) != 0))) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-04-20 05:55:48 +10:00
|
|
|
}
|
2017-04-21 17:58:18 +10:00
|
|
|
else if (cu->editfont) {
|
|
|
|
/* TODO */
|
2017-04-20 05:55:48 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
if (cache->is_dirty == false) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* TODO: check number of vertices/edges? */
|
|
|
|
if (cache->is_editmode) {
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2017-04-20 05:55:48 +10:00
|
|
|
cache->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
|
|
|
|
cache->hide_normals = (cu->drawflag & CU_HIDE_NORMALS) != 0;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
ListBase *nurbs;
|
|
|
|
if (cu->editnurb) {
|
|
|
|
EditNurb *editnurb = cu->editnurb;
|
|
|
|
nurbs = &editnurb->nurbs;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nurbs = &cu->nurb;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
cache->is_editmode = (cu->editnurb != NULL) || (cu->editfont != NULL);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
cache->is_dirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CurveBatchCache *curve_batch_cache_get(Curve *cu)
|
|
|
|
{
|
|
|
|
if (!curve_batch_cache_valid(cu)) {
|
2017-04-21 21:14:11 +10:00
|
|
|
curve_batch_cache_clear(cu);
|
2017-04-15 16:46:17 +10:00
|
|
|
curve_batch_cache_init(cu);
|
|
|
|
}
|
|
|
|
return cu->batch_cache;
|
|
|
|
}
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
void DRW_curve_batch_cache_dirty(Curve *cu, int mode)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = cu->batch_cache;
|
2017-04-21 21:14:11 +10:00
|
|
|
if (cache == NULL) {
|
|
|
|
return;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
2017-04-21 21:14:11 +10:00
|
|
|
switch (mode) {
|
|
|
|
case BKE_CURVE_BATCH_DIRTY_ALL:
|
|
|
|
cache->is_dirty = true;
|
|
|
|
break;
|
|
|
|
case BKE_CURVE_BATCH_DIRTY_SELECT:
|
|
|
|
/* editnurb */
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->overlay.verts);
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->overlay.edges);
|
|
|
|
|
|
|
|
/* editfont */
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->text.select);
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->text.cursor);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BLI_assert(0);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
static void curve_batch_cache_clear(Curve *cu)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = cu->batch_cache;
|
|
|
|
if (!cache) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->overlay.verts);
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->overlay.edges);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->surface.batch);
|
2017-04-21 02:18:14 +10:00
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
if (cache->wire.batch) {
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->wire.batch);
|
2017-04-20 05:55:48 +10:00
|
|
|
cache->wire.verts = NULL;
|
|
|
|
cache->wire.edges = NULL;
|
|
|
|
cache->wire.elem = NULL;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
else {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->wire.verts);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->wire.edges);
|
|
|
|
GWN_INDEXBUF_DISCARD_SAFE(cache->wire.elem);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
2017-04-20 05:23:48 +10:00
|
|
|
|
|
|
|
if (cache->normal.batch) {
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->normal.batch);
|
2017-04-20 05:55:48 +10:00
|
|
|
cache->normal.verts = NULL;
|
|
|
|
cache->normal.edges = NULL;
|
|
|
|
cache->normal.elem = NULL;
|
2017-04-20 05:23:48 +10:00
|
|
|
}
|
|
|
|
else {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->normal.verts);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->normal.edges);
|
|
|
|
GWN_INDEXBUF_DISCARD_SAFE(cache->normal.elem);
|
2017-04-20 05:23:48 +10:00
|
|
|
}
|
2017-04-21 17:58:18 +10:00
|
|
|
|
|
|
|
/* 3d text */
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->text.cursor);
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->text.select);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
void DRW_curve_batch_cache_free(Curve *cu)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-21 21:14:11 +10:00
|
|
|
curve_batch_cache_clear(cu);
|
2017-04-15 16:46:17 +10:00
|
|
|
MEM_SAFE_FREE(cu->batch_cache);
|
|
|
|
}
|
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Private Curve Cache API
|
|
|
|
* \{ */
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
/* Gwn_Batch cache usage. */
|
|
|
|
static Gwn_VertBuf *curve_batch_cache_get_wire_verts(CurveRenderData *rdata, CurveBatchCache *cache)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_WIRE);
|
|
|
|
BLI_assert(rdata->ob_curve_cache != NULL);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
if (cache->wire.verts == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos; } attr_id;
|
2017-04-15 16:46:17 +10:00
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
/* initialize vertex format */
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
const int vert_len = curve_render_data_wire_verts_len_get(rdata);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = cache->wire.verts = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vert_len);
|
2017-04-15 16:46:17 +10:00
|
|
|
int vbo_len_used = 0;
|
2017-04-20 16:24:35 +10:00
|
|
|
for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
|
2017-04-15 16:46:17 +10:00
|
|
|
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++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bevp->vec);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BLI_assert(vbo_len_used == vert_len);
|
|
|
|
}
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
return cache->wire.verts;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_IndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, CurveBatchCache *cache)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_WIRE);
|
|
|
|
BLI_assert(rdata->ob_curve_cache != NULL);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
if (cache->wire.edges == NULL) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const int vert_len = curve_render_data_wire_verts_len_get(rdata);
|
|
|
|
const int edge_len = curve_render_data_wire_edges_len_get(rdata);
|
2017-04-20 05:23:48 +10:00
|
|
|
int edge_len_used = 0;
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBufBuilder elb;
|
|
|
|
GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
|
|
|
int i = 0;
|
2017-04-20 16:24:35 +10:00
|
|
|
for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
|
2017-04-15 16:46:17 +10:00
|
|
|
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++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_line_verts(&elb, i_prev, i);
|
2017-04-20 05:23:48 +10:00
|
|
|
edge_len_used += 1;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
if (rdata->hide_handles) {
|
2017-04-20 05:23:48 +10:00
|
|
|
BLI_assert(edge_len_used <= edge_len);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
else {
|
2017-04-20 05:23:48 +10:00
|
|
|
BLI_assert(edge_len_used == edge_len);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->wire.elem = GWN_indexbuf_build(&elb);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
return cache->wire.elem;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, CurveBatchCache *cache)
|
2017-04-20 05:23:48 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
|
|
|
|
BLI_assert(rdata->ob_curve_cache != NULL);
|
2017-04-20 05:23:48 +10:00
|
|
|
|
|
|
|
if (cache->normal.verts == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos; } attr_id;
|
2017-04-20 05:23:48 +10:00
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
/* initialize vertex format */
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
2017-04-20 05:23:48 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
const int normal_len = curve_render_data_normal_len_get(rdata);
|
2017-04-20 05:23:48 +10:00
|
|
|
const int vert_len = normal_len * 3;
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = cache->normal.verts = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vert_len);
|
2017-04-20 05:23:48 +10:00
|
|
|
int vbo_len_used = 0;
|
|
|
|
|
|
|
|
const BevList *bl;
|
|
|
|
const Nurb *nu;
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
for (bl = rdata->ob_curve_cache->bev.first, nu = rdata->nurbs->first;
|
2017-04-20 05:23:48 +10:00
|
|
|
nu && bl;
|
|
|
|
bl = bl->next, nu = nu->next)
|
|
|
|
{
|
|
|
|
const BevPoint *bevp = bl->bevpoints;
|
|
|
|
int nr = bl->nr;
|
|
|
|
int skip = nu->resolu / 16;
|
|
|
|
|
|
|
|
while (nr-- > 0) { /* accounts for empty bevel lists */
|
|
|
|
const float fac = bevp->radius * cache->normal_size;
|
|
|
|
float vec_a[3]; /* Offset perpendicular to the curve */
|
|
|
|
float vec_b[3]; /* Delta along the curve */
|
|
|
|
|
|
|
|
vec_a[0] = fac;
|
|
|
|
vec_a[1] = 0.0f;
|
|
|
|
vec_a[2] = 0.0f;
|
|
|
|
|
|
|
|
mul_qt_v3(bevp->quat, vec_a);
|
2017-04-20 18:56:53 +10:00
|
|
|
madd_v3_v3fl(vec_a, bevp->dir, -fac);
|
|
|
|
|
|
|
|
reflect_v3_v3v3(vec_b, vec_a, bevp->dir);
|
|
|
|
negate_v3(vec_b);
|
|
|
|
|
2017-04-20 05:23:48 +10:00
|
|
|
add_v3_v3(vec_a, bevp->vec);
|
|
|
|
add_v3_v3(vec_b, bevp->vec);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_a);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, bevp->vec);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_b);
|
2017-04-20 05:23:48 +10:00
|
|
|
|
|
|
|
bevp += skip + 1;
|
|
|
|
nr -= skip;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BLI_assert(vbo_len_used == vert_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->normal.verts;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_IndexBuf *curve_batch_cache_get_normal_edges(CurveRenderData *rdata, CurveBatchCache *cache)
|
2017-04-20 05:23:48 +10:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
|
|
|
|
BLI_assert(rdata->ob_curve_cache != NULL);
|
2017-04-20 05:23:48 +10:00
|
|
|
|
|
|
|
if (cache->normal.edges == NULL) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const int normal_len = curve_render_data_normal_len_get(rdata);
|
2017-04-20 20:59:42 +10:00
|
|
|
const int vert_len = normal_len * 3;
|
2017-04-20 05:23:48 +10:00
|
|
|
const int edge_len = normal_len * 2;
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBufBuilder elb;
|
|
|
|
GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
|
2017-04-20 05:23:48 +10:00
|
|
|
|
|
|
|
int vbo_len_used = 0;
|
|
|
|
for (int i = 0; i < normal_len; i++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 0, vbo_len_used + 1);
|
|
|
|
GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 1, vbo_len_used + 2);
|
2017-04-20 05:23:48 +10:00
|
|
|
vbo_len_used += 3;
|
|
|
|
}
|
|
|
|
|
2017-04-20 20:59:42 +10:00
|
|
|
BLI_assert(vbo_len_used == vert_len);
|
2017-04-20 05:23:48 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->normal.elem = GWN_indexbuf_build(&elb);
|
2017-04-20 05:23:48 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
return cache->normal.elem;
|
|
|
|
}
|
|
|
|
|
2017-04-15 16:46:17 +10:00
|
|
|
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);
|
2017-04-20 16:24:35 +10:00
|
|
|
CurveRenderData *rdata = curve_render_data_create(cu, NULL, options);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
if (cache->overlay.verts == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, data; } attr_id;
|
2017-04-15 16:46:17 +10:00
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
/* initialize vertex format */
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
|
2017-04-20 16:24:35 +10:00
|
|
|
const int vbo_len_capacity = curve_render_data_overlay_verts_len_get(rdata);
|
2017-04-15 16:46:17 +10:00
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-04-15 16:46:17 +10:00
|
|
|
int i = 0;
|
2017-04-20 16:24:35 +10:00
|
|
|
for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next) {
|
2017-04-15 16:46:17 +10:00
|
|
|
if (nu->bezt) {
|
|
|
|
int a = 0;
|
|
|
|
for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
|
|
|
|
if (bezt->hide == false) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const bool is_active = (i == rdata->actvert);
|
2017-04-15 16:46:17 +10:00
|
|
|
char vflag;
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
if (rdata->hide_handles) {
|
2017-04-15 16:46:17 +10:00
|
|
|
vflag = (bezt->f2 & SELECT) ?
|
|
|
|
(is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
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;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
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) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const bool is_active = (i == rdata->actvert);
|
2017-04-15 16:46:17 +10:00
|
|
|
char vflag;
|
|
|
|
vflag = (bp->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp->vec);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
vbo_len_used += 1;
|
|
|
|
}
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i += nu->pntsu;
|
|
|
|
}
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay.verts = GWN_batch_create(GWN_PRIM_POINTS, vbo, NULL);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
if ((cache->overlay.edges == NULL) && (rdata->hide_handles == false)) {
|
2017-04-15 16:46:17 +10:00
|
|
|
/* Note: we could reference indices to vertices (above) */
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, data; } attr_id;
|
2017-04-15 16:46:17 +10:00
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
/* initialize vertex format */
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
|
2017-04-20 16:24:35 +10:00
|
|
|
const int edge_len = curve_render_data_overlay_edges_len_get(rdata);
|
2017-04-15 16:46:17 +10:00
|
|
|
const int vbo_len_capacity = edge_len * 2;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-04-15 16:46:17 +10:00
|
|
|
int i = 0;
|
2017-04-20 16:24:35 +10:00
|
|
|
for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next) {
|
2017-04-15 16:46:17 +10:00
|
|
|
if (nu->bezt) {
|
|
|
|
int a = 0;
|
|
|
|
for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
|
|
|
|
if (bezt->hide == false) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const bool is_active = (i == rdata->actvert);
|
2017-04-15 16:46:17 +10:00
|
|
|
char vflag;
|
|
|
|
|
|
|
|
vflag = (bezt->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[0]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
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;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
vbo_len_used += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vflag = (bezt->f3 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[2]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
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;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_prev->vec);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
vbo_len_used += 1;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_curr->vec);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
|
2017-04-15 16:46:17 +10:00
|
|
|
vbo_len_used += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay.edges = GWN_batch_create(GWN_PRIM_LINES, vbo, NULL);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
curve_render_data_free(rdata);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata, CurveBatchCache *cache)
|
2017-04-21 02:18:14 +10:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
|
|
|
|
if (cache->surface.batch == NULL) {
|
|
|
|
cache->surface.batch = BLI_displist_batch_calc_surface(&rdata->ob_curve_cache->disp);
|
|
|
|
}
|
|
|
|
return cache->surface.batch;
|
|
|
|
}
|
|
|
|
|
2017-04-21 17:58:18 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Private Object/Font Cache API
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_Batch *curve_batch_cache_get_overlay_select(CurveRenderData *rdata, CurveBatchCache *cache)
|
2017-04-21 17:58:18 +10:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
|
|
|
|
if (cache->text.select == NULL) {
|
|
|
|
EditFont *ef = rdata->text.edit_font;
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos; } attr_id;
|
2017-04-21 17:58:18 +10:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
2017-04-21 17:58:18 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
|
2017-04-21 17:58:18 +10:00
|
|
|
const int vbo_len_capacity = ef->selboxes_len * 6;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-04-21 17:58:18 +10:00
|
|
|
|
|
|
|
float box[4][3];
|
|
|
|
|
|
|
|
/* fill in xy below */
|
|
|
|
box[0][2] = box[1][2] = box[2][2] = box[3][2] = 0.001;
|
|
|
|
|
|
|
|
for (int i = 0; i < ef->selboxes_len; i++) {
|
|
|
|
EditFontSelBox *sb = &ef->selboxes[i];
|
|
|
|
|
|
|
|
float selboxw;
|
|
|
|
if (i + 1 != ef->selboxes_len) {
|
|
|
|
if (ef->selboxes[i + 1].y == sb->y)
|
|
|
|
selboxw = ef->selboxes[i + 1].x - sb->x;
|
|
|
|
else
|
|
|
|
selboxw = sb->w;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
selboxw = sb->w;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sb->rot == 0.0f) {
|
|
|
|
copy_v2_fl2(box[0], sb->x, sb->y);
|
|
|
|
copy_v2_fl2(box[1], sb->x + selboxw, sb->y);
|
|
|
|
copy_v2_fl2(box[2], sb->x + selboxw, sb->y + sb->h);
|
|
|
|
copy_v2_fl2(box[3], sb->x, sb->y + sb->h);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
float mat[2][2];
|
|
|
|
|
|
|
|
angle_to_mat2(mat, sb->rot);
|
|
|
|
|
|
|
|
copy_v2_fl2(box[0], sb->x, sb->y);
|
|
|
|
|
|
|
|
copy_v2_fl2(box[1], selboxw, 0.0f);
|
|
|
|
mul_m2v2(mat, box[1]);
|
|
|
|
add_v2_v2(box[1], &sb->x);
|
|
|
|
|
|
|
|
copy_v2_fl2(box[2], selboxw, sb->h);
|
|
|
|
mul_m2v2(mat, box[2]);
|
|
|
|
add_v2_v2(box[2], &sb->x);
|
|
|
|
|
|
|
|
copy_v2_fl2(box[3], 0.0f, sb->h);
|
|
|
|
mul_m2v2(mat, box[3]);
|
|
|
|
add_v2_v2(box[3], &sb->x);
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[1]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
|
2017-04-21 17:58:18 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[3]);
|
2017-04-21 17:58:18 +10:00
|
|
|
}
|
|
|
|
BLI_assert(vbo_len_used == vbo_len_capacity);
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->text.select = GWN_batch_create(GWN_PRIM_TRIS, vbo, NULL);
|
2017-04-21 17:58:18 +10:00
|
|
|
}
|
|
|
|
return cache->text.select;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_Batch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, CurveBatchCache *cache)
|
2017-04-21 17:58:18 +10:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
|
|
|
|
if (cache->text.cursor == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos; } attr_id;
|
2017-04-21 17:58:18 +10:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
|
2017-04-21 17:58:18 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
|
2017-04-21 17:58:18 +10:00
|
|
|
const int vbo_len_capacity = 4;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-04-21 17:58:18 +10:00
|
|
|
for (int i = 0; i < 4; i++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->text.edit_font->textcurs[i]);
|
2017-04-21 17:58:18 +10:00
|
|
|
}
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->text.cursor = GWN_batch_create(GWN_PRIM_TRI_FAN, vbo, NULL);
|
2017-04-21 17:58:18 +10:00
|
|
|
}
|
|
|
|
return cache->text.cursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Public Object/Curve API
|
|
|
|
* \{ */
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = curve_batch_cache_get(cu);
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
if (cache->wire.batch == NULL) {
|
2017-04-15 16:46:17 +10:00
|
|
|
/* create batch from Curve */
|
2017-04-20 16:24:35 +10:00
|
|
|
CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_WIRE);
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->wire.batch = GWN_batch_create(
|
|
|
|
GWN_PRIM_LINES,
|
2017-04-20 16:24:35 +10:00
|
|
|
curve_batch_cache_get_wire_verts(rdata, cache),
|
|
|
|
curve_batch_cache_get_wire_edges(rdata, cache));
|
2017-04-15 16:46:17 +10:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
curve_render_data_free(rdata);
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
2017-04-20 02:08:02 +10:00
|
|
|
return cache->wire.batch;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve_cache, float normal_size)
|
2017-04-20 05:23:48 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = curve_batch_cache_get(cu);
|
|
|
|
|
|
|
|
if (cache->normal.batch != NULL) {
|
|
|
|
cache->normal_size = normal_size;
|
|
|
|
if (cache->normal_size != normal_size) {
|
|
|
|
BATCH_DISCARD_ALL_SAFE(cache->normal.batch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cache->normal_size = normal_size;
|
|
|
|
|
|
|
|
if (cache->normal.batch == NULL) {
|
|
|
|
/* create batch from Curve */
|
2017-04-20 16:24:35 +10:00
|
|
|
CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_NORMAL);
|
2017-04-20 05:23:48 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->normal.batch = GWN_batch_create(
|
|
|
|
GWN_PRIM_LINES,
|
2017-04-20 16:24:35 +10:00
|
|
|
curve_batch_cache_get_normal_verts(rdata, cache),
|
|
|
|
curve_batch_cache_get_normal_edges(rdata, cache));
|
2017-04-20 05:23:48 +10:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
curve_render_data_free(rdata);
|
2017-04-20 05:23:48 +10:00
|
|
|
cache->normal_size = normal_size;
|
|
|
|
}
|
|
|
|
return cache->normal.batch;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(Curve *cu)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = curve_batch_cache_get(cu);
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
if (cache->overlay.edges == NULL) {
|
2017-04-15 16:46:17 +10:00
|
|
|
curve_batch_cache_create_overlay_batches(cu);
|
|
|
|
}
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
return cache->overlay.edges;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(Curve *cu)
|
2017-04-15 16:46:17 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = curve_batch_cache_get(cu);
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
if (cache->overlay.verts == NULL) {
|
2017-04-15 16:46:17 +10:00
|
|
|
curve_batch_cache_create_overlay_batches(cu);
|
|
|
|
}
|
|
|
|
|
2017-04-20 02:08:02 +10:00
|
|
|
return cache->overlay.verts;
|
2017-04-15 16:46:17 +10:00
|
|
|
}
|
2017-04-21 02:18:14 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(
|
2017-04-21 02:18:14 +10:00
|
|
|
struct Curve *cu, struct CurveCache *ob_curve_cache)
|
|
|
|
{
|
|
|
|
CurveBatchCache *cache = curve_batch_cache_get(cu);
|
|
|
|
|
|
|
|
if (cache->surface.batch == NULL) {
|
|
|
|
CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
|
|
|
|
|
|
|
|
curve_batch_cache_get_pos_and_normals(rdata, cache);
|
|
|
|
|
|
|
|
curve_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->surface.batch;
|
|
|
|
}
|
2017-04-21 17:58:18 +10:00
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Public Object/Font API
|
|
|
|
* \{ */
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(Curve *cu)
|
2017-04-21 17:58:18 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = curve_batch_cache_get(cu);
|
|
|
|
|
|
|
|
if (cache->text.select == NULL) {
|
|
|
|
CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT);
|
|
|
|
|
|
|
|
curve_batch_cache_get_overlay_select(rdata, cache);
|
|
|
|
|
|
|
|
curve_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->text.select;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(Curve *cu)
|
2017-04-21 17:58:18 +10:00
|
|
|
{
|
|
|
|
CurveBatchCache *cache = curve_batch_cache_get(cu);
|
|
|
|
|
|
|
|
if (cache->text.cursor == NULL) {
|
|
|
|
CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT);
|
|
|
|
|
|
|
|
curve_batch_cache_get_overlay_cursor(rdata, cache);
|
|
|
|
|
|
|
|
curve_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->text.cursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|