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/engines/overlay/overlay_armature.c')
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c196
1 files changed, 166 insertions, 30 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index 4029f1237e8..f9694b329aa 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -191,20 +191,17 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.point_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_disable(grp, DRW_STATE_WRITE_DEPTH);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", wire_alpha * 0.4f);
cb->transp.point_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
sh = OVERLAY_shader_armature_shape(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.custom_fill = grp;
cb->solid.box_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@@ -213,7 +210,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_disable(grp, DRW_STATE_WRITE_DEPTH);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", wire_alpha * 0.6f);
cb->transp.custom_fill = grp;
cb->transp.box_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@@ -335,7 +331,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", false);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.envelope_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -371,7 +366,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_transp_ps);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", true);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
@@ -2044,6 +2038,128 @@ static void draw_bone_name(ArmatureDrawContext *ctx,
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Pose Bone Culling
+ *
+ * Used for selection since drawing many bones can be slow, see: T91253.
+ *
+ * Bounding spheres are used with margins added to ensure bones are included.
+ * An added margin is needed because #BKE_pchan_minmax only returns the bounds
+ * of the bones head & tail which doesn't account for parts of the bone users may select
+ * (octahedral spheres or envelope radius for example).
+ * \{ */
+
+static void pchan_culling_calc_bsphere(const Object *ob,
+ const bPoseChannel *pchan,
+ BoundSphere *r_bsphere)
+{
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ BKE_pchan_minmax(ob, pchan, min, max);
+ mid_v3_v3v3(r_bsphere->center, min, max);
+ r_bsphere->radius = len_v3v3(min, r_bsphere->center);
+}
+
+/**
+ * \return true when bounding sphere from `pchan` intersect the view.
+ * (same for other "test" functions defined here).
+ */
+static bool pchan_culling_test_simple(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan)
+{
+ BoundSphere bsphere;
+ pchan_culling_calc_bsphere(ob, pchan, &bsphere);
+ return DRW_culling_sphere_test(view, &bsphere);
+}
+
+static bool pchan_culling_test_with_radius_scale(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan,
+ const float scale)
+{
+ BoundSphere bsphere;
+ pchan_culling_calc_bsphere(ob, pchan, &bsphere);
+ bsphere.radius *= scale;
+ return DRW_culling_sphere_test(view, &bsphere);
+}
+
+static bool pchan_culling_test_custom(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan)
+{
+ /* For more aggressive culling the bounding box of the custom-object could be used. */
+ return pchan_culling_test_simple(view, ob, pchan);
+}
+
+static bool pchan_culling_test_wire(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan)
+{
+ BLI_assert(((const bArmature *)ob->data)->drawtype == ARM_WIRE);
+ return pchan_culling_test_simple(view, ob, pchan);
+}
+
+static bool pchan_culling_test_line(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan)
+{
+ BLI_assert(((const bArmature *)ob->data)->drawtype == ARM_LINE);
+ /* Account for the end-points, as the line end-points size is in pixels, this is a rough value.
+ * Since the end-points are small the difference between having any margin or not is unlikely
+ * to be noticeable. */
+ const float scale = 1.1f;
+ return pchan_culling_test_with_radius_scale(view, ob, pchan, scale);
+}
+
+static bool pchan_culling_test_envelope(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan)
+{
+ const bArmature *arm = ob->data;
+ BLI_assert(arm->drawtype == ARM_ENVELOPE);
+ UNUSED_VARS_NDEBUG(arm);
+ BoundSphere bsphere;
+ pchan_culling_calc_bsphere(ob, pchan, &bsphere);
+ bsphere.radius += max_ff(pchan->bone->rad_head, pchan->bone->rad_tail) *
+ mat4_to_size_max_axis(ob->obmat) * mat4_to_size_max_axis(pchan->disp_mat);
+ return DRW_culling_sphere_test(view, &bsphere);
+}
+
+static bool pchan_culling_test_bbone(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan)
+{
+ const bArmature *arm = ob->data;
+ BLI_assert(arm->drawtype == ARM_B_BONE);
+ UNUSED_VARS_NDEBUG(arm);
+ const float ob_scale = mat4_to_size_max_axis(ob->obmat);
+ const Mat4 *bbones_mat = (const Mat4 *)pchan->draw_data->bbone_matrix;
+ for (int i = pchan->bone->segments; i--; bbones_mat++) {
+ BoundSphere bsphere;
+ float size[3];
+ mat4_to_size(size, bbones_mat->mat);
+ copy_v3_v3(bsphere.center, bbones_mat->mat[3]);
+ bsphere.radius = len_v3(size) * ob_scale;
+ if (DRW_culling_sphere_test(view, &bsphere)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool pchan_culling_test_octohedral(const DRWView *view,
+ const Object *ob,
+ const bPoseChannel *pchan)
+{
+ /* No type assertion as this is a fallback (files from the future will end up here). */
+ /* Account for spheres on the end-points. */
+ const float scale = 1.2f;
+ return pchan_culling_test_with_radius_scale(view, ob, pchan, scale);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Main Draw Loops
* \{ */
@@ -2084,7 +2200,9 @@ static void draw_armature_edit(ArmatureDrawContext *ctx)
boneflag &= ~BONE_DRAW_LOCKED_WEIGHT;
- draw_bone_relations(ctx, eBone, NULL, arm, boneflag, constflag);
+ if (!is_select) {
+ draw_bone_relations(ctx, eBone, NULL, arm, boneflag, constflag);
+ }
if (arm->drawtype == ARM_ENVELOPE) {
draw_bone_update_disp_matrix_default(eBone, NULL);
@@ -2107,12 +2225,14 @@ static void draw_armature_edit(ArmatureDrawContext *ctx)
draw_bone_octahedral(ctx, eBone, NULL, arm, boneflag, constflag, select_id);
}
- if (show_text && (arm->flag & ARM_DRAWNAMES)) {
- draw_bone_name(ctx, eBone, NULL, arm, boneflag);
- }
+ if (!is_select) {
+ if (show_text && (arm->flag & ARM_DRAWNAMES)) {
+ draw_bone_name(ctx, eBone, NULL, arm, boneflag);
+ }
- if (arm->flag & ARM_DRAWAXES) {
- draw_axes(ctx, eBone, NULL, arm);
+ if (arm->flag & ARM_DRAWAXES) {
+ draw_axes(ctx, eBone, NULL, arm);
+ }
}
}
}
@@ -2187,6 +2307,8 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
}
}
+ const DRWView *view = is_pose_select ? DRW_view_default_get() : NULL;
+
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next, index += 0x10000) {
Bone *bone = pchan->bone;
const bool bone_visible = (bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0;
@@ -2221,43 +2343,60 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
boneflag &= ~BONE_DRAW_LOCKED_WEIGHT;
}
- draw_bone_relations(ctx, NULL, pchan, arm, boneflag, constflag);
+ if (!is_pose_select) {
+ draw_bone_relations(ctx, NULL, pchan, arm, boneflag, constflag);
+ }
if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
draw_bone_update_disp_matrix_custom(pchan);
- draw_bone_custom_shape(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ if (!is_pose_select || pchan_culling_test_custom(view, ob, pchan)) {
+ draw_bone_custom_shape(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ }
}
else if (arm->drawtype == ARM_ENVELOPE) {
draw_bone_update_disp_matrix_default(NULL, pchan);
- draw_bone_envelope(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ if (!is_pose_select || pchan_culling_test_envelope(view, ob, pchan)) {
+ draw_bone_envelope(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ }
}
else if (arm->drawtype == ARM_LINE) {
draw_bone_update_disp_matrix_default(NULL, pchan);
- draw_bone_line(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ if (!is_pose_select || pchan_culling_test_line(view, ob, pchan)) {
+ draw_bone_line(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ }
}
else if (arm->drawtype == ARM_WIRE) {
draw_bone_update_disp_matrix_bbone(NULL, pchan);
- draw_bone_wire(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ if (!is_pose_select || pchan_culling_test_wire(view, ob, pchan)) {
+ draw_bone_wire(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ }
}
else if (arm->drawtype == ARM_B_BONE) {
draw_bone_update_disp_matrix_bbone(NULL, pchan);
- draw_bone_box(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ if (!is_pose_select || pchan_culling_test_bbone(view, ob, pchan)) {
+ draw_bone_box(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ }
}
else {
draw_bone_update_disp_matrix_default(NULL, pchan);
- draw_bone_octahedral(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ if (!is_pose_select || pchan_culling_test_octohedral(view, ob, pchan)) {
+ draw_bone_octahedral(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
+ }
}
- if (draw_dofs) {
- draw_bone_degrees_of_freedom(ctx, pchan);
- }
+ /* These aren't included in the selection. */
+ if (!is_pose_select) {
+ if (draw_dofs) {
+ draw_bone_degrees_of_freedom(ctx, pchan);
+ }
- if (show_text && (arm->flag & ARM_DRAWNAMES)) {
- draw_bone_name(ctx, NULL, pchan, arm, boneflag);
- }
+ if (show_text && (arm->flag & ARM_DRAWNAMES)) {
+ draw_bone_name(ctx, NULL, pchan, arm, boneflag);
+ }
- if (arm->flag & ARM_DRAWAXES) {
- draw_axes(ctx, NULL, pchan, arm);
+ if (arm->flag & ARM_DRAWAXES) {
+ draw_axes(ctx, NULL, pchan, arm);
+ }
}
}
}
@@ -2365,9 +2504,6 @@ static bool POSE_is_driven_by_active_armature(Object *ob)
if (ob_arm) {
const DRWContextState *draw_ctx = DRW_context_state_get();
bool is_active = OVERLAY_armature_is_pose_mode(ob_arm, draw_ctx);
- if (!is_active && ob_arm->proxy_from) {
- is_active = OVERLAY_armature_is_pose_mode(ob_arm->proxy_from, draw_ctx);
- }
return is_active;
}