diff --git a/src/main/java/io/eiren/gui/SkeletonConfig.java b/src/main/java/io/eiren/gui/SkeletonConfig.java index 6d8305b143..4a0272bd72 100644 --- a/src/main/java/io/eiren/gui/SkeletonConfig.java +++ b/src/main/java/io/eiren/gui/SkeletonConfig.java @@ -34,53 +34,71 @@ public void skeletonUpdated(HumanSkeleton newSkeleton) { removeAll(); int row = 0; - + + add(new TimedResetButton("Reset All", "All"), s(c(1, row, 1), 3, 1)); + row++; + add(new JLabel("Chest"), c(0, row, 1)); add(new AdjButton("+", "Chest", 0.01f), c(1, row, 1)); add(new SkeletonLabel("Chest"), c(2, row, 1)); add(new AdjButton("-", "Chest", -0.01f), c(3, row, 1)); + add(new ResetButton("Reset", "Chest"), c(4, row, 1)); row++; add(new JLabel("Waist"), c(0, row, 1)); add(new AdjButton("+", "Waist", 0.01f), c(1, row, 1)); add(new SkeletonLabel("Waist"), c(2, row, 1)); add(new AdjButton("-", "Waist", -0.01f), c(3, row, 1)); - row++; - - add(new JLabel("Virtual waist"), c(0, row, 1)); - add(new AdjButton("+", "Virtual waist", 0.01f), c(1, row, 1)); - add(new SkeletonLabel("Virtual waist"), c(2, row, 1)); - add(new AdjButton("-", "Virtual waist", -0.01f), c(3, row, 1)); + add(new TimedResetButton("Reset", "Waist"), c(4, row, 1)); row++; add(new JLabel("Hips width"), c(0, row, 1)); add(new AdjButton("+", "Hips width", 0.01f), c(1, row, 1)); add(new SkeletonLabel("Hips width"), c(2, row, 1)); add(new AdjButton("-", "Hips width", -0.01f), c(3, row, 1)); + add(new ResetButton("Reset", "Hips width"), c(4, row, 1)); row++; add(new JLabel("Hip length"), c(0, row, 1)); add(new AdjButton("+", "Hip length", 0.01f), c(1, row, 1)); add(new SkeletonLabel("Hip length"), c(2, row, 1)); add(new AdjButton("-", "Hip length", -0.01f), c(3, row, 1)); + add(new TimedResetButton("Reset", "Hip length"), c(4, row, 1)); row++; add(new JLabel("Ankle length"), c(0, row, 1)); add(new AdjButton("+", "Ankle length", 0.01f), c(1, row, 1)); add(new SkeletonLabel("Ankle length"), c(2, row, 1)); add(new AdjButton("-", "Ankle length", -0.01f), c(3, row, 1)); + add(new TimedResetButton("Reset", "Ankle length"), c(4, row, 1)); + row++; + + add(new JLabel("Foot length"), c(0, row, 1)); + add(new AdjButton("+", "Foot length", 0.01f), c(1, row, 1)); + add(new SkeletonLabel("Foot length"), c(2, row, 1)); + add(new AdjButton("-", "Foot length", -0.01f), c(3, row, 1)); + add(new ResetButton("Reset", "Foot length"), c(4, row, 1)); row++; add(new JLabel("Head offset"), c(0, row, 1)); add(new AdjButton("+", "Head", 0.01f), c(1, row, 1)); add(new SkeletonLabel("Head"), c(2, row, 1)); add(new AdjButton("-", "Head", -0.01f), c(3, row, 1)); + add(new ResetButton("Reset", "Head"), c(4, row, 1)); row++; add(new JLabel("Neck length"), c(0, row, 1)); add(new AdjButton("+", "Neck", 0.01f), c(1, row, 1)); add(new SkeletonLabel("Neck"), c(2, row, 1)); add(new AdjButton("-", "Neck", -0.01f), c(3, row, 1)); + add(new ResetButton("Reset", "Neck"), c(4, row, 1)); + row++; + + add(new JLabel("Virtual waist"), c(0, row, 1)); + add(new AdjButton("+", "Virtual waist", 0.01f), c(1, row, 1)); + add(new SkeletonLabel("Virtual waist"), c(2, row, 1)); + add(new AdjButton("-", "Virtual waist", -0.01f), c(3, row, 1)); + add(new ResetButton("Reset", "Virtual waist"), c(4, row, 1)); row++; gui.refresh(); @@ -91,13 +109,27 @@ private void change(String joint, float diff) { float current = server.humanPoseProcessor.getSkeletonConfig(joint); server.humanPoseProcessor.setSkeletonConfig(joint, current + diff); server.saveConfig(); - labels.get(joint).setText(StringUtils.prettyNumber(current + diff, 2)); + labels.get(joint).setText(StringUtils.prettyNumber((current + diff) * 100, 0)); + } + + private void reset(String joint) { + server.humanPoseProcessor.resetSkeletonConfig(joint); + server.saveConfig(); + if(!"All".equals(joint)) { + float current = server.humanPoseProcessor.getSkeletonConfig(joint); + labels.get(joint).setText(StringUtils.prettyNumber((current) * 100, 0)); + } else { + labels.forEach((jnt, label) -> { + float current = server.humanPoseProcessor.getSkeletonConfig(jnt); + label.setText(StringUtils.prettyNumber((current) * 100, 0)); + }); + } } private class SkeletonLabel extends JLabel { public SkeletonLabel(String joint) { - super(StringUtils.prettyNumber(server.humanPoseProcessor.getSkeletonConfig(joint), 2)); + super(StringUtils.prettyNumber(server.humanPoseProcessor.getSkeletonConfig(joint) * 100, 0)); labels.put(joint, this); } } @@ -114,4 +146,30 @@ public void mouseClicked(MouseEvent e) { }); } } + + private class ResetButton extends JButton { + + public ResetButton(String text, String joint) { + super(text); + addMouseListener(new MouseInputAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + reset(joint); + } + }); + } + } + + private class TimedResetButton extends JButton { + + public TimedResetButton(String text, String joint) { + super(text); + addMouseListener(new MouseInputAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + ButtonTimer.runTimer(TimedResetButton.this, 3, text, () -> reset(joint)); + } + }); + } + } } diff --git a/src/main/java/io/eiren/vr/processor/HumanPoseProcessor.java b/src/main/java/io/eiren/vr/processor/HumanPoseProcessor.java index 91e3187342..e8b53d640b 100644 --- a/src/main/java/io/eiren/vr/processor/HumanPoseProcessor.java +++ b/src/main/java/io/eiren/vr/processor/HumanPoseProcessor.java @@ -38,6 +38,12 @@ public void setSkeletonConfig(String key, float newLength) { if(skeleton != null) skeleton.setSkeletonConfig(key, newLength); } + + @ThreadSafe + public void resetSkeletonConfig(String key) { + if(skeleton != null) + skeleton.resetSkeletonConfig(key); + } @ThreadSafe public float getSkeletonConfig(String key) { diff --git a/src/main/java/io/eiren/vr/processor/HumanSekeletonWithLegs.java b/src/main/java/io/eiren/vr/processor/HumanSekeletonWithLegs.java index 5656ac4561..12e8b7ab88 100644 --- a/src/main/java/io/eiren/vr/processor/HumanSekeletonWithLegs.java +++ b/src/main/java/io/eiren/vr/processor/HumanSekeletonWithLegs.java @@ -4,6 +4,7 @@ import com.jme3.math.FastMath; import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; import io.eiren.util.ann.VRServerThread; import io.eiren.vr.VRServer; @@ -13,6 +14,10 @@ public class HumanSekeletonWithLegs extends HumanSkeleonWithWaist { + public static final float HIPS_WIDTH_DEFAULT = 0.3f; + public static final float FOOT_LENGTH_DEFAULT = 0.05f; + public static final float DEFAULT_FLOOR_OFFSET = 0.05f; + protected final float[] kneeAngles = new float[3]; protected final float[] hipAngles = new float[3]; protected final Quaternion hipBuf = new Quaternion(); @@ -39,7 +44,7 @@ public class HumanSekeletonWithLegs extends HumanSkeleonWithWaist { /** * Distance between centers of both hips */ - protected float hipsWidth = 0.30f; + protected float hipsWidth = HIPS_WIDTH_DEFAULT; /** * Length from waist to knees */ @@ -48,6 +53,7 @@ public class HumanSekeletonWithLegs extends HumanSkeleonWithWaist { * Distance from waist to ankle */ protected float ankleLength = 0.55f; + protected float footLength = FOOT_LENGTH_DEFAULT; protected float minKneePitch = 0f * FastMath.DEG_TO_RAD; protected float maxKneePitch = 90f * FastMath.DEG_TO_RAD; @@ -79,6 +85,7 @@ public HumanSekeletonWithLegs(VRServer server, List co hipsWidth = server.config.getFloat("body.hipsWidth", hipsWidth); hipsLength = server.config.getFloat("body.hipLength", hipsLength); ankleLength = server.config.getFloat("body.ankleLength", ankleLength); + footLength = server.config.getFloat("body.footLength", footLength); waistNode.attachChild(leftHipNode); leftHipNode.localTransform.setTranslation(-hipsWidth / 2, 0, 0); @@ -99,14 +106,51 @@ public HumanSekeletonWithLegs(VRServer server, List co rightAnkleNode.localTransform.setTranslation(0, -ankleLength, 0); leftAnkleNode.attachChild(leftFootNode); - leftFootNode.localTransform.setTranslation(0, 0, -0.05f); + leftFootNode.localTransform.setTranslation(0, 0, -footLength); rightAnkleNode.attachChild(rightFootNode); - rightFootNode.localTransform.setTranslation(0, 0, -0.05f); + rightFootNode.localTransform.setTranslation(0, 0, -footLength); configMap.put("Hips width", hipsWidth); configMap.put("Hip length", hipsLength); configMap.put("Ankle length", ankleLength); + configMap.put("Foot length", footLength); + } + + @Override + public void resetSkeletonConfig(String joint) { + super.resetSkeletonConfig(joint); + switch(joint) { + case "All": + // Resets from the parent already performed + resetSkeletonConfig("Hips width"); + resetSkeletonConfig("Foot length"); + resetSkeletonConfig("Ankle length"); + resetSkeletonConfig("Hip length"); + break; + case "Hips width": + setSkeletonConfig(joint, HIPS_WIDTH_DEFAULT); + break; + case "Foot length": + setSkeletonConfig(joint, FOOT_LENGTH_DEFAULT); + break; + case "Ankle length": // Ankle position is half the distance from waist to 0.05 cm above the floor + Vector3f vec = new Vector3f(); + hmdTracker.getPosition(vec); + float 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 + setSkeletonConfig(joint, (height - DEFAULT_FLOOR_OFFSET) / 4.0f); + } + break; + case "Hip length": // Hip length is the same as ankle length + vec = new Vector3f(); + 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 + setSkeletonConfig(joint, (height - DEFAULT_FLOOR_OFFSET) / 4.0f); + } + break; + } } @Override @@ -131,6 +175,12 @@ public void setSkeletonConfig(String joint, float newLength) { leftAnkleNode.localTransform.setTranslation(0, -ankleLength, 0); rightAnkleNode.localTransform.setTranslation(0, -ankleLength, 0); break; + case "Foot length": + footLength = newLength; + server.config.setProperty("body.footLength", footLength); + leftFootNode.localTransform.setTranslation(0, 0, -footLength); + rightFootNode.localTransform.setTranslation(0, 0, -footLength); + break; } } diff --git a/src/main/java/io/eiren/vr/processor/HumanSkeleonWithWaist.java b/src/main/java/io/eiren/vr/processor/HumanSkeleonWithWaist.java index aa939561fc..9f4b0d4e44 100644 --- a/src/main/java/io/eiren/vr/processor/HumanSkeleonWithWaist.java +++ b/src/main/java/io/eiren/vr/processor/HumanSkeleonWithWaist.java @@ -16,6 +16,9 @@ public class HumanSkeleonWithWaist extends HumanSkeleton { + public static final float HEAD_SHIFT_DEFAULT = 0.1f; + public static final float NECK_LENGTH_DEFAULT = 0.1f; + protected final Map configMap = new HashMap<>(); protected final VRServer server; @@ -48,11 +51,11 @@ public class HumanSkeleonWithWaist extends HumanSkeleton { /** * Distacne from eyes to the base of the neck */ - protected float neckLength = 0.1f; + protected float neckLength = NECK_LENGTH_DEFAULT; /** * Distance from eyes to ear */ - protected float headShift = 0.1f; + protected float headShift = HEAD_SHIFT_DEFAULT; public HumanSkeleonWithWaist(VRServer server, List computedTrackers) { List allTracekrs = server.getAllTrackers(); @@ -96,6 +99,39 @@ public HumanSkeleonWithWaist(VRServer server, List com configMap.put("Virtual waist", trackerWaistDistance); } + @Override + public void resetSkeletonConfig(String joint) { + switch(joint) { + case "All": // Reset all joints according to height + resetSkeletonConfig("Head"); + resetSkeletonConfig("Neck"); + resetSkeletonConfig("Virtual waist"); + resetSkeletonConfig("Waist"); + resetSkeletonConfig("Chest"); + break; + case "Head": + setSkeletonConfig(joint, HEAD_SHIFT_DEFAULT); + break; + case "Neck": + setSkeletonConfig(joint, NECK_LENGTH_DEFAULT); + break; + case "Virtual waist": + setSkeletonConfig(joint, 0.0f); + break; + case "Chest": + setSkeletonConfig(joint, waistDistance / 2.0f); + break; + case "Waist": // Puts Waist in the middle of the height + Vector3f vec = new Vector3f(); + hmdTracker.getPosition(vec); + float 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 + setSkeletonConfig(joint, (height) / 2.0f); + } + break; + } + } + @Override public Map getSkeletonConfig() { return configMap; diff --git a/src/main/java/io/eiren/vr/processor/HumanSkeleton.java b/src/main/java/io/eiren/vr/processor/HumanSkeleton.java index d12fc33d6c..1b09a0bbbf 100644 --- a/src/main/java/io/eiren/vr/processor/HumanSkeleton.java +++ b/src/main/java/io/eiren/vr/processor/HumanSkeleton.java @@ -18,6 +18,9 @@ public abstract class HumanSkeleton { @ThreadSafe public abstract void setSkeletonConfig(String key, float newLength); + + @ThreadSafe + public abstract void resetSkeletonConfig(String joint); @VRServerThread public abstract void resetTrackersFull();