diff options
Diffstat (limited to 'source/blender/draw/intern/draw_armature.c')
-rw-r--r-- | source/blender/draw/intern/draw_armature.c | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 756cc3e6992..6b685f07de1 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -95,6 +95,9 @@ static struct { DRWPass *pass_bone_envelope; } g_data = {NULL}; +/* Prototype */ +static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4]); + /* -------------------------------------------------------------------- */ /** \name Shader Groups (DRW_shgroup) @@ -171,13 +174,22 @@ static void drw_shgroup_bone_envelope_distance( { if (g_data.pass_bone_envelope != NULL) { if (g_data.bone_envelope_distance == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_envelope_distance_outline_get(); - /* Note: bone_wire draw pass is not really working, think we need another one here? */ - g_data.bone_envelope_distance = shgroup_instance_bone_envelope_wire(g_data.pass_bone_envelope, geom); + g_data.bone_envelope_distance = shgroup_instance_bone_envelope_solid(g_data.pass_bone_envelope); + /* pass_bone_envelope should have the DRW_STATE_CULL_FRONT state enabled. */ } + 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); - DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, final_bonemat, color, radius_head, radius_tail, distance); + /* We need matrix mul because we need shear applied. */ + /* NOTE: could be done in shader if that becomes a bottleneck. */ + mul_m4_v4(final_bonemat, head_sphere); + mul_m4_v4(final_bonemat, tail_sphere); + head_sphere[3] = *radius_head; + head_sphere[3] += *distance; + tail_sphere[3] = *radius_tail; + tail_sphere[3] += *distance; + + DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, head_sphere, tail_sphere, color, final_bonemat[0]); } } @@ -186,12 +198,63 @@ static void drw_shgroup_bone_envelope_solid( const float *radius_head, const float *radius_tail) { if (g_data.bone_envelope_solid == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_envelope_solid_get(); - g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid, geom); + g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid); + /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to + * inverted matrix. */ + 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); } + + 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); - DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, final_bonemat, color, radius_head, radius_tail); + 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] / 0.05f; + tmp[3][3] = 1.0f; + copy_v3_v3(tmp[3], tail_sphere); + DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, 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] / 0.05f; + tmp[3][3] = 1.0f; + copy_v3_v3(tmp[3], head_sphere); + DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, 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( |