diff --git a/src/main/java/dev/slimevr/autobone/AutoBone.java b/src/main/java/dev/slimevr/autobone/AutoBone.java index 18a43aeb2f..4990bda538 100644 --- a/src/main/java/dev/slimevr/autobone/AutoBone.java +++ b/src/main/java/dev/slimevr/autobone/AutoBone.java @@ -70,9 +70,12 @@ public String toString() { // SD of 0.07, capture 68% within range public float legBodyRatioRange = 0.07f; - // Assume these to be approximately half - public float kneeLegRatio = 0.5f; - public float chestTorsoRatio = 0.5f; + // kneeLegRatio seems to be around 0.54 to 0.6 after asking a few people in the SlimeVR discord. + public float kneeLegRatio = 0.55f; + // kneeLegRatio seems to be around 0.55 to 0.64 after asking a few people in the SlimeVR discord. TODO : Chest should be a bit shorter (0.54?) if user has an additional hip tracker. + public float chestTorsoRatio = 0.57f; + + // TODO hip tracker stuff... Hip tracker should be around 3 to 5 centimeters. protected final VRServer server; diff --git a/src/main/java/dev/slimevr/gui/SkeletonConfigGUI.java b/src/main/java/dev/slimevr/gui/SkeletonConfigGUI.java index 9d4564e641..c62a98a1c8 100644 --- a/src/main/java/dev/slimevr/gui/SkeletonConfigGUI.java +++ b/src/main/java/dev/slimevr/gui/SkeletonConfigGUI.java @@ -13,7 +13,6 @@ import dev.slimevr.gui.swing.EJBagNoStretch; import dev.slimevr.vr.processor.skeleton.HumanSkeleton; import dev.slimevr.vr.processor.skeleton.SkeletonConfigValue; -import io.eiren.util.StringUtils; import io.eiren.util.ann.ThreadSafe; public class SkeletonConfigGUI extends EJBagNoStretch { @@ -106,9 +105,9 @@ public void mouseClicked(MouseEvent e) { for (SkeletonConfigValue config : SkeletonConfigValue.values) { add(new JLabel(config.label), c(0, row, 2)); - add(new AdjButton("+", config, 0.01f), c(1, row, 2)); + add(new AdjButton("+", config, 0.005f), c(1, row, 2)); add(new SkeletonLabel(config), c(2, row, 2)); - add(new AdjButton("-", config, -0.01f), c(3, row, 2)); + add(new AdjButton("-", config, -0.005f), c(3, row, 2)); // Only use a timer on configs that need time to get into position for switch (config) { @@ -128,11 +127,15 @@ public void mouseClicked(MouseEvent e) { }); } + String getBoneLengthString(SkeletonConfigValue joint){ // Rounded to the nearest 0.5 + return ("" + Math.round(server.humanPoseProcessor.getSkeletonConfig(joint) * 200) / 2.0f); + } + @ThreadSafe public void refreshAll() { java.awt.EventQueue.invokeLater(() -> { labels.forEach((joint, label) -> { - label.setText(StringUtils.prettyNumber(server.humanPoseProcessor.getSkeletonConfig(joint) * 100, 0)); + label.setText(getBoneLengthString(joint)); }); }); } @@ -145,7 +148,7 @@ private void change(SkeletonConfigValue joint, float diff) { server.saveConfig(); // Update GUI - labels.get(joint).setText(StringUtils.prettyNumber((current + diff) * 100, 0)); + labels.get(joint).setText(getBoneLengthString(joint)); } private void reset(SkeletonConfigValue joint) { @@ -155,8 +158,7 @@ private void reset(SkeletonConfigValue joint) { server.saveConfig(); // Update GUI - float current = server.humanPoseProcessor.getSkeletonConfig(joint); - labels.get(joint).setText(StringUtils.prettyNumber((current) * 100, 0)); + labels.get(joint).setText(getBoneLengthString(joint)); } private void resetAll() { @@ -172,7 +174,7 @@ private void resetAll() { private class SkeletonLabel extends JLabel { public SkeletonLabel(SkeletonConfigValue joint) { - super(StringUtils.prettyNumber(server.humanPoseProcessor.getSkeletonConfig(joint) * 100, 0)); + super(getBoneLengthString(joint)); labels.put(joint, this); } } diff --git a/src/main/java/dev/slimevr/vr/processor/skeleton/SimpleSkeleton.java b/src/main/java/dev/slimevr/vr/processor/skeleton/SimpleSkeleton.java index 2c925f0872..e9aa842887 100644 --- a/src/main/java/dev/slimevr/vr/processor/skeleton/SimpleSkeleton.java +++ b/src/main/java/dev/slimevr/vr/processor/skeleton/SimpleSkeleton.java @@ -20,9 +20,7 @@ import io.eiren.util.collections.FastList; public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallback { - - public static final float DEFAULT_FLOOR_OFFSET = 0.05f; - + //#region Upper body nodes (torso) protected final TransformNode hmdNode = new TransformNode("HMD", false); protected final TransformNode headNode = new TransformNode("Head", false); @@ -810,14 +808,14 @@ public void resetSkeletonConfig(SkeletonConfigValue config) { hmdTracker.getPosition(vec); height = vec.y; if(height > 0.5f) { // Reset only if floor level is right, TODO: read floor level from SteamVR if it's not 0 - skeletonConfig.setConfig(SkeletonConfigValue.TORSO, ((height) / 2.0f) - skeletonConfig.getConfig(SkeletonConfigValue.NECK)); + skeletonConfig.setConfig(SkeletonConfigValue.TORSO, ((height) * 0.42f) - skeletonConfig.getConfig(SkeletonConfigValue.NECK)); } else// if floor level is incorrect { skeletonConfig.setConfig(SkeletonConfigValue.TORSO, null); } break; - case CHEST: //Chest is roughly half of the upper body (shoulders to chest) - skeletonConfig.setConfig(SkeletonConfigValue.CHEST, skeletonConfig.getConfig(SkeletonConfigValue.TORSO) / 2.0f); + case CHEST: //Chest is 57% of the upper body by default (shoulders to chest) + skeletonConfig.setConfig(SkeletonConfigValue.CHEST, skeletonConfig.getConfig(SkeletonConfigValue.TORSO) * 0.57f); break; case WAIST: // waist length is from hips to waist skeletonConfig.setConfig(SkeletonConfigValue.WAIST, null); @@ -842,15 +840,15 @@ public void resetSkeletonConfig(SkeletonConfigValue config) { hmdTracker.getPosition(vec); height = vec.y; if(height > 0.5f) { // Reset only if floor level is right, todo: read floor level from SteamVR if it's not 0 - skeletonConfig.setConfig(SkeletonConfigValue.LEGS_LENGTH, height - skeletonConfig.getConfig(SkeletonConfigValue.NECK) - skeletonConfig.getConfig(SkeletonConfigValue.TORSO) - DEFAULT_FLOOR_OFFSET); + skeletonConfig.setConfig(SkeletonConfigValue.LEGS_LENGTH, height - skeletonConfig.getConfig(SkeletonConfigValue.NECK) - skeletonConfig.getConfig(SkeletonConfigValue.TORSO) - 0.05f); } else //if floor level is incorrect { skeletonConfig.setConfig(SkeletonConfigValue.LEGS_LENGTH, null); } resetSkeletonConfig(SkeletonConfigValue.KNEE_HEIGHT); break; - case KNEE_HEIGHT: // Knees are at 50% of the legs by default - skeletonConfig.setConfig(SkeletonConfigValue.KNEE_HEIGHT, skeletonConfig.getConfig(SkeletonConfigValue.LEGS_LENGTH) / 2.0f); + case KNEE_HEIGHT: // Knees are at 55% of the legs by default + skeletonConfig.setConfig(SkeletonConfigValue.KNEE_HEIGHT, skeletonConfig.getConfig(SkeletonConfigValue.LEGS_LENGTH) * 0.55f); break; case CONTROLLER_DISTANCE_Z: skeletonConfig.setConfig(SkeletonConfigValue.CONTROLLER_DISTANCE_Z, null); diff --git a/src/main/java/dev/slimevr/vr/processor/skeleton/SkeletonConfigValue.java b/src/main/java/dev/slimevr/vr/processor/skeleton/SkeletonConfigValue.java index 741982cee0..2c948ec5f9 100644 --- a/src/main/java/dev/slimevr/vr/processor/skeleton/SkeletonConfigValue.java +++ b/src/main/java/dev/slimevr/vr/processor/skeleton/SkeletonConfigValue.java @@ -7,19 +7,19 @@ public enum SkeletonConfigValue { HEAD("Head", "headShift", "Head shift", 0.1f, new SkeletonNodeOffset[]{SkeletonNodeOffset.HEAD}), NECK("Neck", "neckLength", "Neck length", 0.1f, new SkeletonNodeOffset[]{SkeletonNodeOffset.NECK}), - TORSO("Torso", "torsoLength", "Torso length", 0.6f, new SkeletonNodeOffset[]{SkeletonNodeOffset.WAIST}), - CHEST("Chest", "chestDistance", "Chest distance", 0.3f, new SkeletonNodeOffset[]{SkeletonNodeOffset.CHEST, SkeletonNodeOffset.WAIST}), - WAIST("Waist", "waistDistance", "Waist distance", 0.05f, new SkeletonNodeOffset[]{SkeletonNodeOffset.WAIST, SkeletonNodeOffset.HIP}), + TORSO("Torso", "torsoLength", "Torso length", 0.56f, new SkeletonNodeOffset[]{SkeletonNodeOffset.WAIST}), + CHEST("Chest", "chestDistance", "Chest distance", 0.32f, new SkeletonNodeOffset[]{SkeletonNodeOffset.CHEST, SkeletonNodeOffset.WAIST}), + WAIST("Waist", "waistDistance", "Waist distance", 0.04f, new SkeletonNodeOffset[]{SkeletonNodeOffset.WAIST, SkeletonNodeOffset.HIP}), HIP_OFFSET("Hip offset", "hipOffset", "Hip offset", 0.0f, new SkeletonNodeOffset[]{SkeletonNodeOffset.HIP_TRACKER}), - HIPS_WIDTH("Hips width", "hipsWidth", "Hips width", 0.28f, new SkeletonNodeOffset[]{SkeletonNodeOffset.LEFT_HIP, SkeletonNodeOffset.RIGHT_HIP}), - LEGS_LENGTH("Legs length", "legsLength", "Legs length", 0.88f, new SkeletonNodeOffset[]{SkeletonNodeOffset.KNEE}), - KNEE_HEIGHT("Knee height", "kneeHeight", "Knee height", 0.44f, new SkeletonNodeOffset[]{SkeletonNodeOffset.KNEE, SkeletonNodeOffset.ANKLE}), + HIPS_WIDTH("Hips width", "hipsWidth", "Hips width", 0.26f, new SkeletonNodeOffset[]{SkeletonNodeOffset.LEFT_HIP, SkeletonNodeOffset.RIGHT_HIP}), + LEGS_LENGTH("Legs length", "legsLength", "Legs length", 0.92f, new SkeletonNodeOffset[]{SkeletonNodeOffset.KNEE}), + KNEE_HEIGHT("Knee height", "kneeHeight", "Knee height", 0.50f, new SkeletonNodeOffset[]{SkeletonNodeOffset.KNEE, SkeletonNodeOffset.ANKLE}), FOOT_LENGTH("Foot length", "footLength", "Foot length", 0.05f, new SkeletonNodeOffset[]{SkeletonNodeOffset.FOOT}), - FOOT_OFFSET("Foot offset", "footOffset", "Foot offset", 0.0f, new SkeletonNodeOffset[]{SkeletonNodeOffset.ANKLE}), + FOOT_OFFSET("Foot offset", "footOffset", "Foot offset", -0.05f, new SkeletonNodeOffset[]{SkeletonNodeOffset.ANKLE}), SKELETON_OFFSET("Skeleton offset", "skeletonOffset", "Skeleton offset", 0.0f, new SkeletonNodeOffset[]{SkeletonNodeOffset.CHEST_TRACKER, SkeletonNodeOffset.HIP_TRACKER, SkeletonNodeOffset.KNEE_TRACKER, SkeletonNodeOffset.FOOT_TRACKER}), CONTROLLER_DISTANCE_Z("Controller distance z", "controllerDistanceZ", "Controller distance z", 0.15f, new SkeletonNodeOffset[]{SkeletonNodeOffset.HAND}), CONTROLLER_DISTANCE_Y("Controller distance y", "controllerDistanceY", "Controller distance y", 0.05f, new SkeletonNodeOffset[]{SkeletonNodeOffset.HAND}), - ELBOW_DISTANCE("Elbow distance", "elbowDistance", "Elbow distance", 0.22f, new SkeletonNodeOffset[]{SkeletonNodeOffset.ELBOW}), + ELBOW_DISTANCE("Elbow distance", "elbowDistance", "Elbow distance", 0.24f, new SkeletonNodeOffset[]{SkeletonNodeOffset.ELBOW}), ; private static final String CONFIG_PREFIX = "body.";