Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern/draw_armature.c')
-rw-r--r--source/blender/draw/intern/draw_armature.c77
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(