Armature: More work and cleanup on envelope bones drawing.

- Draw tail & head sphere with point shader (no needs for another way).
- Use the same function for issuing the calls for wire and solid envelope.
This commit is contained in:
Clément Foucault 2018-04-30 22:47:40 +02:00
parent a76d27f694
commit e764d2b6ba
5 changed files with 139 additions and 93 deletions

View File

@ -226,6 +226,7 @@ data_to_c_simple(modes/shaders/armature_sphere_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_outline_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_envelope_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_envelope_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_envelope_outline_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_shape_outline_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_shape_outline_geom.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC)

View File

@ -65,6 +65,8 @@
#define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var))
#define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag))
#define PT_DEFAULT_RAD 0.05f /* radius of the point batch. */
/* For now just match 2.7x where possible. */
// #define USE_SOLID_COLOR
@ -83,7 +85,6 @@ static struct {
DRWShadingGroup *bone_envelope_solid;
DRWShadingGroup *bone_envelope_distance;
DRWShadingGroup *bone_envelope_wire;
DRWShadingGroup *bone_envelope_head_wire;
DRWShadingGroup *bone_point_solid;
DRWShadingGroup *bone_point_wire;
DRWShadingGroup *bone_axes;
@ -121,7 +122,7 @@ static void drw_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const f
struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_outline_get();
g_data.bone_octahedral_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
geom = DRW_cache_bone_octahedral_get();
g_data.bone_octahedral_outline = shgroup_instance_armature_shape_outline(g_data.pass_bone_outline, geom);
g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(g_data.pass_bone_outline, geom);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@ -147,7 +148,7 @@ static void drw_shgroup_bone_box_wire(const float (*bone_mat)[4], const float co
struct Gwn_Batch *geom = DRW_cache_bone_box_wire_outline_get();
g_data.bone_box_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
geom = DRW_cache_bone_box_get();
g_data.bone_box_outline = shgroup_instance_armature_shape_outline(g_data.pass_bone_outline, geom);
g_data.bone_box_outline = shgroup_instance_bone_shape_outline(g_data.pass_bone_outline, geom);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@ -189,10 +190,77 @@ static void drw_shgroup_bone_envelope_distance(
tail_sphere[3] = *radius_tail;
tail_sphere[3] += *distance;
/* Shader transform is nicer if tail is the biggest. */
if (*radius_head > *radius_tail) {
swap_v4_v4(head_sphere, tail_sphere);
}
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, head_sphere, tail_sphere, color, final_bonemat[0]);
}
}
static void drw_shgroup_bone_envelope(
DRWShadingGroup *point, DRWShadingGroup *capsule,
const float (*bone_mat)[4], const float color[4],
const float *radius_head, const float *radius_tail)
{
float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f};
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
mul_m4_v4(final_bonemat, head_sphere);
mul_m4_v4(final_bonemat, tail_sphere);
head_sphere[3] = *radius_head;
tail_sphere[3] = *radius_tail;
if (head_sphere[3] < 0.0f) {
/* Draw Tail only */
float tmp[4][4] = {{0.0f}};
tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / PT_DEFAULT_RAD;
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], tail_sphere);
DRW_shgroup_call_dynamic_add(point, tmp, color);
}
else if (tail_sphere[3] < 0.0f) {
/* Draw Head only */
float tmp[4][4] = {{0.0f}};
tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / PT_DEFAULT_RAD;
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], head_sphere);
DRW_shgroup_call_dynamic_add(point, tmp, color);
}
else {
/* Draw Body */
float tmp_sphere[4];
float len = len_v3v3(tail_sphere, head_sphere);
/* Shader transform is nicer if tail is the biggest. */
if (*radius_head > *radius_tail) {
swap_v4_v4(head_sphere, tail_sphere);
}
float fac_head = (len - head_sphere[3]) / len;
float fac_tail = (len - tail_sphere[3]) / len;
/* Small epsilon to avoid problem with float precison in shader. */
if (len > (tail_sphere[3] + head_sphere[3]) + 1e-8f) {
copy_v4_v4(tmp_sphere, head_sphere);
interp_v4_v4v4(head_sphere, tail_sphere, head_sphere, fac_head);
interp_v4_v4v4(tail_sphere, tmp_sphere, tail_sphere, fac_tail);
DRW_shgroup_call_dynamic_add(capsule, head_sphere, tail_sphere, color, final_bonemat[0]);
}
else {
float tmp[4][4] = {{0.0f}};
float fac = max_ff(fac_head, 1.0f - fac_tail);
interp_v4_v4v4(tmp_sphere, tail_sphere, head_sphere, clamp_f(fac, 0.0f, 1.0f));
tmp[0][0] = tmp[1][1] = tmp[2][2] = tmp_sphere[3] / PT_DEFAULT_RAD;
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], tmp_sphere);
DRW_shgroup_call_dynamic_add(point, tmp, color);
}
}
}
static void drw_shgroup_bone_envelope_solid(
const float (*bone_mat)[4], const float color[4],
const float *radius_head, const float *radius_tail)
@ -204,9 +272,40 @@ static void drw_shgroup_bone_envelope_solid(
DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK);
}
if (g_data.bone_point_solid == NULL) {
g_data.bone_point_solid = shgroup_instance_armature_sphere(g_data.pass_bone_solid);
g_data.bone_point_solid = shgroup_instance_bone_sphere(g_data.pass_bone_solid);
}
drw_shgroup_bone_envelope(g_data.bone_point_solid,
g_data.bone_envelope_solid,
bone_mat, color,
radius_head, radius_tail);
}
static void drw_shgroup_bone_envelope_wire(
const float (*bone_mat)[4], const float color[4],
const float *radius_head, const float *radius_tail, const float *UNUSED(distance))
{
if (g_data.bone_envelope_wire == NULL) {
g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.pass_bone_wire);
}
if (g_data.bone_point_wire == NULL) {
g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.pass_bone_wire);
}
drw_shgroup_bone_envelope(g_data.bone_point_wire,
g_data.bone_envelope_wire,
bone_mat, color,
radius_head, radius_tail);
}
static void drw_shgroup_bone_envelope_head_wire(
const float (*bone_mat)[4], const float color[4],
const float *radius_head, const float *radius_tail, const float *UNUSED(distance))
{
if (g_data.bone_point_wire == NULL) {
g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.pass_bone_wire);
}
float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f};
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@ -218,69 +317,19 @@ static void drw_shgroup_bone_envelope_solid(
if (head_sphere[3] < 0.0f) {
/* Draw Tail only */
float tmp[4][4] = {{0.0f}};
tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / 0.05f;
tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / PT_DEFAULT_RAD;
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], tail_sphere);
DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, color);
DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, color);
}
else if (tail_sphere[3] < 0.0f) {
if (head_sphere[3] > 0.0f) {
/* Draw Head only */
float tmp[4][4] = {{0.0f}};
tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / 0.05f;
tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / PT_DEFAULT_RAD;
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], head_sphere);
DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, color);
DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, color);
}
else {
/* Draw Body */
float tmp_sphere[4];
float len = len_v3v3(tail_sphere, head_sphere);
float fac_head = (len - head_sphere[3]) / len;
float fac_tail = (len - tail_sphere[3]) / len;
/* Small epsilon to avoid problem with float precison in shader. */
if (len > (tail_sphere[3] + head_sphere[3]) + 1e-8f) {
copy_v4_v4(tmp_sphere, head_sphere);
interp_v4_v4v4(head_sphere, tail_sphere, head_sphere, fac_head);
interp_v4_v4v4(tail_sphere, tmp_sphere, tail_sphere, fac_tail);
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, head_sphere, tail_sphere, color, final_bonemat[0]);
}
else {
float tmp[4][4] = {{0.0f}};
float fac = max_ff(fac_head, 1.0f - fac_tail);
interp_v4_v4v4(tmp_sphere, tail_sphere, head_sphere, clamp_f(fac, 0.0f, 1.0f));
tmp[0][0] = tmp[1][1] = tmp[2][2] = tmp_sphere[3] / 0.05f;
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], tmp_sphere);
DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, color);
}
}
}
static void drw_shgroup_bone_envelope_wire(
const float (*bone_mat)[4], const float color[4],
const float *radius_head, const float *radius_tail, const float *distance)
{
if (g_data.bone_envelope_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_wire_outline_get();
g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, final_bonemat, color, radius_head, radius_tail, distance);
}
static void drw_shgroup_bone_envelope_head_wire(
const float (*bone_mat)[4], const float color[4],
const float *radius_head, const float *radius_tail, const float *distance)
{
if (g_data.bone_envelope_head_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_head_wire_outline_get();
g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, final_bonemat, color, radius_head, radius_tail, distance);
}
/* Custom (geometry) */
@ -313,12 +362,7 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float
static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_point_solid == NULL) {
#if 0 /* old style geometry sphere */
struct Gwn_Batch *geom = DRW_cache_bone_point_get()
g_data.bone_point_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
#else /* new style raytraced sphere */
g_data.bone_point_solid = shgroup_instance_armature_sphere(g_data.pass_bone_solid);
#endif
g_data.bone_point_solid = shgroup_instance_bone_sphere(g_data.pass_bone_solid);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@ -328,12 +372,7 @@ static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float
static void drw_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_point_wire == NULL) {
#if 0 /* old style 3 axis circles */
struct Gwn_Batch *geom = DRW_cache_bone_point_wire_outline_get();
g_data.bone_point_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
#else /* new style contour outline */
g_data.bone_point_wire = shgroup_instance_armature_sphere_outline(g_data.pass_bone_wire);
#endif
g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.pass_bone_wire);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);

View File

@ -2096,7 +2096,7 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
static struct { uint pos0, pos1; } attr_id;
if (format.attrib_ct == 0) {
attr_id.pos0 = GWN_vertformat_attr_add(&format, "pos0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
}
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);

View File

@ -158,9 +158,10 @@ void DRW_globals_update(void)
extern char datatoc_armature_sphere_vert_glsl[];
extern char datatoc_armature_sphere_frag_glsl[];
extern char datatoc_armature_sphere_outline_vert_glsl[];
extern char datatoc_armature_envelope_vert_glsl[];
extern char datatoc_armature_envelope_frag_glsl[];
extern char datatoc_armature_sphere_outline_vert_glsl[];
extern char datatoc_armature_envelope_outline_vert_glsl[];
extern char datatoc_armature_shape_outline_vert_glsl[];
extern char datatoc_armature_shape_outline_geom_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
@ -184,8 +185,7 @@ static struct {
struct Gwn_VertFormat *instance_camera;
struct Gwn_VertFormat *instance_distance_lines;
struct Gwn_VertFormat *instance_spot;
struct Gwn_VertFormat *instance_bone_envelope_wire;
struct Gwn_VertFormat *instance_bone_envelope_solid;
struct Gwn_VertFormat *instance_bone_envelope;
struct Gwn_VertFormat *instance_mball_handles;
} g_formats = {NULL};
@ -425,19 +425,25 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_Batch *geom)
DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE);
if (g_armature_shaders.bone_envelope_outline == NULL) {
g_armature_shaders.bone_envelope_outline = DRW_shader_create(
datatoc_armature_envelope_outline_vert_glsl, NULL,
datatoc_gpu_shader_flat_color_frag_glsl, NULL);
}
DRW_shgroup_instance_format(g_formats.instance_bone_envelope_wire, {
{"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
{"color" , DRW_ATTRIB_FLOAT, 4},
{"radius_head" , DRW_ATTRIB_FLOAT, 1},
{"radius_tail" , DRW_ATTRIB_FLOAT, 1},
{"distance" , DRW_ATTRIB_FLOAT, 1}
DRW_shgroup_instance_format(g_formats.instance_bone_envelope, {
{"headSphere" , DRW_ATTRIB_FLOAT, 4},
{"tailSphere" , DRW_ATTRIB_FLOAT, 4},
{"color" , DRW_ATTRIB_FLOAT, 4},
{"xAxis" , DRW_ATTRIB_FLOAT, 3}
});
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_bone_envelope_wire);
DRWShadingGroup *grp = DRW_shgroup_instance_create(g_armature_shaders.bone_envelope_outline,
pass, DRW_cache_bone_envelope_outline_get(),
g_formats.instance_bone_envelope);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
return grp;
}
@ -450,7 +456,7 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass)
datatoc_armature_envelope_frag_glsl, NULL);
}
DRW_shgroup_instance_format(g_formats.instance_bone_envelope_solid, {
DRW_shgroup_instance_format(g_formats.instance_bone_envelope, {
{"headSphere" , DRW_ATTRIB_FLOAT, 4},
{"tailSphere" , DRW_ATTRIB_FLOAT, 4},
{"color" , DRW_ATTRIB_FLOAT, 4},
@ -459,7 +465,7 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass)
DRWShadingGroup *grp = DRW_shgroup_instance_create(g_armature_shaders.bone_envelope,
pass, DRW_cache_bone_envelope_solid_get(),
g_formats.instance_bone_envelope_solid);
g_formats.instance_bone_envelope);
return grp;
}
@ -481,7 +487,7 @@ DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass, struct Gwn_Batch
}
/* Only works with batches with adjacency infos. */
DRWShadingGroup *shgroup_instance_armature_shape_outline(DRWPass *pass, struct Gwn_Batch *geom)
DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct Gwn_Batch *geom)
{
if (g_armature_shaders.shape_outline == NULL) {
g_armature_shaders.shape_outline = DRW_shader_create(
@ -504,7 +510,7 @@ DRWShadingGroup *shgroup_instance_armature_shape_outline(DRWPass *pass, struct G
return grp;
}
DRWShadingGroup *shgroup_instance_armature_sphere(DRWPass *pass)
DRWShadingGroup *shgroup_instance_bone_sphere(DRWPass *pass)
{
if (g_armature_shaders.bone_sphere == NULL) {
g_armature_shaders.bone_sphere = DRW_shader_create(
@ -524,7 +530,7 @@ DRWShadingGroup *shgroup_instance_armature_sphere(DRWPass *pass)
return grp;
}
DRWShadingGroup *shgroup_instance_armature_sphere_outline(DRWPass *pass)
DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass)
{
if (g_armature_shaders.bone_sphere_outline == NULL) {
g_armature_shaders.bone_sphere_outline = DRW_shader_create(

View File

@ -118,12 +118,12 @@ struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass, struct Gw
struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_bone_envelope_outline(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_armature_shape_outline(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_armature_sphere(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_armature_sphere_outline(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_bone_sphere(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass);
int DRW_object_wire_theme_get(
struct Object *ob, struct ViewLayer *view_layer, float **r_color);