Armature: More work and cleanup on envelope bones drawing.
authorClément Foucault <foucault.clem@gmail.com>
Mon, 30 Apr 2018 20:47:40 +0000 (22:47 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Wed, 2 May 2018 18:49:38 +0000 (20:49 +0200)
- 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.

source/blender/draw/CMakeLists.txt
source/blender/draw/intern/draw_armature.c
source/blender/draw/intern/draw_cache.c
source/blender/draw/intern/draw_common.c
source/blender/draw/intern/draw_common.h

index 3ccbf967b87ba5968d0fc5e7e64baec846d75bfe..0db397433e5fb592e5d7d492f21ad8d74c3ef27d 100644 (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)
index 6b685f07de1a3d7f819043b732818262e26b29f9..5a3c03d5be281f6f05ab5c06c5669a572891140e 100644 (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,24 +190,20 @@ 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_solid(
+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)
 {
-       if (g_data.bone_envelope_solid == NULL) {
-               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);
@@ -218,69 +215,121 @@ 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(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] / 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(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(g_data.bone_envelope_solid, head_sphere, tail_sphere, color, final_bonemat[0]);
+                       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] / 0.05f;
+                       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(g_data.bone_point_solid, tmp, color);
+                       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)
+{
+       if (g_data.bone_envelope_solid == NULL) {
+               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_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 *distance)
+        const float *radius_head, const float *radius_tail, const float *UNUSED(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);
+               g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.pass_bone_wire);
        }
-       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);
+       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 *distance)
+        const float *radius_head, const float *radius_tail, const float *UNUSED(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);
+       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);
-       DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, final_bonemat, color, radius_head, radius_tail, distance);
+       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(g_data.bone_point_wire, tmp, color);
+       }
+       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] / PT_DEFAULT_RAD;
+               tmp[3][3] = 1.0f;
+               copy_v3_v3(tmp[3], head_sphere);
+               DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, color);
+       }
 }
 
 /* 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);
index db0f891c730abfdacac914589d68aad6d1aff7a7..aa21bb7214a44f541caf1ca524a448df8afcc0f6 100644 (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);
index 8697d4c814ee697987c597fdde7f98bd345972f5..f108b129febf18cd44a4004f59430d6dbf346ab7 100644 (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(
index 8197474928254611c16f470ac9a9fc1e7d124dc9..656a4d7303de6b93b98e2a0d1a6fe2dc03644a53 100644 (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);