mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
remove hungarian notation
This commit is contained in:
parent
9b37b83eb6
commit
a444d6a2a2
1 changed files with 235 additions and 189 deletions
424
examples/grab.js
424
examples/grab.js
|
@ -10,97 +10,13 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
var MOVE_TIMESCALE = 0.1;
|
|
||||||
var INV_MOVE_TIMESCALE = 1.0 / MOVE_TIMESCALE;
|
|
||||||
var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed
|
var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed
|
||||||
var CLOSE_ENOUGH = 0.001;
|
var ZERO_VEC3 = {x: 0, y: 0, z: 0};
|
||||||
var ZERO_VEC3 = { x: 0, y: 0, z: 0 };
|
var IDENTITY_QUAT = {x: 0, y: 0, z: 0, w: 0};
|
||||||
var ANGULAR_DAMPING_RATE = 0.40;
|
|
||||||
|
|
||||||
// NOTE: to improve readability global variable names start with 'g'
|
|
||||||
var gIsGrabbing = false;
|
|
||||||
var gGrabbedEntity = null;
|
|
||||||
var gActionID = null;
|
|
||||||
var gEntityProperties;
|
|
||||||
var gStartPosition;
|
|
||||||
var gStartRotation;
|
|
||||||
var gCurrentPosition;
|
|
||||||
var gOriginalGravity = ZERO_VEC3;
|
|
||||||
var gPlaneNormal = ZERO_VEC3;
|
|
||||||
|
|
||||||
// gMaxGrabDistance is a function of the size of the object.
|
|
||||||
var gMaxGrabDistance;
|
|
||||||
|
|
||||||
// gGrabMode defines the degrees of freedom of the grab target positions
|
|
||||||
// relative to gGrabStartPosition options include:
|
|
||||||
// xzPlane (default)
|
|
||||||
// verticalCylinder (SHIFT)
|
|
||||||
// rotate (CONTROL)
|
|
||||||
// Modes to eventually support?:
|
|
||||||
// xyPlane
|
|
||||||
// yzPlane
|
|
||||||
// polar
|
|
||||||
// elevationAzimuth
|
|
||||||
var gGrabMode = "xzplane";
|
|
||||||
|
|
||||||
// gGrabOffset allows the user to grab an object off-center. It points from the object's center
|
|
||||||
// to the point where the ray intersects the grab plane (at the moment the grab is initiated).
|
|
||||||
// Future target positions of the ray intersection are on the same plane, and the offset is subtracted
|
|
||||||
// to compute the target position of the object's center.
|
|
||||||
var gGrabOffset = { x: 0, y: 0, z: 0 };
|
|
||||||
|
|
||||||
var gTargetPosition;
|
|
||||||
var gTargetRotation;
|
|
||||||
var gLiftKey = false; // SHIFT
|
|
||||||
var gRotateKey = false; // CONTROL
|
|
||||||
|
|
||||||
var gInitialMouse = { x: 0, y: 0 };
|
|
||||||
var gPreviousMouse = { x: 0, y: 0 };
|
|
||||||
var gMouseCursorLocation = { x: 0, y: 0 };
|
|
||||||
var gMouseAtRotateStart = { x: 0, y: 0 };
|
|
||||||
|
|
||||||
var gBeaconHeight = 0.10;
|
|
||||||
|
|
||||||
// var gAngularVelocity = ZERO_VEC3;
|
|
||||||
|
|
||||||
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
|
||||||
// var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav");
|
|
||||||
// var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav");
|
|
||||||
// var VOLUME = 0.0;
|
|
||||||
|
|
||||||
var gBeaconHeight = 0.10;
|
|
||||||
var BEACON_COLOR = {
|
|
||||||
red: 200,
|
|
||||||
green: 200,
|
|
||||||
blue: 200
|
|
||||||
};
|
|
||||||
var BEACON_WIDTH = 2;
|
|
||||||
|
|
||||||
|
|
||||||
var gBeacon = Overlays.addOverlay("line3d", {
|
// helper function
|
||||||
color: BEACON_COLOR,
|
function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event, maxDistance) {
|
||||||
alpha: 1,
|
|
||||||
visible: false,
|
|
||||||
lineWidth: BEACON_WIDTH
|
|
||||||
});
|
|
||||||
|
|
||||||
function updateDropLine(position) {
|
|
||||||
Overlays.editOverlay(gBeacon, {
|
|
||||||
visible: true,
|
|
||||||
start: {
|
|
||||||
x: position.x,
|
|
||||||
y: position.y + gBeaconHeight,
|
|
||||||
z: position.z
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
x: position.x,
|
|
||||||
y: position.y - gBeaconHeight,
|
|
||||||
z: position.z
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event) {
|
|
||||||
var cameraPosition = Camera.getPosition();
|
var cameraPosition = Camera.getPosition();
|
||||||
var localPointOnPlane = Vec3.subtract(pointOnPlane, cameraPosition);
|
var localPointOnPlane = Vec3.subtract(pointOnPlane, cameraPosition);
|
||||||
var distanceFromPlane = Vec3.dot(localPointOnPlane, planeNormal);
|
var distanceFromPlane = Vec3.dot(localPointOnPlane, planeNormal);
|
||||||
|
@ -117,7 +33,7 @@ function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event) {
|
||||||
var useMaxForwardGrab = false;
|
var useMaxForwardGrab = false;
|
||||||
if (Math.abs(dirDotNorm) > MIN_RAY_PLANE_DOT) {
|
if (Math.abs(dirDotNorm) > MIN_RAY_PLANE_DOT) {
|
||||||
var distanceToIntersection = distanceFromPlane / dirDotNorm;
|
var distanceToIntersection = distanceFromPlane / dirDotNorm;
|
||||||
if (distanceToIntersection > 0 && distanceToIntersection < gMaxGrabDistance) {
|
if (distanceToIntersection > 0 && distanceToIntersection < maxDistance) {
|
||||||
// ray points into the plane
|
// ray points into the plane
|
||||||
localIntersection = Vec3.multiply(pickRay.direction, distanceFromPlane / dirDotNorm);
|
localIntersection = Vec3.multiply(pickRay.direction, distanceFromPlane / dirDotNorm);
|
||||||
} else {
|
} else {
|
||||||
|
@ -134,52 +50,160 @@ function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event) {
|
||||||
// we re-route the intersection to be in front at max distance.
|
// we re-route the intersection to be in front at max distance.
|
||||||
var rayDirection = Vec3.subtract(pickRay.direction, Vec3.multiply(planeNormal, dirDotNorm));
|
var rayDirection = Vec3.subtract(pickRay.direction, Vec3.multiply(planeNormal, dirDotNorm));
|
||||||
rayDirection = Vec3.normalize(rayDirection);
|
rayDirection = Vec3.normalize(rayDirection);
|
||||||
localIntersection = Vec3.multiply(rayDirection, gMaxGrabDistance);
|
localIntersection = Vec3.multiply(rayDirection, maxDistance);
|
||||||
localIntersection = Vec3.sum(localIntersection, Vec3.multiply(planeNormal, distanceFromPlane));
|
localIntersection = Vec3.sum(localIntersection, Vec3.multiply(planeNormal, distanceFromPlane));
|
||||||
}
|
}
|
||||||
var worldIntersection = Vec3.sum(cameraPosition, localIntersection);
|
var worldIntersection = Vec3.sum(cameraPosition, localIntersection);
|
||||||
return worldIntersection;
|
return worldIntersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeNewGrabPlane() {
|
// Mouse class stores mouse click and drag info
|
||||||
if (!gIsGrabbing) {
|
Mouse = function() {
|
||||||
|
this.current = {x: 0, y: 0 };
|
||||||
|
this.previous = {x: 0, y: 0 };
|
||||||
|
this.rotateStart = {x: 0, y: 0 };
|
||||||
|
this.cursorRestore = {x: 0, y: 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
Mouse.prototype.startDrag = function(position) {
|
||||||
|
this.current = {x: position.x, y: position.y};
|
||||||
|
this.startRotateDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mouse.prototype.updateDrag = function(position) {
|
||||||
|
this.current = {x: position.x, y: position.y };
|
||||||
|
}
|
||||||
|
|
||||||
|
Mouse.prototype.startRotateDrag = function() {
|
||||||
|
this.previous = {x: this.current.x, y: this.current.y};
|
||||||
|
this.rotateStart = {x: this.current.x, y: this.current.y};
|
||||||
|
this.cursorRestore = { x: Window.getCursorPositionX(), y: Window.getCursorPositionY() };
|
||||||
|
}
|
||||||
|
|
||||||
|
Mouse.prototype.getDrag = function() {
|
||||||
|
var delta = {x: this.current.x - this.previous.x, y: this.current.y - this.previous.y};
|
||||||
|
this.previous = {x: this.current.x, y: this.current.y};
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mouse.prototype.restoreRotateCursor = function() {
|
||||||
|
Window.setCursorPosition(this.cursorRestore.x, this.cursorRestore.y);
|
||||||
|
this.current = {x: this.rotateStart.x, y: this.rotateStart.y};
|
||||||
|
}
|
||||||
|
|
||||||
|
var mouse = new Mouse();
|
||||||
|
|
||||||
|
|
||||||
|
// Beacon class stores info for drawing a line at object's target position
|
||||||
|
Beacon = function() {
|
||||||
|
this.height = 0.10;
|
||||||
|
this.overlayID = Overlays.addOverlay("line3d", {
|
||||||
|
color: {red: 200, green: 200, blue: 200},
|
||||||
|
alpha: 1,
|
||||||
|
visible: false,
|
||||||
|
lineWidth: 2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Beacon.prototype.enable = function() {
|
||||||
|
Overlays.editOverlay(this.overlayID, { visible: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
Beacon.prototype.disable = function() {
|
||||||
|
Overlays.editOverlay(this.overlayID, { visible: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
Beacon.prototype.updatePosition = function(position) {
|
||||||
|
Overlays.editOverlay(this.overlayID, {
|
||||||
|
visible: true,
|
||||||
|
start: {
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + this.height,
|
||||||
|
z: position.z
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
x: position.x,
|
||||||
|
y: position.y - this.height,
|
||||||
|
z: position.z
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var beacon = new Beacon();
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
||||||
|
// var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav");
|
||||||
|
// var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav");
|
||||||
|
// var VOLUME = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
// Grabber class stores and computes info for grab behavior
|
||||||
|
Grabber = function() {
|
||||||
|
this.isGrabbing = false;
|
||||||
|
this.entityID = null;
|
||||||
|
this.actionID = null;
|
||||||
|
this.startPosition = ZERO_VEC3;
|
||||||
|
this.lastRotation = IDENTITY_QUAT;
|
||||||
|
this.currentPosition = ZERO_VEC3;
|
||||||
|
this.planeNormal = ZERO_VEC3;
|
||||||
|
|
||||||
|
this.originalGravity = ZERO_VEC3;
|
||||||
|
// maxDistance is a function of the size of the object.
|
||||||
|
this.maxDistance;
|
||||||
|
|
||||||
|
// mode defines the degrees of freedom of the grab target positions
|
||||||
|
// relative to startPosition options include:
|
||||||
|
// xzPlane (default)
|
||||||
|
// verticalCylinder (SHIFT)
|
||||||
|
// rotate (CONTROL)
|
||||||
|
this.mode = "xzplane";
|
||||||
|
|
||||||
|
// offset allows the user to grab an object off-center. It points from the object's center
|
||||||
|
// to the point where the ray intersects the grab plane (at the moment the grab is initiated).
|
||||||
|
// Future target positions of the ray intersection are on the same plane, and the offset is subtracted
|
||||||
|
// to compute the target position of the object's center.
|
||||||
|
this.offset = {x: 0, y: 0, z: 0 };
|
||||||
|
|
||||||
|
this.targetPosition;
|
||||||
|
this.targetRotation;
|
||||||
|
|
||||||
|
this.liftKey = false; // SHIFT
|
||||||
|
this.rotateKey = false; // CONTROL
|
||||||
|
}
|
||||||
|
|
||||||
|
Grabber.prototype.computeNewGrabPlane = function() {
|
||||||
|
if (!this.isGrabbing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var maybeResetMousePosition = false;
|
var modeWasRotate = (this.mode == "rotate");
|
||||||
if (gGrabMode !== "rotate") {
|
this.mode = "xzPlane";
|
||||||
gMouseAtRotateStart = gMouseCursorLocation;
|
this.planeNormal = {x: 0, y: 1, z: 0 };
|
||||||
|
if (this.rotateKey) {
|
||||||
|
this.mode = "rotate";
|
||||||
|
mouse.startRotateDrag();
|
||||||
} else {
|
} else {
|
||||||
maybeResetMousePosition = true;
|
if (modeWasRotate) {
|
||||||
}
|
// we reset the mouse screen position whenever we stop rotating
|
||||||
gGrabMode = "xzPlane";
|
mouse.restoreRotateCursor();
|
||||||
gPlaneNormal = { x: 0, y: 1, z: 0 };
|
|
||||||
if (gLiftKey) {
|
|
||||||
if (!gRotateKey) {
|
|
||||||
gGrabMode = "verticalCylinder";
|
|
||||||
// a new planeNormal will be computed each move
|
|
||||||
}
|
}
|
||||||
} else if (gRotateKey) {
|
if (this.liftKey) {
|
||||||
gGrabMode = "rotate";
|
this.mode = "verticalCylinder";
|
||||||
}
|
// NOTE: during verticalCylinder mode a new planeNormal will be computed each move
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gPointOnPlane = Vec3.sum(gCurrentPosition, gGrabOffset);
|
this.pointOnPlane = Vec3.sum(this.currentPosition, this.offset);
|
||||||
var xzOffset = Vec3.subtract(gPointOnPlane, Camera.getPosition());
|
var xzOffset = Vec3.subtract(this.pointOnPlane, Camera.getPosition());
|
||||||
xzOffset.y = 0;
|
xzOffset.y = 0;
|
||||||
gXzDistanceToGrab = Vec3.length(xzOffset);
|
this.xzDistanceToGrab = Vec3.length(xzOffset);
|
||||||
|
|
||||||
if (gGrabMode !== "rotate" && maybeResetMousePosition) {
|
|
||||||
// we reset the mouse position whenever we stop rotating
|
|
||||||
Window.setCursorPosition(gMouseAtRotateStart.x, gMouseAtRotateStart.y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
Grabber.prototype.pressEvent = function(event) {
|
||||||
if (!event.isLeftButton) {
|
if (!event.isLeftButton) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gInitialMouse = {x: event.x, y: event.y };
|
|
||||||
gPreviousMouse = {x: event.x, y: event.y };
|
|
||||||
|
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
var pickResults = Entities.findRayIntersection(pickRay, true); // accurate picking
|
var pickResults = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||||
|
@ -193,150 +217,172 @@ function mousePressEvent(event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mouse.startDrag(event);
|
||||||
|
|
||||||
var clickedEntity = pickResults.entityID;
|
var clickedEntity = pickResults.entityID;
|
||||||
var entityProperties = Entities.getEntityProperties(clickedEntity)
|
var entityProperties = Entities.getEntityProperties(clickedEntity)
|
||||||
gStartPosition = entityProperties.position;
|
this.startPosition = entityProperties.position;
|
||||||
gStartRotation = entityProperties.rotation;
|
this.lastRotation = entityProperties.rotation;
|
||||||
var cameraPosition = Camera.getPosition();
|
var cameraPosition = Camera.getPosition();
|
||||||
|
|
||||||
gBeaconHeight = Vec3.length(entityProperties.dimensions);
|
var objectBoundingDiameter = Vec3.length(entityProperties.dimensions);
|
||||||
gMaxGrabDistance = gBeaconHeight / MAX_SOLID_ANGLE;
|
beacon.height = objectBoundingDiameter;
|
||||||
if (Vec3.distance(gStartPosition, cameraPosition) > gMaxGrabDistance) {
|
this.maxDistance = objectBoundingDiameter / MAX_SOLID_ANGLE;
|
||||||
|
if (Vec3.distance(this.startPosition, cameraPosition) > this.maxDistance) {
|
||||||
// don't allow grabs of things far away
|
// don't allow grabs of things far away
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entities.editEntity(clickedEntity, { gravity: ZERO_VEC3 });
|
Entities.editEntity(clickedEntity, { gravity: ZERO_VEC3 });
|
||||||
gIsGrabbing = true;
|
this.isGrabbing = true;
|
||||||
|
|
||||||
gGrabbedEntity = clickedEntity;
|
this.entityID = clickedEntity;
|
||||||
gCurrentPosition = entityProperties.position;
|
this.currentPosition = entityProperties.position;
|
||||||
gOriginalGravity = entityProperties.gravity;
|
this.originalGravity = entityProperties.gravity;
|
||||||
gTargetPosition = gStartPosition;
|
this.targetPosition = {x: this.startPosition.x, y: this.startPosition.y, z: this.startPosition.z};
|
||||||
|
|
||||||
// compute the grab point
|
// compute the grab point
|
||||||
var nearestPoint = Vec3.subtract(gStartPosition, cameraPosition);
|
var nearestPoint = Vec3.subtract(this.startPosition, cameraPosition);
|
||||||
var distanceToGrab = Vec3.dot(nearestPoint, pickRay.direction);
|
var distanceToGrab = Vec3.dot(nearestPoint, pickRay.direction);
|
||||||
nearestPoint = Vec3.multiply(distanceToGrab, pickRay.direction);
|
nearestPoint = Vec3.multiply(distanceToGrab, pickRay.direction);
|
||||||
gPointOnPlane = Vec3.sum(cameraPosition, nearestPoint);
|
this.pointOnPlane = Vec3.sum(cameraPosition, nearestPoint);
|
||||||
|
|
||||||
// compute the grab offset (points from object center to point of grab)
|
// compute the grab offset (points from object center to point of grab)
|
||||||
gGrabOffset = Vec3.subtract(gPointOnPlane, gStartPosition);
|
this.offset = Vec3.subtract(this.pointOnPlane, this.startPosition);
|
||||||
|
|
||||||
computeNewGrabPlane();
|
this.computeNewGrabPlane();
|
||||||
|
|
||||||
updateDropLine(gStartPosition);
|
beacon.updatePosition(this.startPosition);
|
||||||
|
|
||||||
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
||||||
//Audio.playSound(grabSound, { position: entityProperties.position, volume: VOLUME });
|
//Audio.playSound(grabSound, { position: entityProperties.position, volume: VOLUME });
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseReleaseEvent() {
|
Grabber.prototype.releaseEvent = function() {
|
||||||
if (gIsGrabbing) {
|
if (this.isGrabbing) {
|
||||||
if (Vec3.length(gOriginalGravity) != 0) {
|
if (Vec3.length(this.originalGravity) != 0) {
|
||||||
Entities.editEntity(gGrabbedEntity, { gravity: gOriginalGravity });
|
Entities.editEntity(this.entityID, { gravity: this.originalGravity});
|
||||||
}
|
}
|
||||||
|
|
||||||
gIsGrabbing = false
|
this.isGrabbing = false
|
||||||
Entities.deleteAction(gGrabbedEntity, gActionID);
|
Entities.deleteAction(this.entityID, this.actionID);
|
||||||
gActionID = null;
|
this.actionID = null;
|
||||||
|
|
||||||
Overlays.editOverlay(gBeacon, { visible: false });
|
beacon.disable();
|
||||||
|
|
||||||
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
||||||
//Audio.playSound(releaseSound, { position: entityProperties.position, volume: VOLUME });
|
//Audio.playSound(releaseSound, { position: entityProperties.position, volume: VOLUME });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseMoveEvent(event) {
|
Grabber.prototype.moveEvent = function(event) {
|
||||||
if (!gIsGrabbing) {
|
if (!this.isGrabbing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mouse.updateDrag(event);
|
||||||
|
|
||||||
// see if something added/restored gravity
|
// see if something added/restored gravity
|
||||||
var entityProperties = Entities.getEntityProperties(gGrabbedEntity);
|
var entityProperties = Entities.getEntityProperties(this.entityID);
|
||||||
if (Vec3.length(entityProperties.gravity) != 0) {
|
if (Vec3.length(entityProperties.gravity) != 0) {
|
||||||
gOriginalGravity = entityProperties.gravity;
|
this.originalGravity = entityProperties.gravity;
|
||||||
}
|
}
|
||||||
gCurrentPosition = entityProperties.position;
|
this.currentPosition = entityProperties.position;
|
||||||
|
|
||||||
var actionArgs = {};
|
var actionArgs = {};
|
||||||
|
|
||||||
if (gGrabMode === "rotate") {
|
if (this.mode === "rotate") {
|
||||||
var deltaMouse = { x: 0, y: 0 };
|
var drag = mouse.getDrag();
|
||||||
var dx = event.x - gInitialMouse.x;
|
|
||||||
var dy = event.y - gInitialMouse.y;
|
|
||||||
var orientation = Camera.getOrientation();
|
var orientation = Camera.getOrientation();
|
||||||
var dragOffset = Vec3.multiply(dx, Quat.getRight(orientation));
|
var dragOffset = Vec3.multiply(drag.x, Quat.getRight(orientation));
|
||||||
dragOffset = Vec3.sum(dragOffset, Vec3.multiply(-dy, Quat.getUp(orientation)));
|
dragOffset = Vec3.sum(dragOffset, Vec3.multiply(-drag.y, Quat.getUp(orientation)));
|
||||||
var axis = Vec3.cross(dragOffset, Quat.getFront(orientation));
|
var axis = Vec3.cross(dragOffset, Quat.getFront(orientation));
|
||||||
axis = Vec3.normalize(axis);
|
axis = Vec3.normalize(axis);
|
||||||
var ROTATE_STRENGTH = 0.4; // magic number tuned by hand
|
var ROTATE_STRENGTH = 0.4; // magic number tuned by hand
|
||||||
var angle = ROTATE_STRENGTH * Math.sqrt((dx * dx) + (dy * dy));
|
var angle = ROTATE_STRENGTH * Math.sqrt((drag.x * drag.x) + (drag.y * drag.y));
|
||||||
var deltaQ = Quat.angleAxis(angle, axis);
|
var deltaQ = Quat.angleAxis(angle, axis);
|
||||||
// var qZero = entityProperties.rotation;
|
// var qZero = entityProperties.rotation;
|
||||||
var qZero = gStartRotation;
|
//var qZero = this.lastRotation;
|
||||||
var qOne = Quat.multiply(deltaQ, qZero);
|
this.lastRotation = Quat.multiply(deltaQ, this.lastRotation);
|
||||||
actionArgs = {targetRotation: qOne, angularTimeScale: 0.1};
|
actionArgs = {targetRotation: this.lastRotation, angularTimeScale: 0.1};
|
||||||
} else {
|
} else {
|
||||||
var newTargetPosition;
|
var newPointOnPlane;
|
||||||
if (gGrabMode === "verticalCylinder") {
|
if (this.mode === "verticalCylinder") {
|
||||||
// for this mode we recompute the plane based on current Camera
|
// for this mode we recompute the plane based on current Camera
|
||||||
var planeNormal = Quat.getFront(Camera.getOrientation());
|
var planeNormal = Quat.getFront(Camera.getOrientation());
|
||||||
planeNormal.y = 0;
|
planeNormal.y = 0;
|
||||||
planeNormal = Vec3.normalize(planeNormal);
|
planeNormal = Vec3.normalize(planeNormal);
|
||||||
var pointOnCylinder = Vec3.multiply(planeNormal, gXzDistanceToGrab);
|
var pointOnCylinder = Vec3.multiply(planeNormal, this.xzDistanceToGrab);
|
||||||
pointOnCylinder = Vec3.sum(Camera.getPosition(), pointOnCylinder);
|
pointOnCylinder = Vec3.sum(Camera.getPosition(), pointOnCylinder);
|
||||||
newTargetPosition = mouseIntersectionWithPlane(pointOnCylinder, planeNormal, event);
|
this.pointOnPlane = mouseIntersectionWithPlane(pointOnCylinder, planeNormal, mouse.current, this.maxDistance);
|
||||||
gPointOnPlane = Vec3.sum(newTargetPosition, gGrabOffset);
|
newPointOnPlane = {x: this.pointOnPlane.x, y: this.pointOnPlane.y, z: this.pointOnPlane.z};
|
||||||
} else {
|
} else {
|
||||||
var cameraPosition = Camera.getPosition();
|
var cameraPosition = Camera.getPosition();
|
||||||
newTargetPosition = mouseIntersectionWithPlane(gPointOnPlane, gPlaneNormal, event);
|
newPointOnPlane = mouseIntersectionWithPlane(this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance);
|
||||||
var relativePosition = Vec3.subtract(newTargetPosition, cameraPosition);
|
var relativePosition = Vec3.subtract(newPointOnPlane, cameraPosition);
|
||||||
var distance = Vec3.length(relativePosition);
|
var distance = Vec3.length(relativePosition);
|
||||||
if (distance > gMaxGrabDistance) {
|
if (distance > this.maxDistance) {
|
||||||
// clamp distance
|
// clamp distance
|
||||||
relativePosition = Vec3.multiply(relativePosition, gMaxGrabDistance / distance);
|
relativePosition = Vec3.multiply(relativePosition, this.maxDistance / distance);
|
||||||
newTargetPosition = Vec3.sum(relativePosition, cameraPosition);
|
newPointOnPlane = Vec3.sum(relativePosition, cameraPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gTargetPosition = Vec3.subtract(newTargetPosition, gGrabOffset);
|
this.targetPosition = Vec3.subtract(newPointOnPlane, this.offset);
|
||||||
actionArgs = {targetPosition: gTargetPosition, linearTimeScale: 0.1};
|
actionArgs = {targetPosition: this.targetPosition, linearTimeScale: 0.1};
|
||||||
}
|
|
||||||
gPreviousMouse = { x: event.x, y: event.y };
|
|
||||||
gMouseCursorLocation = { x: Window.getCursorPositionX(), y: Window.getCursorPositionY() };
|
|
||||||
|
|
||||||
if (!gActionID) {
|
beacon.updatePosition(this.targetPosition);
|
||||||
gActionID = Entities.addAction("spring", gGrabbedEntity, actionArgs);
|
}
|
||||||
|
|
||||||
|
if (!this.actionID) {
|
||||||
|
this.actionID = Entities.addAction("spring", this.entityID, actionArgs);
|
||||||
} else {
|
} else {
|
||||||
Entities.updateAction(gGrabbedEntity, gActionID, actionArgs);
|
Entities.updateAction(this.entityID, this.actionID, actionArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDropLine(gTargetPosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function keyReleaseEvent(event) {
|
Grabber.prototype.keyReleaseEvent = function(event) {
|
||||||
if (event.text === "SHIFT") {
|
if (event.text === "SHIFT") {
|
||||||
gLiftKey = false;
|
this.liftKey = false;
|
||||||
}
|
}
|
||||||
if (event.text === "CONTROL") {
|
if (event.text === "CONTROL") {
|
||||||
gRotateKey = false;
|
this.rotateKey = false;
|
||||||
}
|
}
|
||||||
computeNewGrabPlane();
|
this.computeNewGrabPlane();
|
||||||
|
}
|
||||||
|
|
||||||
|
Grabber.prototype.keyPressEvent = function(event) {
|
||||||
|
if (event.text === "SHIFT") {
|
||||||
|
this.liftKey = true;
|
||||||
|
}
|
||||||
|
if (event.text === "CONTROL") {
|
||||||
|
this.rotateKey = true;
|
||||||
|
}
|
||||||
|
this.computeNewGrabPlane();
|
||||||
|
}
|
||||||
|
|
||||||
|
var grabber = new Grabber();
|
||||||
|
|
||||||
|
function pressEvent(event) {
|
||||||
|
grabber.pressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveEvent(event) {
|
||||||
|
grabber.moveEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function releaseEvent(event) {
|
||||||
|
grabber.releaseEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function keyPressEvent(event) {
|
function keyPressEvent(event) {
|
||||||
if (event.text === "SHIFT") {
|
grabber.keyPressEvent(event);
|
||||||
gLiftKey = true;
|
|
||||||
}
|
|
||||||
if (event.text === "CONTROL") {
|
|
||||||
gRotateKey = true;
|
|
||||||
}
|
|
||||||
computeNewGrabPlane();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
function keyReleaseEvent(event) {
|
||||||
Controller.mousePressEvent.connect(mousePressEvent);
|
grabber.keyReleaseEvent(event);
|
||||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
}
|
||||||
|
|
||||||
|
Controller.mousePressEvent.connect(pressEvent);
|
||||||
|
Controller.mouseMoveEvent.connect(moveEvent);
|
||||||
|
Controller.mouseReleaseEvent.connect(releaseEvent);
|
||||||
Controller.keyPressEvent.connect(keyPressEvent);
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||||
|
|
Loading…
Reference in a new issue