752 lines
23 KiB
C
752 lines
23 KiB
C
/*
|
|
* ***** 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) 2008, Blender Foundation
|
|
* This is a new part of Blender
|
|
*
|
|
* Contributor(s): Antonio Vazquez
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file draw/engines/gpencil/gpencil_draw_cache_impl.c
|
|
* \ingroup draw
|
|
*/
|
|
|
|
#include "BLI_polyfill_2d.h"
|
|
#include "BLI_math_color.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
|
#include "DNA_gpencil_types.h"
|
|
#include "DNA_screen_types.h"
|
|
#include "DNA_view3d_types.h"
|
|
|
|
#include "BKE_action.h"
|
|
#include "BKE_deform.h"
|
|
#include "BKE_gpencil.h"
|
|
|
|
#include "DRW_render.h"
|
|
|
|
#include "GPU_immediate.h"
|
|
#include "GPU_draw.h"
|
|
|
|
#include "ED_gpencil.h"
|
|
#include "ED_view3d.h"
|
|
|
|
#include "UI_resources.h"
|
|
|
|
#include "gpencil_engine.h"
|
|
|
|
/* Helper to add stroke point to vbo */
|
|
static void gpencil_set_stroke_point(
|
|
GPUVertBuf *vbo, const bGPDspoint *pt, int idx,
|
|
uint pos_id, uint color_id,
|
|
uint thickness_id, uint uvdata_id, short thickness,
|
|
const float ink[4])
|
|
{
|
|
|
|
float alpha = ink[3] * pt->strength;
|
|
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
|
|
float col[4];
|
|
ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha);
|
|
|
|
GPU_vertbuf_attr_set(vbo, color_id, idx, col);
|
|
|
|
/* transfer both values using the same shader variable */
|
|
float uvdata[2] = { pt->uv_fac, pt->uv_rot };
|
|
GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata);
|
|
|
|
/* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */
|
|
float thick = max_ff(pt->pressure * thickness, 1.0f);
|
|
GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick);
|
|
|
|
GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
|
|
}
|
|
|
|
/* Helper to add a new fill point and texture coordinates to vertex buffer */
|
|
static void gpencil_set_fill_point(
|
|
GPUVertBuf *vbo, int idx, bGPDspoint *pt, const float fcolor[4], float uv[2],
|
|
uint pos_id, uint color_id, uint text_id)
|
|
{
|
|
GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
|
|
GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
|
|
GPU_vertbuf_attr_set(vbo, text_id, idx, uv);
|
|
}
|
|
|
|
/* create batch geometry data for points stroke shader */
|
|
GPUBatch *DRW_gpencil_get_point_geom(bGPDstroke *gps, short thickness, const float ink[4])
|
|
{
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id, size_id, uvdata_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
size_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, gps->totpoints);
|
|
|
|
/* draw stroke curve */
|
|
const bGPDspoint *pt = gps->points;
|
|
int idx = 0;
|
|
float alpha;
|
|
float col[4];
|
|
|
|
for (int i = 0; i < gps->totpoints; i++, pt++) {
|
|
/* set point */
|
|
alpha = ink[3] * pt->strength;
|
|
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
|
|
ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha);
|
|
|
|
float thick = max_ff(pt->pressure * thickness, 1.0f);
|
|
|
|
GPU_vertbuf_attr_set(vbo, color_id, idx, col);
|
|
GPU_vertbuf_attr_set(vbo, size_id, idx, &thick);
|
|
|
|
/* transfer both values using the same shader variable */
|
|
float uvdata[2] = { pt->uv_fac, pt->uv_rot };
|
|
GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata);
|
|
|
|
GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
|
|
idx++;
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
/* create batch geometry data for stroke shader */
|
|
GPUBatch *DRW_gpencil_get_stroke_geom(bGPDstroke *gps, short thickness, const float ink[4])
|
|
{
|
|
bGPDspoint *points = gps->points;
|
|
int totpoints = gps->totpoints;
|
|
/* if cyclic needs more vertex */
|
|
int cyclic_add = (gps->flag & GP_STROKE_CYCLIC) ? 1 : 0;
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id, thickness_id, uvdata_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, totpoints + cyclic_add + 2);
|
|
|
|
/* draw stroke curve */
|
|
const bGPDspoint *pt = points;
|
|
int idx = 0;
|
|
for (int i = 0; i < totpoints; i++, pt++) {
|
|
/* first point for adjacency (not drawn) */
|
|
if (i == 0) {
|
|
if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
|
|
gpencil_set_stroke_point(
|
|
vbo, &points[totpoints - 1], idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
|
|
idx++;
|
|
}
|
|
else {
|
|
gpencil_set_stroke_point(
|
|
vbo, &points[1], idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
|
|
idx++;
|
|
}
|
|
}
|
|
/* set point */
|
|
gpencil_set_stroke_point(
|
|
vbo, pt, idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
|
|
idx++;
|
|
}
|
|
|
|
if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
|
|
/* draw line to first point to complete the cycle */
|
|
gpencil_set_stroke_point(
|
|
vbo, &points[0], idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
|
|
idx++;
|
|
/* now add adjacency point (not drawn) */
|
|
gpencil_set_stroke_point(
|
|
vbo, &points[1], idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
|
|
idx++;
|
|
}
|
|
/* last adjacency point (not drawn) */
|
|
else {
|
|
gpencil_set_stroke_point(
|
|
vbo, &points[totpoints - 2], idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
/* create batch geometry data for current buffer stroke shader */
|
|
GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
|
|
{
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
Scene *scene = draw_ctx->scene;
|
|
View3D *v3d = draw_ctx->v3d;
|
|
ARegion *ar = draw_ctx->ar;
|
|
RegionView3D *rv3d = draw_ctx->rv3d;
|
|
ToolSettings *ts = scene->toolsettings;
|
|
Object *ob = draw_ctx->obact;
|
|
|
|
tGPspoint *points = gpd->runtime.sbuffer;
|
|
int totpoints = gpd->runtime.sbuffer_size;
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id, thickness_id, uvdata_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, totpoints + 2);
|
|
|
|
/* draw stroke curve */
|
|
const tGPspoint *tpt = points;
|
|
bGPDspoint pt, pt2;
|
|
int idx = 0;
|
|
|
|
/* get origin to reproject point */
|
|
float origin[3];
|
|
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
|
|
ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
|
|
|
|
for (int i = 0; i < totpoints; i++, tpt++) {
|
|
ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
|
|
ED_gp_project_point_to_plane(ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
|
|
|
|
/* first point for adjacency (not drawn) */
|
|
if (i == 0) {
|
|
if (totpoints > 1) {
|
|
ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2);
|
|
gpencil_set_stroke_point(
|
|
vbo, &pt2, idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
|
|
}
|
|
else {
|
|
gpencil_set_stroke_point(
|
|
vbo, &pt, idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
|
|
}
|
|
idx++;
|
|
}
|
|
/* set point */
|
|
gpencil_set_stroke_point(
|
|
vbo, &pt, idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
|
|
idx++;
|
|
}
|
|
|
|
/* last adjacency point (not drawn) */
|
|
if (totpoints > 2) {
|
|
ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2);
|
|
gpencil_set_stroke_point(
|
|
vbo, &pt2, idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
|
|
}
|
|
else {
|
|
gpencil_set_stroke_point(
|
|
vbo, &pt, idx,
|
|
pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
/* create batch geometry data for current buffer point shader */
|
|
GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness)
|
|
{
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
Scene *scene = draw_ctx->scene;
|
|
View3D *v3d = draw_ctx->v3d;
|
|
ARegion *ar = draw_ctx->ar;
|
|
RegionView3D *rv3d = draw_ctx->rv3d;
|
|
ToolSettings *ts = scene->toolsettings;
|
|
Object *ob = draw_ctx->obact;
|
|
|
|
tGPspoint *points = gpd->runtime.sbuffer;
|
|
int totpoints = gpd->runtime.sbuffer_size;
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id, thickness_id, uvdata_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, totpoints);
|
|
|
|
/* draw stroke curve */
|
|
const tGPspoint *tpt = points;
|
|
bGPDspoint pt;
|
|
int idx = 0;
|
|
|
|
/* get origin to reproject point */
|
|
float origin[3];
|
|
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
|
|
ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
|
|
|
|
for (int i = 0; i < totpoints; i++, tpt++) {
|
|
ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
|
|
ED_gp_project_point_to_plane(ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
|
|
|
|
/* set point */
|
|
gpencil_set_stroke_point(
|
|
vbo, &pt, idx,
|
|
pos_id, color_id, thickness_id, uvdata_id,
|
|
thickness, gpd->runtime.scolor);
|
|
idx++;
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
/* create batch geometry data for current buffer fill shader */
|
|
GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd)
|
|
{
|
|
if (gpd == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
const tGPspoint *points = gpd->runtime.sbuffer;
|
|
int totpoints = gpd->runtime.sbuffer_size;
|
|
if (totpoints < 3) {
|
|
return NULL;
|
|
}
|
|
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
Scene *scene = draw_ctx->scene;
|
|
View3D *v3d = draw_ctx->v3d;
|
|
ARegion *ar = draw_ctx->ar;
|
|
ToolSettings *ts = scene->toolsettings;
|
|
Object *ob = draw_ctx->obact;
|
|
|
|
/* get origin to reproject point */
|
|
float origin[3];
|
|
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
|
|
ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
|
|
|
|
int tot_triangles = totpoints - 2;
|
|
/* allocate memory for temporary areas */
|
|
uint (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, __func__);
|
|
float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, __func__);
|
|
|
|
/* Convert points to array and triangulate
|
|
* Here a cache is not used because while drawing the information changes all the time, so the cache
|
|
* would be recalculated constantly, so it is better to do direct calculation for each function call
|
|
*/
|
|
for (int i = 0; i < totpoints; i++) {
|
|
const tGPspoint *pt = &points[i];
|
|
points2d[i][0] = pt->x;
|
|
points2d[i][1] = pt->y;
|
|
}
|
|
BLI_polyfill_calc(points2d, (uint)totpoints, 0, tmp_triangles);
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
|
|
/* draw triangulation data */
|
|
if (tot_triangles > 0) {
|
|
GPU_vertbuf_data_alloc(vbo, tot_triangles * 3);
|
|
|
|
const tGPspoint *tpt;
|
|
bGPDspoint pt;
|
|
|
|
int idx = 0;
|
|
for (int i = 0; i < tot_triangles; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
tpt = &points[tmp_triangles[i][j]];
|
|
ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
|
|
GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt.x);
|
|
GPU_vertbuf_attr_set(vbo, color_id, idx, gpd->runtime.sfill);
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* clear memory */
|
|
if (tmp_triangles) {
|
|
MEM_freeN(tmp_triangles);
|
|
}
|
|
if (points2d) {
|
|
MEM_freeN(points2d);
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
/* create batch geometry data for stroke shader */
|
|
GPUBatch *DRW_gpencil_get_fill_geom(Object *ob, bGPDstroke *gps, const float color[4])
|
|
{
|
|
BLI_assert(gps->totpoints >= 3);
|
|
|
|
/* Calculate triangles cache for filling area (must be done only after changes) */
|
|
if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
|
|
DRW_gpencil_triangulate_stroke_fill(gps);
|
|
ED_gpencil_calc_stroke_uv(ob, gps);
|
|
}
|
|
|
|
BLI_assert(gps->tot_triangles >= 1);
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id, text_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
text_id = GPU_vertformat_attr_add(&format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, gps->tot_triangles * 3);
|
|
|
|
/* Draw all triangles for filling the polygon (cache must be calculated before) */
|
|
bGPDtriangle *stroke_triangle = gps->triangles;
|
|
int idx = 0;
|
|
for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
gpencil_set_fill_point(
|
|
vbo, idx, &gps->points[stroke_triangle->verts[j]], color, stroke_triangle->uv[j],
|
|
pos_id, color_id, text_id);
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
/* Draw selected verts for strokes being edited */
|
|
GPUBatch *DRW_gpencil_get_edit_geom(bGPDstroke *gps, float alpha, short dflag)
|
|
{
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
Object *ob = draw_ctx->obact;
|
|
bGPdata *gpd = ob->data;
|
|
bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
|
|
|
|
int vgindex = ob->actdef - 1;
|
|
if (!BLI_findlink(&ob->defbase, vgindex)) {
|
|
vgindex = -1;
|
|
}
|
|
|
|
/* Get size of verts:
|
|
* - The selected state needs to be larger than the unselected state so that
|
|
* they stand out more.
|
|
* - We use the theme setting for size of the unselected verts
|
|
*/
|
|
float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
|
|
float vsize;
|
|
if ((int)bsize > 8) {
|
|
vsize = 10.0f;
|
|
bsize = 8.0f;
|
|
}
|
|
else {
|
|
vsize = bsize + 2;
|
|
}
|
|
|
|
/* for now, we assume that the base color of the points is not too close to the real color */
|
|
float selectColor[4];
|
|
UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
|
|
selectColor[3] = alpha;
|
|
|
|
float unselectColor[4];
|
|
UI_GetThemeColor3fv(TH_GP_VERTEX, unselectColor);
|
|
unselectColor[3] = alpha;
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id, size_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
size_id = GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, gps->totpoints);
|
|
|
|
/* Draw start and end point differently if enabled stroke direction hint */
|
|
bool show_direction_hint = (dflag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
|
|
|
|
/* Draw all the stroke points (selected or not) */
|
|
bGPDspoint *pt = gps->points;
|
|
MDeformVert *dvert = gps->dvert;
|
|
|
|
int idx = 0;
|
|
float fcolor[4];
|
|
float fsize = 0;
|
|
for (int i = 0; i < gps->totpoints; i++, pt++) {
|
|
/* weight paint */
|
|
if (is_weight_paint) {
|
|
float weight = (dvert && dvert->dw) ? defvert_find_weight(dvert, vgindex) : 0.0f;
|
|
float hue = 2.0f * (1.0f - weight) / 3.0f;
|
|
hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]);
|
|
selectColor[3] = 1.0f;
|
|
copy_v4_v4(fcolor, selectColor);
|
|
fsize = vsize;
|
|
}
|
|
else {
|
|
if (show_direction_hint && i == 0) {
|
|
/* start point in green bigger */
|
|
ARRAY_SET_ITEMS(fcolor, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
fsize = vsize + 4;
|
|
}
|
|
else if (show_direction_hint && (i == gps->totpoints - 1)) {
|
|
/* end point in red smaller */
|
|
ARRAY_SET_ITEMS(fcolor, 1.0f, 0.0f, 0.0f, 1.0f);
|
|
fsize = vsize + 1;
|
|
}
|
|
else if (pt->flag & GP_SPOINT_SELECT) {
|
|
copy_v4_v4(fcolor, selectColor);
|
|
fsize = vsize;
|
|
}
|
|
else {
|
|
copy_v4_v4(fcolor, unselectColor);
|
|
fsize = bsize;
|
|
}
|
|
}
|
|
|
|
GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
|
|
GPU_vertbuf_attr_set(vbo, size_id, idx, &fsize);
|
|
GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
|
|
idx++;
|
|
if (gps->dvert != NULL) {
|
|
dvert++;
|
|
}
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
/* Draw lines for strokes being edited */
|
|
GPUBatch *DRW_gpencil_get_edlin_geom(bGPDstroke *gps, float alpha, short UNUSED(dflag))
|
|
{
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
Object *ob = draw_ctx->obact;
|
|
bGPdata *gpd = ob->data;
|
|
bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
|
|
|
|
int vgindex = ob->actdef - 1;
|
|
if (!BLI_findlink(&ob->defbase, vgindex)) {
|
|
vgindex = -1;
|
|
}
|
|
|
|
float selectColor[4];
|
|
UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
|
|
selectColor[3] = alpha;
|
|
float linecolor[4];
|
|
copy_v4_v4(linecolor, gpd->line_color);
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, gps->totpoints);
|
|
|
|
/* Draw all the stroke lines (selected or not) */
|
|
bGPDspoint *pt = gps->points;
|
|
MDeformVert *dvert = gps->dvert;
|
|
|
|
int idx = 0;
|
|
float fcolor[4];
|
|
for (int i = 0; i < gps->totpoints; i++, pt++) {
|
|
/* weight paint */
|
|
if (is_weight_paint) {
|
|
float weight = (dvert && dvert->dw) ? defvert_find_weight(dvert, vgindex) : 0.0f;
|
|
float hue = 2.0f * (1.0f - weight) / 3.0f;
|
|
hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]);
|
|
selectColor[3] = 1.0f;
|
|
copy_v4_v4(fcolor, selectColor);
|
|
}
|
|
else {
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
copy_v4_v4(fcolor, selectColor);
|
|
}
|
|
else {
|
|
copy_v4_v4(fcolor, linecolor);
|
|
}
|
|
}
|
|
|
|
GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
|
|
GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
|
|
idx++;
|
|
|
|
if (gps->dvert != NULL) {
|
|
dvert++;
|
|
}
|
|
}
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
static void set_grid_point(
|
|
GPUVertBuf *vbo, int idx, float col_grid[4],
|
|
uint pos_id, uint color_id,
|
|
float v1, float v2, int axis)
|
|
{
|
|
GPU_vertbuf_attr_set(vbo, color_id, idx, col_grid);
|
|
|
|
float pos[3];
|
|
/* Set the grid in the selected axis (default is always Y axis) */
|
|
if (axis & V3D_GP_GRID_AXIS_X) {
|
|
pos[0] = 0.0f;
|
|
pos[1] = v1;
|
|
pos[2] = v2;
|
|
}
|
|
else if (axis & V3D_GP_GRID_AXIS_Z) {
|
|
pos[0] = v1;
|
|
pos[1] = v2;
|
|
pos[2] = 0.0f;
|
|
}
|
|
else {
|
|
pos[0] = v1;
|
|
pos[1] = 0.0f;
|
|
pos[2] = v2;
|
|
}
|
|
|
|
|
|
|
|
GPU_vertbuf_attr_set(vbo, pos_id, idx, pos);
|
|
}
|
|
|
|
/* Draw grid lines */
|
|
GPUBatch *DRW_gpencil_get_grid(void)
|
|
{
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
Scene *scene = draw_ctx->scene;
|
|
ToolSettings *ts = scene->toolsettings;
|
|
View3D *v3d = draw_ctx->v3d;
|
|
|
|
float col_grid[4];
|
|
|
|
/* verify we have something to draw and valid values */
|
|
if (v3d->overlay.gpencil_grid_lines < 1) {
|
|
v3d->overlay.gpencil_grid_lines = GP_DEFAULT_GRID_LINES;
|
|
}
|
|
|
|
if (v3d->overlay.gpencil_grid_scale == 0.0f) {
|
|
v3d->overlay.gpencil_grid_scale = 1.0f;
|
|
}
|
|
|
|
if (v3d->overlay.gpencil_grid_opacity < 0.1f) {
|
|
v3d->overlay.gpencil_grid_opacity = 0.1f;
|
|
}
|
|
|
|
UI_GetThemeColor3fv(TH_GRID, col_grid);
|
|
col_grid[3] = v3d->overlay.gpencil_grid_opacity;
|
|
|
|
/* if use locked axis, copy value */
|
|
int axis = v3d->overlay.gpencil_grid_axis;
|
|
if ((v3d->overlay.gpencil_grid_axis & V3D_GP_GRID_AXIS_LOCK) == 0) {
|
|
|
|
axis = v3d->overlay.gpencil_grid_axis;
|
|
}
|
|
else {
|
|
switch (ts->gp_sculpt.lock_axis) {
|
|
case GP_LOCKAXIS_X:
|
|
{
|
|
axis = V3D_GP_GRID_AXIS_X;
|
|
break;
|
|
}
|
|
case GP_LOCKAXIS_NONE:
|
|
case GP_LOCKAXIS_Y:
|
|
{
|
|
axis = V3D_GP_GRID_AXIS_Y;
|
|
break;
|
|
}
|
|
case GP_LOCKAXIS_Z:
|
|
{
|
|
axis = V3D_GP_GRID_AXIS_Z;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *grid_unit = NULL;
|
|
const int gridlines = v3d->overlay.gpencil_grid_lines;
|
|
const float grid_scale = v3d->overlay.gpencil_grid_scale * ED_scene_grid_scale(scene, &grid_unit);
|
|
const float grid = grid_scale;
|
|
const float space = (grid_scale / gridlines);
|
|
|
|
const uint vertex_len = 2 * (gridlines * 4 + 2);
|
|
|
|
static GPUVertFormat format = { 0 };
|
|
static uint pos_id, color_id;
|
|
if (format.attr_len == 0) {
|
|
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
|
|
GPU_vertbuf_data_alloc(vbo, vertex_len);
|
|
|
|
int idx = 0;
|
|
|
|
for (int a = 1; a <= gridlines; a++) {
|
|
const float line = a * space;
|
|
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid, -line, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid, -line, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid, +line, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid, +line, axis);
|
|
idx++;
|
|
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line, -grid, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line, +grid, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line, -grid, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line, +grid, axis);
|
|
idx++;
|
|
}
|
|
/* center lines */
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid, 0.0f, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid, 0.0f, axis);
|
|
idx++;
|
|
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f, -grid, axis);
|
|
idx++;
|
|
set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f, +grid, axis);
|
|
idx++;
|
|
|
|
return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
|
|
}
|