GPU_batch: Add GPU_batch_wire_from_poly_2d_encoded

Draws wire around polygon shapes:
better visibility w/ any background color.
This commit is contained in:
Campbell Barton 2018-01-20 18:41:11 +11:00
parent e969ac6413
commit a3716f5945
4 changed files with 138 additions and 17 deletions

View File

@ -69,7 +69,7 @@ typedef struct ButtonManipulator2D {
bool is_init;
/* Use an icon or shape */
int icon;
Gwn_Batch *shape_batch;
Gwn_Batch *shape_batch[2];
} ButtonManipulator2D;
#define CIRCLE_RESOLUTION 32
@ -114,7 +114,8 @@ static void button2d_draw_intern(
/* We shouldn't need the +1, but a NULL char is set. */
char *polys = MEM_mallocN(polys_len + 1, __func__);
RNA_property_string_get(mpr->ptr, prop, polys);
button->shape_batch = GPU_batch_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
button->shape_batch[0] = GPU_batch_tris_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
button->shape_batch[1] = GPU_batch_wire_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
MEM_freeN(polys);
}
}
@ -131,11 +132,21 @@ static void button2d_draw_intern(
glEnable(GL_BLEND);
if (select == false) {
if (button->shape_batch != NULL) {
if (button->shape_batch[0] != NULL) {
glEnable(GL_POLYGON_SMOOTH);
GWN_batch_program_set_builtin(button->shape_batch, GPU_SHADER_2D_UNIFORM_COLOR);
GWN_batch_uniform_4f(button->shape_batch, "color", UNPACK4(color));
GWN_batch_draw(button->shape_batch);
glEnable(GL_LINE_SMOOTH);
glLineWidth(1.0f);
for (uint i = 0; i < ARRAY_SIZE(button->shape_batch) && button->shape_batch[i]; i++) {
GWN_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR);
GWN_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
GWN_batch_draw(button->shape_batch[i]);
if (i == 0) {
/* Invert line color. */
color[0] = 1.0f - color[0];
color[1] = 1.0f - color[1];
color[2] = 1.0f - color[2];
}
}
glDisable(GL_POLYGON_SMOOTH);
gpuPopMatrix();
}
@ -203,7 +214,10 @@ static int manipulator_button2d_cursor_get(wmManipulator *UNUSED(mpr))
static void manipulator_button2d_free(wmManipulator *mpr)
{
ButtonManipulator2D *shape = (ButtonManipulator2D *)mpr;
GWN_BATCH_DISCARD_SAFE(shape->shape_batch);
for (uint i = 0; i < ARRAY_SIZE(shape->shape_batch); i++) {
GWN_BATCH_DISCARD_SAFE(shape->shape_batch[i]);
}
}
/** \} */

View File

@ -201,6 +201,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
mpr->ptr, prop,
(const char *)info->shape, info->shape_size);
/* don't fade icons so much */
copy_v3_fl(mpr->color, 0.0f);
mpr->color[3] = 0.5f;
}

View File

@ -47,7 +47,10 @@ struct rctf;
/* gpu_batch.c */
void GWN_batch_program_set_builtin(Gwn_Batch *batch, GPUBuiltinShader shader_id) ATTR_NONNULL(1);
Gwn_Batch *GPU_batch_from_poly_2d_encoded(
Gwn_Batch *GPU_batch_tris_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect
) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect
) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);

View File

@ -35,6 +35,7 @@
#include "BLI_rect.h"
#include "BLI_math.h"
#include "BLI_polyfill2d.h"
#include "BLI_sort_utils.h"
#include "GPU_batch.h" /* own include */
@ -67,11 +68,11 @@ void GWN_batch_program_set_builtin(Gwn_Batch *batch, GPUBuiltinShader shader_id)
* \param polys_flat_len: Length of the array (must be an even number).
* \param rect: Optional region to map the byte 0..255 coords to. When not set use -1..1.
*/
Gwn_Batch *GPU_batch_from_poly_2d_encoded(
Gwn_Batch *GPU_batch_tris_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
{
uchar (*polys)[2] = (void *)polys_flat;
uint polys_len = polys_flat_len / 2;
const uchar (*polys)[2] = (const void *)polys_flat;
const uint polys_len = polys_flat_len / 2;
BLI_assert(polys_flat_len == polys_len * 2);
/* Over alloc in both cases */
@ -100,10 +101,10 @@ Gwn_Batch *GPU_batch_from_poly_2d_encoded(
if (polys[i_poly - 1][0] == polys[i_poly][0] &&
polys[i_poly - 1][1] == polys[i_poly][1])
{
const uint verts_len = (&verts[i_vert]) - verts_step;
BLI_assert(verts_len >= 3);
const uint tris_len = (verts_len - 2);
BLI_polyfill_calc(verts_step, verts_len, -1, tris_step);
const uint verts_step_len = (&verts[i_vert]) - verts_step;
BLI_assert(verts_step_len >= 3);
const uint tris_len = (verts_step_len - 2);
BLI_polyfill_calc(verts_step, verts_step_len, -1, tris_step);
/* offset indices */
if (verts_step != verts) {
uint *t = tris_step[0];
@ -115,8 +116,8 @@ Gwn_Batch *GPU_batch_from_poly_2d_encoded(
}
BLI_assert(t == tris_step[tris_len]);
}
verts_step += verts_len;
tris_step += (verts_len - 2);
verts_step += verts_step_len;
tris_step += tris_len;
i_poly++;
/* ignore the duplicate point */
}
@ -157,6 +158,108 @@ Gwn_Batch *GPU_batch_from_poly_2d_encoded(
GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
}
Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
{
const uchar (*polys)[2] = (const void *)polys_flat;
const uint polys_len = polys_flat_len / 2;
BLI_assert(polys_flat_len == polys_len * 2);
/* Over alloc */
int32_t *lines = MEM_mallocN(sizeof(*lines) * polys_len, __func__);
int32_t *lines_step = lines;
const float range_uchar[2] = {
(rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f,
(rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f,
};
const float min_uchar[2] = {
(rect ? rect->xmin : -1.0f),
(rect ? rect->ymin : -1.0f),
};
const bool hide_lines = true;
uint i_poly_prev = 0;
uint i_poly = 0;
while (i_poly != polys_len) {
i_poly++;
if (polys[i_poly - 1][0] == polys[i_poly][0] &&
polys[i_poly - 1][1] == polys[i_poly][1])
{
const uchar (*polys_step)[2] = polys + i_poly_prev;
const uint polys_step_len = i_poly - i_poly_prev;
BLI_assert(polys_step_len >= 2);
for (uint i_prev = polys_step_len - 1, i = 0; i < polys_step_len; i_prev = i++) {
union {
uint8_t as_u8[4];
uint16_t as_u16[2];
uint32_t as_u32;
} data;
data.as_u16[0] = *((const uint16_t *)polys_step[i_prev]);
data.as_u16[1] = *((const uint16_t *)polys_step[i]);
if (data.as_u16[0] > data.as_u16[1]) {
SWAP(uint16_t, data.as_u16[0], data.as_u16[1]);
}
*lines_step = data.as_u32;
lines_step++;
}
i_poly++;
i_poly_prev = i_poly;
/* ignore the duplicate point */
}
}
uint lines_len = (lines_step - lines);
uint lines_hide_len = 0;
if (hide_lines) {
qsort(lines, lines_len, sizeof(int32_t), BLI_sortutil_cmp_int);
for (uint i_prev = 0, i = 1; i < lines_len; i_prev = i++) {
if ((lines[i] == lines[i_prev])) {
lines_hide_len++;
}
}
}
/* We have vertices and tris, make a batch from this. */
static Gwn_VertFormat format = {0};
static struct { uint pos; } attr_id;
if (format.attrib_ct == 0) {
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
}
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
GWN_vertbuf_data_alloc(vbo, (lines_len - lines_hide_len) * 2);
Gwn_VertBufRaw pos_step;
GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
for (uint i = 0; i < lines_len; i++) {
if (hide_lines) {
if ((i + 1 != lines_len) && (lines[i + 1] == lines[i])) {
i++;
continue;
}
}
union {
uint8_t as_u8_pair[2][2];
uint32_t as_u32;
} data;
data.as_u32 = lines[i];
for (uint k = 0; k < 2; k++) {
float *pos_v2 = GWN_vertbuf_raw_step(&pos_step);
for (uint j = 0; j < 2; j++) {
pos_v2[j] = min_uchar[j] + ((float)data.as_u8_pair[k][j] * range_uchar[j]);
}
}
}
MEM_freeN(lines);
return GWN_batch_create_ex(
GWN_PRIM_LINES, vbo,
NULL,
GWN_BATCH_OWNS_VBO);
}
/** \} */
/* -------------------------------------------------------------------- */