mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 16:55:06 +02:00
Merge pull request #6741 from PhilipRosedale/master
Improved hand controller grab and mouse movement
This commit is contained in:
commit
9276c78368
2 changed files with 105 additions and 200 deletions
|
@ -23,8 +23,9 @@ var WANT_DEBUG = false;
|
|||
// these tune time-averaging and "on" value for analog trigger
|
||||
//
|
||||
|
||||
var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value
|
||||
var TRIGGER_ON_VALUE = 0.4;
|
||||
var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing
|
||||
var TRIGGER_ON_VALUE = 0.4; // Squeezed just enough to activate search or near grab
|
||||
var TRIGGER_GRAB_VALUE = 0.85; // Squeezed far enough to complete distant grab
|
||||
var TRIGGER_OFF_VALUE = 0.15;
|
||||
|
||||
var BUMPER_ON_VALUE = 0.5;
|
||||
|
@ -96,7 +97,7 @@ var MSEC_PER_SEC = 1000.0;
|
|||
var LIFETIME = 10;
|
||||
var ACTION_TTL = 15; // seconds
|
||||
var ACTION_TTL_REFRESH = 5;
|
||||
var PICKS_PER_SECOND_PER_HAND = 5;
|
||||
var PICKS_PER_SECOND_PER_HAND = 60;
|
||||
var MSECS_PER_SEC = 1000.0;
|
||||
var GRABBABLE_PROPERTIES = [
|
||||
"position",
|
||||
|
@ -123,8 +124,8 @@ var blacklist = [];
|
|||
|
||||
//we've created various ways of visualizing looking for and moving distant objects
|
||||
var USE_ENTITY_LINES_FOR_SEARCHING = false;
|
||||
var USE_OVERLAY_LINES_FOR_SEARCHING = false;
|
||||
var USE_PARTICLE_BEAM_FOR_SEARCHING = true;
|
||||
var USE_OVERLAY_LINES_FOR_SEARCHING = true;
|
||||
var USE_PARTICLE_BEAM_FOR_SEARCHING = false;
|
||||
|
||||
var USE_ENTITY_LINES_FOR_MOVING = false;
|
||||
var USE_OVERLAY_LINES_FOR_MOVING = false;
|
||||
|
@ -290,6 +291,11 @@ function MyController(hand) {
|
|||
this.spotlight = null;
|
||||
this.pointlight = null;
|
||||
this.overlayLine = null;
|
||||
this.searchSphere = null;
|
||||
|
||||
// how far from camera to search intersection?
|
||||
this.intersectionDistance = 0.0;
|
||||
this.searchSphereDistance = 0.0;
|
||||
|
||||
this.ignoreIK = false;
|
||||
this.offsetPosition = Vec3.ZERO;
|
||||
|
@ -409,6 +415,23 @@ function MyController(hand) {
|
|||
}
|
||||
};
|
||||
|
||||
var SEARCH_SPHERE_ALPHA = 0.5;
|
||||
this.searchSphereOn = function(location, size, color) {
|
||||
if (this.searchSphere === null) {
|
||||
var sphereProperties = {
|
||||
position: location,
|
||||
size: size,
|
||||
color: color,
|
||||
alpha: SEARCH_SPHERE_ALPHA,
|
||||
solid: true,
|
||||
visible: true
|
||||
}
|
||||
this.searchSphere = Overlays.addOverlay("sphere", sphereProperties);
|
||||
} else {
|
||||
Overlays.editOverlay(this.searchSphere, { position: location, size: size, color: color, visible: true });
|
||||
}
|
||||
}
|
||||
|
||||
this.overlayLineOn = function(closePoint, farPoint, color) {
|
||||
if (this.overlayLine === null) {
|
||||
var lineProperties = {
|
||||
|
@ -654,6 +677,17 @@ function MyController(hand) {
|
|||
this.overlayLine = null;
|
||||
};
|
||||
|
||||
this.searchSphereOff = function() {
|
||||
if (this.searchSphere !== null) {
|
||||
//Overlays.editOverlay(this.searchSphere, { visible: false });
|
||||
Overlays.deleteOverlay(this.searchSphere);
|
||||
this.searchSphere = null;
|
||||
this.searchSphereDistance = 0.0;
|
||||
this.intersectionDistance = 0.0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.particleBeamOff = function() {
|
||||
if (this.particleBeam !== null) {
|
||||
Entities.editEntity(this.particleBeam, {
|
||||
|
@ -687,6 +721,7 @@ function MyController(hand) {
|
|||
if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) {
|
||||
this.particleBeamOff();
|
||||
}
|
||||
this.searchSphereOff();
|
||||
};
|
||||
|
||||
this.triggerPress = function(value) {
|
||||
|
@ -704,6 +739,10 @@ function MyController(hand) {
|
|||
(triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO));
|
||||
};
|
||||
|
||||
this.triggerSmoothedGrab = function() {
|
||||
return this.triggerValue > TRIGGER_GRAB_VALUE;
|
||||
};
|
||||
|
||||
this.triggerSmoothedSqueezed = function() {
|
||||
return this.triggerValue > TRIGGER_ON_VALUE;
|
||||
};
|
||||
|
@ -712,11 +751,6 @@ function MyController(hand) {
|
|||
return this.triggerValue < TRIGGER_OFF_VALUE;
|
||||
};
|
||||
|
||||
this.triggerSqueezed = function() {
|
||||
var triggerValue = this.rawTriggerValue;
|
||||
return triggerValue > TRIGGER_ON_VALUE;
|
||||
};
|
||||
|
||||
this.bumperSqueezed = function() {
|
||||
return _this.rawBumperValue > BUMPER_ON_VALUE;
|
||||
};
|
||||
|
@ -726,15 +760,15 @@ function MyController(hand) {
|
|||
};
|
||||
|
||||
this.off = function() {
|
||||
if (this.triggerSmoothedSqueezed()) {
|
||||
if (this.triggerSmoothedSqueezed() || this.bumperSqueezed()) {
|
||||
this.lastPickTime = 0;
|
||||
this.setState(STATE_SEARCHING);
|
||||
return;
|
||||
}
|
||||
if (this.bumperSqueezed()) {
|
||||
this.lastPickTime = 0;
|
||||
this.setState(STATE_EQUIP_SEARCHING);
|
||||
return;
|
||||
var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
this.startingHandRotation = Controller.getPoseValue(controllerHandInput).rotation;
|
||||
if (this.triggerSmoothedSqueezed()) {
|
||||
this.setState(STATE_SEARCHING);
|
||||
} else {
|
||||
this.setState(STATE_EQUIP_SEARCHING);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -746,15 +780,20 @@ function MyController(hand) {
|
|||
return;
|
||||
}
|
||||
|
||||
// the trigger is being pressed, do a ray test
|
||||
// the trigger is being pressed, so do a ray test to see what we are hitting
|
||||
var handPosition = this.getHandPosition();
|
||||
|
||||
var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
var currentHandRotation = Controller.getPoseValue(controllerHandInput).rotation;
|
||||
var handDeltaRotation = Quat.multiply(currentHandRotation, Quat.inverse(this.startingHandRotation));
|
||||
|
||||
var distantPickRay = {
|
||||
origin: handPosition,
|
||||
direction: Quat.getUp(this.getHandRotation()),
|
||||
origin: Camera.position,
|
||||
direction: Quat.getFront(Quat.multiply(Camera.orientation, handDeltaRotation)),
|
||||
length: PICK_MAX_DISTANCE
|
||||
};
|
||||
|
||||
// don't pick 60x per second.
|
||||
// Pick at some maximum rate, not always
|
||||
var pickRays = [];
|
||||
var now = Date.now();
|
||||
if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) {
|
||||
|
@ -793,7 +832,7 @@ function MyController(hand) {
|
|||
if (intersection.intersects) {
|
||||
|
||||
// the ray is intersecting something we can move.
|
||||
var intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection);
|
||||
this.intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection);
|
||||
|
||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA);
|
||||
var defaultDisableNearGrabData = {
|
||||
|
@ -809,11 +848,11 @@ function MyController(hand) {
|
|||
if (typeof grabbableData.grabbable !== 'undefined' && !grabbableData.grabbable) {
|
||||
continue;
|
||||
}
|
||||
if (intersectionDistance > pickRay.length) {
|
||||
if (this.intersectionDistance > pickRay.length) {
|
||||
// too far away for this ray.
|
||||
continue;
|
||||
}
|
||||
if (intersectionDistance <= NEAR_PICK_MAX_DISTANCE) {
|
||||
if (this.intersectionDistance <= NEAR_PICK_MAX_DISTANCE) {
|
||||
// the hand is very close to the intersected object. go into close-grabbing mode.
|
||||
if (grabbableData.wantsTrigger) {
|
||||
this.grabbedEntity = intersection.entityID;
|
||||
|
@ -851,11 +890,11 @@ function MyController(hand) {
|
|||
// this.setState(STATE_EQUIP_SPRING);
|
||||
this.setState(STATE_EQUIP);
|
||||
return;
|
||||
} else if (this.state == STATE_SEARCHING) {
|
||||
} else if ((this.state == STATE_SEARCHING) && this.triggerSmoothedGrab()) {
|
||||
this.setState(STATE_DISTANCE_HOLDING);
|
||||
return;
|
||||
}
|
||||
} else if (grabbableData.wantsTrigger) {
|
||||
} else if (grabbableData.wantsTrigger && this.triggerSmoothedGrab()) {
|
||||
this.grabbedEntity = intersection.entityID;
|
||||
this.setState(STATE_FAR_TRIGGER);
|
||||
return;
|
||||
|
@ -864,6 +903,7 @@ function MyController(hand) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// forward ray test failed, try sphere test.
|
||||
if (WANT_DEBUG) {
|
||||
Entities.addEntity({
|
||||
|
@ -970,14 +1010,23 @@ function MyController(hand) {
|
|||
this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
||||
}
|
||||
|
||||
if (USE_OVERLAY_LINES_FOR_SEARCHING === true) {
|
||||
this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR);
|
||||
}
|
||||
|
||||
if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) {
|
||||
this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR);
|
||||
}
|
||||
|
||||
if (this.intersectionDistance > 0) {
|
||||
var SPHERE_INTERSECTION_SIZE = 0.011;
|
||||
var SEARCH_SPHERE_FOLLOW_RATE = 0.50;
|
||||
var SEARCH_SPHERE_CHASE_DROP = 0.2;
|
||||
this.searchSphereDistance = this.searchSphereDistance * SEARCH_SPHERE_FOLLOW_RATE + this.intersectionDistance * (1.0 - SEARCH_SPHERE_FOLLOW_RATE);
|
||||
var searchSphereLocation = Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
|
||||
searchSphereLocation.y -= ((this.intersectionDistance - this.searchSphereDistance) / this.intersectionDistance) * SEARCH_SPHERE_CHASE_DROP;
|
||||
this.searchSphereOn(searchSphereLocation, SPHERE_INTERSECTION_SIZE * this.intersectionDistance, this.triggerSmoothedGrab() ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
|
||||
if (USE_OVERLAY_LINES_FOR_SEARCHING === true) {
|
||||
var OVERLAY_BEAM_SETBACK = 0.9;
|
||||
var startBeam = Vec3.sum(handPosition, Vec3.multiply(Vec3.subtract(searchSphereLocation, handPosition), OVERLAY_BEAM_SETBACK));
|
||||
this.overlayLineOn(startBeam, searchSphereLocation, this.triggerSmoothedGrab() ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.distanceHolding = function() {
|
||||
|
|
|
@ -22,33 +22,13 @@ function length(posA, posB) {
|
|||
return length;
|
||||
}
|
||||
|
||||
var EXPECTED_CHANGE = 50;
|
||||
var lastPos = Controller.getReticlePosition();
|
||||
function moveReticleAbsolute(x, y) {
|
||||
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.y = y;
|
||||
Controller.setReticlePosition(globalPos);
|
||||
lastPos = globalPos;
|
||||
}
|
||||
|
||||
|
||||
var MAPPING_NAME = "com.highfidelity.testing.reticleWithHandRotation";
|
||||
var mapping = Controller.newMapping(MAPPING_NAME);
|
||||
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();
|
||||
|
||||
|
||||
var lastRotatedLeft = Vec3.UNIT_NEG_Y;
|
||||
var lastRotatedRight = Vec3.UNIT_NEG_Y;
|
||||
|
||||
function debugPrint(message) {
|
||||
if (DEBUGGING) {
|
||||
|
@ -65,24 +43,9 @@ function debugPrint(message) {
|
|||
}
|
||||
}
|
||||
|
||||
var MAX_WAKE_UP_DISTANCE = 0.005;
|
||||
var MIN_WAKE_UP_DISTANCE = 0.001;
|
||||
var INITIAL_WAKE_UP_DISTANCE = MIN_WAKE_UP_DISTANCE;
|
||||
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;
|
||||
var leftRightBias = 0.0;
|
||||
var filteredRotatedLeft = Vec3.UNIT_NEG_Y;
|
||||
var filteredRotatedRight = Vec3.UNIT_NEG_Y;
|
||||
|
||||
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 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;
|
||||
|
||||
if (suppressLeft && suppressRight) {
|
||||
debugPrint("both hands suppressed bail out early");
|
||||
return;
|
||||
|
||||
// Decide which hand should be controlling the pointer
|
||||
// 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) {
|
||||
debugPrint("right only");
|
||||
rotatedLeft = rotatedRight;
|
||||
}
|
||||
if (suppressRight) {
|
||||
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);
|
||||
}
|
||||
// Velocity filter the hand rotation used to position reticle so that it is easier to target small things with the hand controllers
|
||||
var VELOCITY_FILTER_GAIN = 1.0;
|
||||
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));
|
||||
var rotated = Vec3.mix(filteredRotatedLeft, filteredRotatedRight, leftRightBias);
|
||||
|
||||
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
|
||||
|
||||
if (DEBUGGING) {
|
||||
print("absolutePitch:" + absolutePitch);
|
||||
print("absoluteYaw:" + absoluteYaw);
|
||||
Vec3.print("rotated:", rotated);
|
||||
}
|
||||
|
||||
var ROTATION_BOUND = 0.6;
|
||||
var clampYaw = Math.clamp(absoluteYaw, -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
|
||||
var xRatio = (clampYaw + 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 y = screenSizeY * yRatio;
|
||||
|
||||
if (DEBUGGING) {
|
||||
print("position x:" + x + " y:" + y);
|
||||
}
|
||||
if (!(xRatio == 0.5 && yRatio == 0)) {
|
||||
// don't move the reticle with the hand controllers unless the controllers are actually being moved
|
||||
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) && (angularVelocityMagnitude > MINIMUM_CONTROLLER_ANGULAR_VELOCITY)) {
|
||||
moveReticleAbsolute(x, y);
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue