keep hokey paddle in playing field

This commit is contained in:
Andrew Meadows 2015-05-18 09:42:55 -07:00
parent 1f8008e5b5
commit 257a730029

View file

@ -1,4 +1,3 @@
// grab.js // grab.js
// examples // examples
// //
@ -11,12 +10,38 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
// these are hand-measured bounds of the AirHockey table
var fieldMaxOffset = {
x: 0.475,
y: 0.315,
z: 0.830
};
var fieldMinOffset = {
x: -0.475,
y: 0.315,
z: -0.830
};
// parameters for storing the table playing field
var fieldMax = {
x: 0,
y: 0,
z: 0
};
var fieldMin = {
x: 0,
y: 0,
z: 0
};
var isGrabbing = false; var isGrabbing = false;
var grabbedEntity = null; var grabbedEntity = null;
var prevMouse = {}; var prevMouse = {};
var deltaMouse = { var deltaMouse = {
z: 0 z: 0
} }
var TABLE_SEARCH_RANGE = 10;
var entityProps; var entityProps;
var moveUpDown = false; var moveUpDown = false;
var CLOSE_ENOUGH = 0.001; var CLOSE_ENOUGH = 0.001;
@ -26,8 +51,13 @@ var DAMPING_RATE = 0.80;
var ANGULAR_DAMPING_RATE = 0.40; var ANGULAR_DAMPING_RATE = 0.40;
var SCREEN_TO_METERS = 0.001; var SCREEN_TO_METERS = 0.001;
var currentPosition, currentVelocity, cameraEntityDistance, currentRotation; var currentPosition, currentVelocity, cameraEntityDistance, currentRotation;
var grabHeight;
var velocityTowardTarget, desiredVelocity, addedVelocity, newVelocity, dPosition, camYaw, distanceToTarget, targetPosition; var velocityTowardTarget, desiredVelocity, addedVelocity, newVelocity, dPosition, camYaw, distanceToTarget, targetPosition;
var originalGravity = {x: 0, y: 0, z: 0}; var originalGravity = {
x: 0,
y: 0,
z: 0
};
var shouldRotate = false; var shouldRotate = false;
var dQ, theta, axisAngle, dT; var dQ, theta, axisAngle, dT;
var angularVelocity = { var angularVelocity = {
@ -75,9 +105,15 @@ function mousePressEvent(event) {
if (!event.isLeftButton) { if (!event.isLeftButton) {
return; return;
} }
prevMouse.x = event.x;
prevMouse.y = event.y;
var pickRay = Camera.computePickRay(event.x, event.y); var pickRay = Camera.computePickRay(event.x, event.y);
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
if (intersection.intersects && intersection.properties.collisionsWillMove) { if (!intersection.intersects) {
return;
}
if (intersection.properties.collisionsWillMove) {
grabbedEntity = intersection.entityID; grabbedEntity = intersection.entityID;
var props = Entities.getEntityProperties(grabbedEntity) var props = Entities.getEntityProperties(grabbedEntity)
isGrabbing = true; isGrabbing = true;
@ -87,14 +123,34 @@ function mousePressEvent(event) {
currentVelocity = props.velocity; currentVelocity = props.velocity;
updateDropLine(targetPosition); updateDropLine(targetPosition);
// remember the height of the object when first grabbed
// we'll try to maintain this height during the rest of this grab
grabHeight = currentPosition.y;
Entities.editEntity(grabbedEntity, { Entities.editEntity(grabbedEntity, {
gravity: {x: 0, y: 0, z: 0} gravity: {
x: 0,
y: 0,
z: 0
}
}); });
Audio.playSound(grabSound, { Audio.playSound(grabSound, {
position: props.position, position: props.position,
volume: VOLUME volume: VOLUME
}); });
//We want to detect table once user grabs something that may be on a table...
var potentialTables = Entities.findEntities(MyAvatar.position, TABLE_SEARCH_RANGE);
potentialTables.forEach(function(table) {
var props = Entities.getEntityProperties(table);
if (props.name === "table") {
var tablePosition = props.position;
// when we know the table's position we can compute the X-Z bounds of its field
fieldMax = Vec3.sum(tablePosition, fieldMaxOffset);
fieldMin = Vec3.sum(tablePosition, fieldMinOffset);
}
});
} }
} }
@ -144,6 +200,7 @@ function mouseReleaseEvent() {
} }
} }
// new mouseMoveEvent
function mouseMoveEvent(event) { function mouseMoveEvent(event) {
if (isGrabbing) { if (isGrabbing) {
// see if something added/restored gravity // see if something added/restored gravity
@ -152,6 +209,7 @@ function mouseMoveEvent(event) {
originalGravity = props.gravity; originalGravity = props.gravity;
} }
if (shouldRotate) {
deltaMouse.x = event.x - prevMouse.x; deltaMouse.x = event.x - prevMouse.x;
if (!moveUpDown) { if (!moveUpDown) {
deltaMouse.z = event.y - prevMouse.y; deltaMouse.z = event.y - prevMouse.y;
@ -160,16 +218,6 @@ function mouseMoveEvent(event) {
deltaMouse.y = (event.y - prevMouse.y) * -1; deltaMouse.y = (event.y - prevMouse.y) * -1;
deltaMouse.z = 0; deltaMouse.z = 0;
} }
// Update the target position by the amount the mouse moved
camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y;
dPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse);
if (!shouldRotate) {
// Adjust target position for the object by the mouse move
cameraEntityDistance = Vec3.distance(Camera.getPosition(), currentPosition);
// Scale distance we want to move by the distance from the camera to the grabbed object
// TODO: Correct SCREEN_TO_METERS to be correct for the actual FOV, resolution
targetPosition = Vec3.sum(targetPosition, Vec3.multiply(dPosition, cameraEntityDistance * SCREEN_TO_METERS));
} else if (shouldRotate) {
var transformedDeltaMouse = { var transformedDeltaMouse = {
x: deltaMouse.z, x: deltaMouse.z,
y: deltaMouse.x, y: deltaMouse.x,
@ -180,15 +228,37 @@ function mouseMoveEvent(event) {
theta = 2 * Math.acos(dQ.w); theta = 2 * Math.acos(dQ.w);
axisAngle = Quat.axis(dQ); axisAngle = Quat.axis(dQ);
angularVelocity = Vec3.multiply((theta / dT), axisAngle); angularVelocity = Vec3.multiply((theta / dT), axisAngle);
} } else {
var relativePosition = Vec3.subtract(currentPosition, Camera.getPosition());
if (relativePosition.y < 0) {
// grabee is below camera, so movement is valid
// compute intersectionPoint where mouse ray hits grabee's current x-z plane
var pickRay = Camera.computePickRay(event.x, event.y);
var mousePosition = pickRay.direction;
var length = relativePosition.y / mousePosition.y;
mousePosition = Vec3.multiply(mousePosition, length);
mousePosition = Vec3.sum(Camera.getPosition(), mousePosition);
// clamp mousePosition to table field
if (mousePosition.x < fieldMin.x) {
mousePosition.x = fieldMin.x;
} else if (mousePosition.x > fieldMax.x) {
mousePosition.x = fieldMax.x;
}
if (mousePosition.z < fieldMin.z) {
mousePosition.z = fieldMin.z;
} else if (mousePosition.z > fieldMax.z) {
mousePosition.z = fieldMax.z;
}
mousePosition.y = grabHeight;
targetPosition = mousePosition;
}
}
} }
prevMouse.x = event.x; prevMouse.x = event.x;
prevMouse.y = event.y; prevMouse.y = event.y;
} }
function keyReleaseEvent(event) { function keyReleaseEvent(event) {
if (event.text === "SHIFT") { if (event.text === "SHIFT") {
moveUpDown = false; moveUpDown = false;
@ -237,7 +307,11 @@ function update(deltaTime) {
newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE)); newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE));
// Update entity // Update entity
} else { } else {
newVelocity = {x: 0, y: 0, z: 0}; newVelocity = {
x: 0,
y: 0,
z: 0
};
} }
if (shouldRotate) { if (shouldRotate) {
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE)); angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
@ -245,6 +319,12 @@ function update(deltaTime) {
angularVelocity = entityProps.angularVelocity; angularVelocity = entityProps.angularVelocity;
} }
// enforce that grabee's rotation is only about y-axis while being grabbed
currentRotation.x = 0;
currentRotation.z = 0;
currentRotation.y = Math.sqrt(1.0 - currentRotation.w * currentRotation.w);
// Hrm... slamming the currentRotation doesn't seem to work
Entities.editEntity(grabbedEntity, { Entities.editEntity(grabbedEntity, {
position: currentPosition, position: currentPosition,
rotation: currentRotation, rotation: currentRotation,