Armature: Fix/Change bone axes display.

Now the axes are displayed correctly at the tip of the bone and with the
axes names.

I've made some modifications though:
- Axes are colored. (should not be in object mode but that's TODO)
- Axes ends are not flat arrows anymore. Replaced with a small diamond.
- Axes names are now scale by their respective axes instead of being
  affected by other axes.
- Changed axes names "font" to be a bit more sexy.
This commit is contained in:
Clément Foucault 2018-05-06 16:09:25 +02:00
parent 1a81ac7d9a
commit c472936074
Notes: blender-bot 2023-02-14 05:54:53 +01:00
Referenced by issue #54945, Armature Drawing Remaining Tasks
6 changed files with 211 additions and 4 deletions

View File

@ -224,6 +224,7 @@ data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_view_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_solid_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_solid_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_outline_vert.glsl SRC)

View File

@ -315,8 +315,7 @@ static void drw_shgroup_bone_point(
static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_axes == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_arrows_get();
g_data.bone_axes = shgroup_instance_wire(g_data.pass_bone_wire, geom);
g_data.bone_axes = shgroup_instance_bone_axes(g_data.pass_bone_wire);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);

View File

@ -2104,10 +2104,164 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
return SHC.drw_bone_point_wire;
}
static void set_bone_axis_vert(
Gwn_VertBuf *vbo, uint axis, uint pos, uint col,
unsigned int *v, const float *a, const float *p, const float *c)
{
GWN_vertbuf_attr_set(vbo, axis, *v, a);
GWN_vertbuf_attr_set(vbo, pos, *v, p);
GWN_vertbuf_attr_set(vbo, col, *v, c);
*v += 1;
}
#define S_X 0.0215f
#define S_Y 0.025f
static float x_axis_name[4][2] = {
{ 0.9f * S_X, 1.0f * S_Y}, {-1.0f * S_X, -1.0f * S_Y},
{-0.9f * S_X, 1.0f * S_Y}, { 1.0f * S_X, -1.0f * S_Y}
};
#define X_LEN (sizeof(x_axis_name) / (sizeof(float) * 2))
#undef S_X
#undef S_Y
#define S_X 0.0175f
#define S_Y 0.025f
static float y_axis_name[6][2] = {
{-1.0f * S_X, 1.0f * S_Y}, { 0.0f * S_X, -0.1f * S_Y},
{ 1.0f * S_X, 1.0f * S_Y}, { 0.0f * S_X, -0.1f * S_Y},
{ 0.0f * S_X, -0.1f * S_Y}, { 0.0f * S_X, -1.0f * S_Y}
};
#define Y_LEN (sizeof(y_axis_name) / (sizeof(float) * 2))
#undef S_X
#undef S_Y
#define S_X 0.02f
#define S_Y 0.025f
static float z_axis_name[10][2] = {
{-0.95f * S_X, 1.00f * S_Y}, { 0.95f * S_X, 1.00f * S_Y},
{ 0.95f * S_X, 1.00f * S_Y}, { 0.95f * S_X, 0.90f * S_Y},
{ 0.95f * S_X, 0.90f * S_Y}, {-1.00f * S_X, -0.90f * S_Y},
{-1.00f * S_X, -0.90f * S_Y}, {-1.00f * S_X, -1.00f * S_Y},
{-1.00f * S_X, -1.00f * S_Y}, { 1.00f * S_X, -1.00f * S_Y}
};
#define Z_LEN (sizeof(z_axis_name) / (sizeof(float) * 2))
#undef S_X
#undef S_Y
#define S_X 0.007f
#define S_Y 0.007f
static float axis_marker[8][2] = {
#if 0 /* square */
{-1.0f * S_X, 1.0f * S_Y}, { 1.0f * S_X, 1.0f * S_Y},
{ 1.0f * S_X, 1.0f * S_Y}, { 1.0f * S_X, -1.0f * S_Y},
{ 1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X, -1.0f * S_Y},
{-1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X, 1.0f * S_Y}
#else /* diamond */
{-S_X, 0.f}, { 0.f, S_Y},
{ 0.f, S_Y}, { S_X, 0.f},
{ S_X, 0.f}, { 0.f, -S_Y},
{ 0.f, -S_Y}, {-S_X, 0.f}
#endif
};
#define MARKER_LEN (sizeof(axis_marker) / (sizeof(float) * 2))
#define MARKER_FILL_LAYER 6
#undef S_X
#undef S_Y
#define S_X 0.0007f
#define S_Y 0.0007f
#define O_X 0.001f
#define O_Y -0.001f
static float axis_name_shadow[8][2] = {
{-S_X + O_X, S_Y + O_Y}, { S_X + O_X, S_Y + O_Y},
{ S_X + O_X, S_Y + O_Y}, { S_X + O_X, -S_Y + O_Y},
{ S_X + O_X, -S_Y + O_Y}, {-S_X + O_X, -S_Y + O_Y},
{-S_X + O_X, -S_Y + O_Y}, {-S_X + O_X, S_Y + O_Y}
};
// #define SHADOW_RES (sizeof(axis_name_shadow) / (sizeof(float) * 2))
#define SHADOW_RES 0
#undef O_X
#undef O_Y
#undef S_X
#undef S_Y
Gwn_Batch *DRW_cache_bone_arrows_get(void)
{
if (!SHC.drw_bone_arrows) {
Gwn_VertBuf *vbo = fill_arrows_vbo(0.25f);
/* Position Only 3D format */
static Gwn_VertFormat format = { 0 };
static struct { uint axis, pos, col; } attr_id;
if (format.attrib_ct == 0) {
attr_id.axis = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
attr_id.pos = GWN_vertformat_attr_add(&format, "screenPos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
attr_id.col = GWN_vertformat_attr_add(&format, "colorAxis", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
}
/* Line */
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
GWN_vertbuf_data_alloc(vbo, (2 + MARKER_LEN * MARKER_FILL_LAYER) * 3 +
(X_LEN + Y_LEN + Z_LEN) * (1 + SHADOW_RES));
unsigned int v = 0;
for (int axis = 0; axis < 3; axis++) {
float pos[2] = {0.0f, 0.0f};
float c[3] = {0.0f, 0.0f, 0.0f};
float a = 0.0f;
/* center to axis line */
set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, &v, &a, pos, c);
c[axis] = 0.5f;
a = axis + 0.25f;
set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, &v, &a, pos, c);
/* Axis end marker */
for (int j = 1; j < MARKER_FILL_LAYER + 1; ++j) {
for (int i = 0; i < MARKER_LEN; ++i) {
float tmp[2];
mul_v2_v2fl(tmp, axis_marker[i], j / (float)MARKER_FILL_LAYER);
set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col,
&v, &a, tmp, c);
}
}
a = axis + 0.31f;
/* Axis name */
int axis_v_ct;
float (*axis_verts)[2];
if (axis == 0) {
axis_verts = x_axis_name;
axis_v_ct = X_LEN;
}
else if (axis == 1) {
axis_verts = y_axis_name;
axis_v_ct = Y_LEN;
}
else {
axis_verts = z_axis_name;
axis_v_ct = Z_LEN;
}
/* Axis name shadows */
copy_v3_fl(c, 0.0f);
c[axis] = 0.3f;
for (int j = 0; j < SHADOW_RES; ++j) {
for (int i = 0; i < axis_v_ct; ++i) {
float tmp[2];
add_v2_v2v2(tmp, axis_verts[i], axis_name_shadow[j]);
set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col,
&v, &a, tmp, c);
}
}
/* Axis name */
copy_v3_fl(c, 0.1f);
c[axis] = 1.0f;
for (int i = 0; i < axis_v_ct; ++i) {
set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col,
&v, &a, axis_verts[i], c);
}
}
SHC.drw_bone_arrows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
}
return SHC.drw_bone_arrows;

View File

@ -153,6 +153,7 @@ void DRW_globals_update(void)
/* ********************************* SHGROUP ************************************* */
extern char datatoc_armature_axes_vert_glsl[];
extern char datatoc_armature_sphere_solid_vert_glsl[];
extern char datatoc_armature_sphere_solid_frag_glsl[];
extern char datatoc_armature_sphere_outline_vert_glsl[];
@ -171,6 +172,7 @@ extern char datatoc_object_mball_handles_vert_glsl[];
static struct {
struct GPUShader *shape_outline;
struct GPUShader *shape_solid;
struct GPUShader *bone_axes;
struct GPUShader *bone_envelope;
struct GPUShader *bone_envelope_distance;
struct GPUShader *bone_envelope_outline;
@ -435,6 +437,27 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass)
{
if (g_shaders.bone_axes == NULL) {
g_shaders.bone_axes = DRW_shader_create(
datatoc_armature_axes_vert_glsl, NULL,
datatoc_gpu_shader_flat_color_frag_glsl, NULL);
}
DRW_shgroup_instance_format(g_formats.instance_color, {
{"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
{"color" , DRW_ATTRIB_FLOAT, 4}
});
DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_axes,
pass, DRW_cache_bone_arrows_get(),
g_formats.instance_bone_outline);
DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2);
return grp;
}
DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass)
{
if (g_shaders.bone_envelope_outline == NULL) {
@ -610,7 +633,6 @@ DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass)
}
/* ******************************************** COLOR UTILS *********************************************** */
/* TODO FINISH */

View File

@ -116,6 +116,7 @@ struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn
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_mball_handles(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_axes(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_envelope_distance(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_envelope_outline(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass);

View File

@ -0,0 +1,30 @@
uniform mat4 ViewProjectionMatrix;
uniform vec3 screenVecs[3];
/* ---- Instanciated Attribs ---- */
in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */
in vec2 screenPos;
in vec3 colorAxis;
/* ---- Per instance Attribs ---- */
in mat4 InstanceModelMatrix;
in vec3 color;
flat out vec4 finalColor;
void main()
{
vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz;
vec3 y_axis = InstanceModelMatrix[1].xyz;
vec3 bone_loc = InstanceModelMatrix[3].xyz;
vec3 wpos = bone_loc + y_axis + chosen_axis * fract(axis);
vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y;
/* Scale uniformly by axis length */
spos *= length(chosen_axis);
gl_Position = ViewProjectionMatrix * vec4(wpos + spos, 1.0);
finalColor.rgb = mix(color, colorAxis, 0.9);
finalColor.a = 1.0;
}