mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 08:43:47 +02:00
Improved hand controller reticle movement
This commit is contained in:
parent
890b39f04b
commit
36beea17fa
1 changed files with 24 additions and 168 deletions
|
@ -22,33 +22,13 @@ function length(posA, posB) {
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
var EXPECTED_CHANGE = 50;
|
|
||||||
var lastPos = Controller.getReticlePosition();
|
|
||||||
function moveReticleAbsolute(x, y) {
|
function moveReticleAbsolute(x, y) {
|
||||||
var globalPos = Controller.getReticlePosition();
|
var globalPos = Controller.getReticlePosition();
|
||||||
var dX = x - globalPos.x;
|
|
||||||
var dY = y - globalPos.y;
|
|
||||||
|
|
||||||
// some debugging to see if position is jumping around on us...
|
|
||||||
var distanceSinceLastMove = length(lastPos, globalPos);
|
|
||||||
if (distanceSinceLastMove > EXPECTED_CHANGE) {
|
|
||||||
debugPrint("------------------ distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.abs(dX) > EXPECTED_CHANGE) {
|
|
||||||
debugPrint("surpressing unexpectedly large change dX:" + dX + "----------------------------");
|
|
||||||
}
|
|
||||||
if (Math.abs(dY) > EXPECTED_CHANGE) {
|
|
||||||
debugPrint("surpressing unexpectedly large change dY:" + dY + "----------------------------");
|
|
||||||
}
|
|
||||||
|
|
||||||
globalPos.x = x;
|
globalPos.x = x;
|
||||||
globalPos.y = y;
|
globalPos.y = y;
|
||||||
Controller.setReticlePosition(globalPos);
|
Controller.setReticlePosition(globalPos);
|
||||||
lastPos = globalPos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var MAPPING_NAME = "com.highfidelity.testing.reticleWithHandRotation";
|
var MAPPING_NAME = "com.highfidelity.testing.reticleWithHandRotation";
|
||||||
var mapping = Controller.newMapping(MAPPING_NAME);
|
var mapping = Controller.newMapping(MAPPING_NAME);
|
||||||
mapping.from(Controller.Standard.LT).peek().constrainToInteger().to(Controller.Actions.ReticleClick);
|
mapping.from(Controller.Standard.LT).peek().constrainToInteger().to(Controller.Actions.ReticleClick);
|
||||||
|
@ -56,8 +36,6 @@ mapping.from(Controller.Standard.RT).peek().constrainToInteger().to(Controller.A
|
||||||
mapping.enable();
|
mapping.enable();
|
||||||
|
|
||||||
|
|
||||||
var lastRotatedLeft = Vec3.UNIT_NEG_Y;
|
|
||||||
var lastRotatedRight = Vec3.UNIT_NEG_Y;
|
|
||||||
|
|
||||||
function debugPrint(message) {
|
function debugPrint(message) {
|
||||||
if (DEBUGGING) {
|
if (DEBUGGING) {
|
||||||
|
@ -65,24 +43,9 @@ function debugPrint(message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var MAX_WAKE_UP_DISTANCE = 0.005;
|
var leftRightBias = 0.0;
|
||||||
var MIN_WAKE_UP_DISTANCE = 0.001;
|
var filteredRotatedLeft = Vec3.UNIT_NEG_Y;
|
||||||
var INITIAL_WAKE_UP_DISTANCE = MIN_WAKE_UP_DISTANCE;
|
var filteredRotatedRight = Vec3.UNIT_NEG_Y;
|
||||||
var INCREMENTAL_WAKE_UP_DISTANCE = 0.001;
|
|
||||||
|
|
||||||
var MAX_SLEEP_DISTANCE = 0.0004;
|
|
||||||
var MIN_SLEEP_DISTANCE = 0.00001; //0.00002;
|
|
||||||
var INITIAL_SLEEP_DISTANCE = MIN_SLEEP_DISTANCE;
|
|
||||||
var INCREMENTAL_SLEEP_DISTANCE = 0.000002; // 0.00002;
|
|
||||||
|
|
||||||
var leftAsleep = true;
|
|
||||||
var rightAsleep = true;
|
|
||||||
|
|
||||||
var leftWakeUpDistance = INITIAL_WAKE_UP_DISTANCE;
|
|
||||||
var rightWakeUpDistance = INITIAL_WAKE_UP_DISTANCE;
|
|
||||||
|
|
||||||
var leftSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
var rightSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
|
|
||||||
Script.update.connect(function(deltaTime) {
|
Script.update.connect(function(deltaTime) {
|
||||||
|
|
||||||
|
@ -96,153 +59,46 @@ Script.update.connect(function(deltaTime) {
|
||||||
var rotatedRight = Vec3.multiplyQbyV(poseRight.rotation, Vec3.UNIT_NEG_Y);
|
var rotatedRight = Vec3.multiplyQbyV(poseRight.rotation, Vec3.UNIT_NEG_Y);
|
||||||
var rotatedLeft = Vec3.multiplyQbyV(poseLeft.rotation, Vec3.UNIT_NEG_Y);
|
var rotatedLeft = Vec3.multiplyQbyV(poseLeft.rotation, Vec3.UNIT_NEG_Y);
|
||||||
|
|
||||||
var suppressRight = false;
|
|
||||||
var suppressLeft = false;
|
|
||||||
|
|
||||||
// What I really want to do is to slowly increase the epsilon you have to move it
|
|
||||||
// to wake up, the longer you go without moving it
|
|
||||||
var leftDistance = Vec3.distance(rotatedLeft, lastRotatedLeft);
|
|
||||||
var rightDistance = Vec3.distance(rotatedRight, lastRotatedRight);
|
|
||||||
|
|
||||||
// check to see if hand should wakeup or sleep
|
|
||||||
if (leftAsleep) {
|
|
||||||
if (leftDistance > leftWakeUpDistance) {
|
|
||||||
leftAsleep = false;
|
|
||||||
leftSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
leftWakeUpDistance = INITIAL_WAKE_UP_DISTANCE;
|
|
||||||
} else {
|
|
||||||
// grow the wake up distance to make it harder to wake up
|
|
||||||
leftWakeUpDistance = Math.min(leftWakeUpDistance + INCREMENTAL_WAKE_UP_DISTANCE, MAX_WAKE_UP_DISTANCE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we are awake, determine if we should fall asleep, if we haven't moved
|
|
||||||
// at least as much as our sleep distance then we sleep
|
|
||||||
if (leftDistance < leftSleepDistance) {
|
|
||||||
leftAsleep = true;
|
|
||||||
leftSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
leftWakeUpDistance = INITIAL_WAKE_UP_DISTANCE;
|
|
||||||
} else {
|
|
||||||
// if we moved more than the sleep amount, but we moved less than the max sleep
|
|
||||||
// amount, then increase our liklihood of sleep.
|
|
||||||
if (leftDistance < MAX_SLEEP_DISTANCE) {
|
|
||||||
print("growing sleep....");
|
|
||||||
leftSleepDistance = Math.max(leftSleepDistance + INCREMENTAL_SLEEP_DISTANCE, MAX_SLEEP_DISTANCE);
|
|
||||||
} else {
|
|
||||||
// otherwise reset it to initial
|
|
||||||
leftSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (leftAsleep) {
|
|
||||||
suppressLeft = true;
|
|
||||||
debugPrint("suppressing left not moving enough");
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if hand should wakeup or sleep
|
|
||||||
if (rightAsleep) {
|
|
||||||
if (rightDistance > rightWakeUpDistance) {
|
|
||||||
rightAsleep = false;
|
|
||||||
rightSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
rightWakeUpDistance = INITIAL_WAKE_UP_DISTANCE;
|
|
||||||
} else {
|
|
||||||
// grow the wake up distance to make it harder to wake up
|
|
||||||
rightWakeUpDistance = Math.min(rightWakeUpDistance + INCREMENTAL_WAKE_UP_DISTANCE, MAX_WAKE_UP_DISTANCE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we are awake, determine if we should fall asleep, if we haven't moved
|
|
||||||
// at least as much as our sleep distance then we sleep
|
|
||||||
if (rightDistance < rightSleepDistance) {
|
|
||||||
rightAsleep = true;
|
|
||||||
rightSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
rightWakeUpDistance = INITIAL_WAKE_UP_DISTANCE;
|
|
||||||
} else {
|
|
||||||
// if we moved more than the sleep amount, but we moved less than the max sleep
|
|
||||||
// amount, then increase our liklihood of sleep.
|
|
||||||
if (rightDistance < MAX_SLEEP_DISTANCE) {
|
|
||||||
print("growing sleep....");
|
|
||||||
rightSleepDistance = Math.max(rightSleepDistance + INCREMENTAL_SLEEP_DISTANCE, MAX_SLEEP_DISTANCE);
|
|
||||||
} else {
|
|
||||||
// otherwise reset it to initial
|
|
||||||
rightSleepDistance = INITIAL_SLEEP_DISTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rightAsleep) {
|
|
||||||
suppressRight = true;
|
|
||||||
debugPrint("suppressing right not moving enough");
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if hand is on base station
|
|
||||||
if (Vec3.equal(rotatedLeft, Vec3.UNIT_NEG_Y)) {
|
|
||||||
suppressLeft = true;
|
|
||||||
debugPrint("suppressing left on base station");
|
|
||||||
}
|
|
||||||
if (Vec3.equal(rotatedRight, Vec3.UNIT_NEG_Y)) {
|
|
||||||
suppressRight = true;
|
|
||||||
debugPrint("suppressing right on base station");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep track of last rotations, to detect resting (but not on base station hands) in the future
|
|
||||||
lastRotatedLeft = rotatedLeft;
|
|
||||||
lastRotatedRight = rotatedRight;
|
lastRotatedRight = rotatedRight;
|
||||||
|
|
||||||
if (suppressLeft && suppressRight) {
|
|
||||||
debugPrint("both hands suppressed bail out early");
|
// Decide which hand should be controlling the pointer
|
||||||
return;
|
// by comparing which one is moving more, and by
|
||||||
|
// tending to stay with the one moving more.
|
||||||
|
var BIAS_ADJUST_RATE = 0.5;
|
||||||
|
var BIAS_ADJUST_DEADZONE = 0.05;
|
||||||
|
leftRightBias += (Vec3.length(poseRight.angularVelocity) - Vec3.length(poseLeft.angularVelocity)) * BIAS_ADJUST_RATE;
|
||||||
|
if (leftRightBias < BIAS_ADJUST_DEADZONE) {
|
||||||
|
leftRightBias = 0.0;
|
||||||
|
} else if (leftRightBias > (1.0 - BIAS_ADJUST_DEADZONE)) {
|
||||||
|
leftRightBias = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (suppressLeft) {
|
// Velocity filter the hand rotation used to position reticle so that it is easier to target small things with the hand controllers
|
||||||
debugPrint("right only");
|
var VELOCITY_FILTER_GAIN = 1.0;
|
||||||
rotatedLeft = rotatedRight;
|
filteredRotatedLeft = Vec3.mix(filteredRotatedLeft, rotatedLeft, Math.clamp(Vec3.length(poseLeft.angularVelocity) * VELOCITY_FILTER_GAIN, 0.0, 1.0));
|
||||||
}
|
filteredRotatedRight = Vec3.mix(filteredRotatedRight, rotatedRight, Math.clamp(Vec3.length(poseRight.angularVelocity) * VELOCITY_FILTER_GAIN, 0.0, 1.0));
|
||||||
if (suppressRight) {
|
var rotated = Vec3.mix(filteredRotatedLeft, filteredRotatedRight, leftRightBias);
|
||||||
debugPrint("left only");
|
|
||||||
rotatedRight = rotatedLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Average the two hand positions, if either hand is on base station, the
|
|
||||||
// other hand becomes the only used hand and the average is the hand in use
|
|
||||||
var rotated = Vec3.multiply(Vec3.sum(rotatedRight,rotatedLeft), 0.5);
|
|
||||||
|
|
||||||
if (DEBUGGING) {
|
|
||||||
Vec3.print("rotatedRight:", rotatedRight);
|
|
||||||
Vec3.print("rotatedLeft:", rotatedLeft);
|
|
||||||
Vec3.print("rotated:", rotated);
|
|
||||||
}
|
|
||||||
|
|
||||||
var absolutePitch = rotated.y; // from 1 down to -1 up ... but note: if you rotate down "too far" it starts to go up again...
|
var absolutePitch = rotated.y; // from 1 down to -1 up ... but note: if you rotate down "too far" it starts to go up again...
|
||||||
var absoluteYaw = -rotated.x; // from -1 left to 1 right
|
var absoluteYaw = -rotated.x; // from -1 left to 1 right
|
||||||
|
|
||||||
if (DEBUGGING) {
|
|
||||||
print("absolutePitch:" + absolutePitch);
|
|
||||||
print("absoluteYaw:" + absoluteYaw);
|
|
||||||
Vec3.print("rotated:", rotated);
|
|
||||||
}
|
|
||||||
|
|
||||||
var ROTATION_BOUND = 0.6;
|
var ROTATION_BOUND = 0.6;
|
||||||
var clampYaw = Math.clamp(absoluteYaw, -ROTATION_BOUND, ROTATION_BOUND);
|
var clampYaw = Math.clamp(absoluteYaw, -ROTATION_BOUND, ROTATION_BOUND);
|
||||||
var clampPitch = Math.clamp(absolutePitch, -ROTATION_BOUND, ROTATION_BOUND);
|
var clampPitch = Math.clamp(absolutePitch, -ROTATION_BOUND, ROTATION_BOUND);
|
||||||
if (DEBUGGING) {
|
|
||||||
print("clampYaw:" + clampYaw);
|
|
||||||
print("clampPitch:" + clampPitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// using only from -ROTATION_BOUND to ROTATION_BOUND
|
// using only from -ROTATION_BOUND to ROTATION_BOUND
|
||||||
var xRatio = (clampYaw + ROTATION_BOUND) / (2 * ROTATION_BOUND);
|
var xRatio = (clampYaw + ROTATION_BOUND) / (2 * ROTATION_BOUND);
|
||||||
var yRatio = (clampPitch + ROTATION_BOUND) / (2 * ROTATION_BOUND);
|
var yRatio = (clampPitch + ROTATION_BOUND) / (2 * ROTATION_BOUND);
|
||||||
|
|
||||||
if (DEBUGGING) {
|
|
||||||
print("xRatio:" + xRatio);
|
|
||||||
print("yRatio:" + yRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
var x = screenSizeX * xRatio;
|
var x = screenSizeX * xRatio;
|
||||||
var y = screenSizeY * yRatio;
|
var y = screenSizeY * yRatio;
|
||||||
|
|
||||||
if (DEBUGGING) {
|
// don't move the reticle with the hand controllers unless the controllers are actually being moved
|
||||||
print("position x:" + x + " y:" + y);
|
var MINIMUM_CONTROLLER_ANGULAR_VELOCITY = 0.0001;
|
||||||
}
|
var angularVelocityMagnitude = Vec3.length(poseLeft.angularVelocity) * (1.0 - leftRightBias) + Vec3.length(poseRight.angularVelocity) * leftRightBias;
|
||||||
if (!(xRatio == 0.5 && yRatio == 0)) {
|
|
||||||
|
if (!(xRatio == 0.5 && yRatio == 0) && (angularVelocityMagnitude > MINIMUM_CONTROLLER_ANGULAR_VELOCITY)) {
|
||||||
moveReticleAbsolute(x, y);
|
moveReticleAbsolute(x, y);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue