From 89c30ff746010c73968d38ae32b9e04e2f0a8a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 3 Oct 2018 15:42:05 +0200 Subject: [PATCH] Pose Mode: Add back IK Degrees of freedom display --- source/blender/draw/CMakeLists.txt | 1 + source/blender/draw/intern/draw_armature.c | 88 +++++++++++++++++ source/blender/draw/intern/draw_cache.c | 96 +++++++++++++++++++ source/blender/draw/intern/draw_cache.h | 2 + source/blender/draw/intern/draw_common.c | 26 +++++ source/blender/draw/intern/draw_common.h | 1 + .../draw/modes/shaders/armature_dof_vert.glsl | 30 ++++++ 7 files changed, 244 insertions(+) create mode 100644 source/blender/draw/modes/shaders/armature_dof_vert.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index a2ab6383828..4f9a90ba4f0 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -263,6 +263,7 @@ 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/armature_stick_vert.glsl SRC) data_to_c_simple(modes/shaders/armature_stick_frag.glsl SRC) +data_to_c_simple(modes/shaders/armature_dof_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_common_lib.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC) diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 4eeb306c1c4..777775cf8ca 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -83,6 +83,8 @@ static struct { DRWShadingGroup *bone_box_outline; DRWShadingGroup *bone_wire; DRWShadingGroup *bone_stick; + DRWShadingGroup *bone_dof_sphere; + DRWShadingGroup *bone_dof_lines; DRWShadingGroup *bone_envelope_solid; DRWShadingGroup *bone_envelope_distance; DRWShadingGroup *bone_envelope_wire; @@ -1413,6 +1415,83 @@ static void draw_bone_octahedral( /** \} */ +/* -------------------------------------------------------------------- */ + +/** \name Draw Degrees of Freedom + * \{ */ + +static void draw_bone_dofs(bPoseChannel *pchan) +{ + float final_bonemat[4][4], posetrans[4][4], mat[4][4]; + float amin[2], amax[2], xminmax[2], zminmax[2]; + float col_sphere[4] = {0.25f, 0.25f, 0.25f, 0.25f}; + float col_lines[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + float col_xaxis[4] = {1.0f, 0.0f, 0.0f, 1.0f}; + float col_zaxis[4] = {0.0f, 0.0f, 1.0f, 1.0f}; + + if (g_data.passes.bone_envelope == NULL) { + return; + } + + if (g_data.bone_dof_sphere == NULL) { + g_data.bone_dof_lines = shgroup_instance_bone_dof(g_data.passes.bone_wire, DRW_cache_bone_dof_lines_get()); + g_data.bone_dof_sphere = shgroup_instance_bone_dof(g_data.passes.bone_envelope, DRW_cache_bone_dof_sphere_get()); + DRW_shgroup_state_enable(g_data.bone_dof_sphere, DRW_STATE_BLEND); + DRW_shgroup_state_disable(g_data.bone_dof_sphere, DRW_STATE_CULL_FRONT); + } + + /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ + xminmax[0] = sinf(pchan->limitmin[0] * 0.5f); + xminmax[1] = sinf(pchan->limitmax[0] * 0.5f); + zminmax[0] = sinf(pchan->limitmin[2] * 0.5f); + zminmax[1] = sinf(pchan->limitmax[2] * 0.5f); + + unit_m4(posetrans); + translate_m4(posetrans, pchan->pose_mat[3][0], pchan->pose_mat[3][1], pchan->pose_mat[3][2]); + /* in parent-bone pose space... */ + if (pchan->parent) { + copy_m4_m4(mat, pchan->parent->pose_mat); + mat[3][0] = mat[3][1] = mat[3][2] = 0.0f; + mul_m4_m4m4(posetrans, posetrans, mat); + } + /* ... but own restspace */ + mul_m4_m4m3(posetrans, posetrans, pchan->bone->bone_mat); + + float scale = pchan->bone->length * pchan->size[1]; + scale_m4_fl(mat, scale); + mat[1][1] = -mat[1][1]; + mul_m4_m4m4(posetrans, posetrans, mat); + + /* into world space. */ + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, posetrans); + + if ((pchan->ikflag & BONE_IK_XLIMIT) && + (pchan->ikflag & BONE_IK_ZLIMIT)) + { + amin[0] = xminmax[0]; + amax[0] = xminmax[1]; + amin[1] = zminmax[0]; + amax[1] = zminmax[1]; + DRW_shgroup_call_dynamic_add(g_data.bone_dof_sphere, final_bonemat, col_sphere, amin, amax); + DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_lines, amin, amax); + } + if (pchan->ikflag & BONE_IK_XLIMIT) { + amin[0] = xminmax[0]; + amax[0] = xminmax[1]; + amin[1] = amax[1] = 0.0f; + DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_xaxis, amin, amax); + } + if (pchan->ikflag & BONE_IK_ZLIMIT) { + amin[1] = zminmax[0]; + amax[1] = zminmax[1]; + amin[0] = amax[0] = 0.0f; + DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_zaxis, amin, amax); + } +} + +/** \} */ + + /* -------------------------------------------------------------------- */ /** \name Draw Relationships @@ -1704,6 +1783,15 @@ static void draw_armature_pose(Object *ob, const float const_color[4]) draw_bone_octahedral(NULL, pchan, arm, boneflag, constflag, select_id); } + if (!is_pose_select && show_relations && + (arm->flag & ARM_POSEMODE) && + (bone->flag & BONE_SELECTED) && + ((ob->base_flag & BASE_FROMDUPLI) == 0) && + (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_ZLIMIT))) + { + draw_bone_dofs(pchan); + } + /* Draw names of bone */ if (show_text && (arm->flag & ARM_DRAWNAMES)) { uchar color[4]; diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 6376855ed43..9f0306f32a3 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -108,6 +108,8 @@ static struct DRWShapeCache { GPUBatch *drw_bone_point_wire; GPUBatch *drw_bone_stick; GPUBatch *drw_bone_arrows; + GPUBatch *drw_bone_dof_sphere; + GPUBatch *drw_bone_dof_lines; GPUBatch *drw_camera; GPUBatch *drw_camera_frame; GPUBatch *drw_camera_tria; @@ -2698,6 +2700,100 @@ GPUBatch *DRW_cache_bone_arrows_get(void) return SHC.drw_bone_arrows; } +const float staticSine[16] = { + 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f, + 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f, + 0.743144825477f, 0.809016994375f, 0.866025403784f, + 0.913545457643f, 0.951056516295f, 0.978147600734f, + 0.994521895368f, 1.0f +}; + +#define set_vert(a, b, quarter) \ + copy_v2_fl2(pos, (quarter % 2 == 0) ? -(a) : (a), (quarter < 2) ? -(b) : (b)); \ + GPU_vertbuf_attr_set(vbo, attr_id.pos, v++, pos); + +GPUBatch *DRW_cache_bone_dof_sphere_get(void) +{ + if (!SHC.drw_bone_dof_sphere) { + int i, j, q, n = ARRAY_SIZE(staticSine); + float x, z, px, pz, pos[2]; + + /* Position Only 3D format */ + static GPUVertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attr_len == 0) { + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, n * n * 6 * 4); + + uint v = 0; + for (q = 0; q < 4; ++q) { + pz = 0.0f; + for (i = 1; i < n; ++i) { + z = staticSine[i]; + px = 0.0f; + for (j = 1; j <= (n - i); ++j) { + x = staticSine[j]; + if (j == n - i) { + set_vert(px, z, q); + set_vert(px, pz, q); + set_vert(x, pz, q); + } + else { + set_vert(x, z, q); + set_vert(x, pz, q); + set_vert(px, z, q); + + set_vert(x, pz, q); + set_vert(px, pz, q); + set_vert(px, z, q); + } + px = x; + } + pz = z; + } + } + /* TODO alloc right count from the begining. */ + GPU_vertbuf_data_resize(vbo, v); + + SHC.drw_bone_dof_sphere = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); + } + return SHC.drw_bone_dof_sphere; +} + +GPUBatch *DRW_cache_bone_dof_lines_get(void) +{ + if (!SHC.drw_bone_dof_lines) { + int i, n = ARRAY_SIZE(staticSine); + float pos[2]; + + /* Position Only 3D format */ + static GPUVertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attr_len == 0) { + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, n * 4); + + uint v = 0; + for (i = 0; i < n * 4; i++) { + float a = (1.0f - (i / (float)(n * 4))) * 2.0f * M_PI; + float x = cosf(a); + float y = sinf(a); + set_vert(x, y, 0); + } + + SHC.drw_bone_dof_lines = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO); + } + return SHC.drw_bone_dof_lines; +} + +#undef set_vert + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index f97ff34eecf..5999dc25338 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -121,6 +121,8 @@ struct GPUBatch *DRW_cache_bone_point_get(void); struct GPUBatch *DRW_cache_bone_point_wire_outline_get(void); struct GPUBatch *DRW_cache_bone_stick_get(void); struct GPUBatch *DRW_cache_bone_arrows_get(void); +struct GPUBatch *DRW_cache_bone_dof_sphere_get(void); +struct GPUBatch *DRW_cache_bone_dof_lines_get(void); /* Meshes */ struct GPUBatch *DRW_cache_mesh_surface_overlay_get(struct Object *ob); diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index de300201f1b..3e8c01bb14d 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -222,6 +222,7 @@ extern char datatoc_armature_shape_outline_vert_glsl[]; extern char datatoc_armature_shape_outline_geom_glsl[]; extern char datatoc_armature_stick_vert_glsl[]; extern char datatoc_armature_stick_frag_glsl[]; +extern char datatoc_armature_dof_vert_glsl[]; extern char datatoc_common_globals_lib_glsl[]; @@ -242,6 +243,7 @@ static struct { struct GPUShader *bone_sphere; struct GPUShader *bone_sphere_outline; struct GPUShader *bone_stick; + struct GPUShader *bone_dofs; struct GPUShader *mpath_line_sh; struct GPUShader *mpath_points_sh; @@ -265,6 +267,7 @@ static struct { struct GPUVertFormat *instance_distance_lines; struct GPUVertFormat *instance_spot; struct GPUVertFormat *instance_bone; + struct GPUVertFormat *instance_bone_dof; struct GPUVertFormat *instance_bone_stick; struct GPUVertFormat *instance_bone_outline; struct GPUVertFormat *instance_bone_envelope; @@ -784,6 +787,29 @@ DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass) return grp; } +struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct GPUBatch *geom) +{ + if (g_shaders.bone_dofs == NULL) { + g_shaders.bone_dofs = DRW_shader_create( + datatoc_armature_dof_vert_glsl, NULL, + datatoc_gpu_shader_flat_color_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_dof, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"color", DRW_ATTRIB_FLOAT, 4}, + {"amin", DRW_ATTRIB_FLOAT, 2}, + {"amax", DRW_ATTRIB_FLOAT, 2}, + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_dofs, + pass, geom, + g_formats.instance_bone_dof); + + return grp; +} + struct GPUShader *mpath_line_shader_get(void) { if (g_shaders.mpath_line_sh == NULL) { diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 206639341cf..f9e9d2adba3 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -150,6 +150,7 @@ struct DRWShadingGroup *shgroup_instance_bone_shape_solid(struct DRWPass *pass, struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass); struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass, bool transp); struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct GPUBatch *geom); struct GPUShader *mpath_line_shader_get(void); struct GPUShader *mpath_points_shader_get(void); diff --git a/source/blender/draw/modes/shaders/armature_dof_vert.glsl b/source/blender/draw/modes/shaders/armature_dof_vert.glsl new file mode 100644 index 00000000000..5c89cf644d6 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_dof_vert.glsl @@ -0,0 +1,30 @@ + +uniform mat4 ViewProjectionMatrix; + +/* ---- Instantiated Attribs ---- */ +in vec2 pos; + +/* ---- Per instance Attribs ---- */ +/* Assumed to be in world coordinate already. */ +in mat4 InstanceModelMatrix; +in vec4 color; +in vec2 amin; +in vec2 amax; + +flat out vec4 finalColor; + +vec3 sphere_project(float ax, float az) +{ + float sine = 1.0 - ax * ax - az * az; + float q3 = sqrt(max(0.0, sine)); + + return vec3(-az * q3, 0.5 - sine, ax * q3) * 2.0; +} + +void main() +{ + vec3 final_pos = sphere_project(pos.x * abs((pos.x > 0.0) ? amax.x : amin.x), + pos.y * abs((pos.y > 0.0) ? amax.y : amin.y)); + gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(final_pos, 1.0)); + finalColor = color; +}