mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 14:37:46 +02:00
convert grab.js to use spring action. rotation doesn't work right, yet
This commit is contained in:
parent
eb85f7f818
commit
14a45e8349
3 changed files with 65 additions and 39 deletions
|
@ -4,7 +4,7 @@
|
||||||
// Created by Eric Levin on May 1, 2015
|
// Created by Eric Levin on May 1, 2015
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Grab's physically moveable entities with the mouse, by applying a spring force.
|
// Grab's physically moveable entities with the mouse, by applying a spring force.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// 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
|
||||||
|
@ -20,6 +20,7 @@ var ANGULAR_DAMPING_RATE = 0.40;
|
||||||
// NOTE: to improve readability global variable names start with 'g'
|
// NOTE: to improve readability global variable names start with 'g'
|
||||||
var gIsGrabbing = false;
|
var gIsGrabbing = false;
|
||||||
var gGrabbedEntity = null;
|
var gGrabbedEntity = null;
|
||||||
|
var gActionID = null;
|
||||||
var gPrevMouse = {x: 0, y: 0};
|
var gPrevMouse = {x: 0, y: 0};
|
||||||
var gEntityProperties;
|
var gEntityProperties;
|
||||||
var gStartPosition;
|
var gStartPosition;
|
||||||
|
@ -31,20 +32,20 @@ var gPlaneNormal = ZERO_VEC3;
|
||||||
// gMaxGrabDistance is a function of the size of the object.
|
// gMaxGrabDistance is a function of the size of the object.
|
||||||
var gMaxGrabDistance;
|
var gMaxGrabDistance;
|
||||||
|
|
||||||
// gGrabMode defines the degrees of freedom of the grab target positions
|
// gGrabMode defines the degrees of freedom of the grab target positions
|
||||||
// relative to gGrabStartPosition options include:
|
// relative to gGrabStartPosition options include:
|
||||||
// xzPlane (default)
|
// xzPlane (default)
|
||||||
// verticalCylinder (SHIFT)
|
// verticalCylinder (SHIFT)
|
||||||
// rotate (CONTROL)
|
// rotate (CONTROL)
|
||||||
// Modes to eventually support?:
|
// Modes to eventually support?:
|
||||||
// xyPlane
|
// xyPlane
|
||||||
// yzPlane
|
// yzPlane
|
||||||
// polar
|
// polar
|
||||||
// elevationAzimuth
|
// elevationAzimuth
|
||||||
var gGrabMode = "xzplane";
|
var gGrabMode = "xzplane";
|
||||||
|
|
||||||
// gGrabOffset allows the user to grab an object off-center. It points from ray's intersection
|
// gGrabOffset allows the user to grab an object off-center. It points from ray's intersection
|
||||||
// with the move-plane to object center (at the moment the grab is initiated). Future target positions
|
// with the move-plane to object center (at the moment the grab is initiated). Future target positions
|
||||||
// are relative to the ray's intersection by the same offset.
|
// are relative to the ray's intersection by the same offset.
|
||||||
var gGrabOffset = { x: 0, y: 0, z: 0 };
|
var gGrabOffset = { x: 0, y: 0, z: 0 };
|
||||||
|
|
||||||
|
@ -162,7 +163,7 @@ function computeNewGrabPlane() {
|
||||||
var xzOffset = Vec3.subtract(gPointOnPlane, Camera.getPosition());
|
var xzOffset = Vec3.subtract(gPointOnPlane, Camera.getPosition());
|
||||||
xzOffset.y = 0;
|
xzOffset.y = 0;
|
||||||
gXzDistanceToGrab = Vec3.length(xzOffset);
|
gXzDistanceToGrab = Vec3.length(xzOffset);
|
||||||
|
|
||||||
if (gGrabMode !== "rotate" && maybeResetMousePosition) {
|
if (gGrabMode !== "rotate" && maybeResetMousePosition) {
|
||||||
// we reset the mouse position whenever we stop rotating
|
// we reset the mouse position whenever we stop rotating
|
||||||
Window.setCursorPosition(gMouseAtRotateStart.x, gMouseAtRotateStart.y);
|
Window.setCursorPosition(gMouseAtRotateStart.x, gMouseAtRotateStart.y);
|
||||||
|
@ -193,6 +194,7 @@ function mousePressEvent(event) {
|
||||||
var cameraPosition = Camera.getPosition();
|
var cameraPosition = Camera.getPosition();
|
||||||
|
|
||||||
gBeaconHeight = Vec3.length(entityProperties.dimensions);
|
gBeaconHeight = Vec3.length(entityProperties.dimensions);
|
||||||
|
print("gBeaconHeight = " + gBeaconHeight);
|
||||||
gMaxGrabDistance = gBeaconHeight / MAX_SOLID_ANGLE;
|
gMaxGrabDistance = gBeaconHeight / MAX_SOLID_ANGLE;
|
||||||
if (Vec3.distance(objectPosition, cameraPosition) > gMaxGrabDistance) {
|
if (Vec3.distance(objectPosition, cameraPosition) > gMaxGrabDistance) {
|
||||||
// don't allow grabs of things far away
|
// don't allow grabs of things far away
|
||||||
|
@ -231,6 +233,8 @@ function mouseReleaseEvent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
gIsGrabbing = false
|
gIsGrabbing = false
|
||||||
|
Entities.deleteAction(grabbedEntity, gActionID);
|
||||||
|
gActionID = null;
|
||||||
|
|
||||||
Overlays.editOverlay(gBeacon, { visible: false });
|
Overlays.editOverlay(gBeacon, { visible: false });
|
||||||
|
|
||||||
|
@ -250,6 +254,8 @@ function mouseMoveEvent(event) {
|
||||||
gOriginalGravity = entityProperties.gravity;
|
gOriginalGravity = entityProperties.gravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var actionArgs;
|
||||||
|
|
||||||
if (gGrabMode === "rotate") {
|
if (gGrabMode === "rotate") {
|
||||||
var deltaMouse = { x: 0, y: 0 };
|
var deltaMouse = { x: 0, y: 0 };
|
||||||
var dx = event.x - gPreviousMouse.x;
|
var dx = event.x - gPreviousMouse.x;
|
||||||
|
@ -259,9 +265,12 @@ function mouseMoveEvent(event) {
|
||||||
var dragOffset = Vec3.multiply(dx, Quat.getRight(orientation));
|
var dragOffset = Vec3.multiply(dx, Quat.getRight(orientation));
|
||||||
dragOffset = Vec3.sum(dragOffset, Vec3.multiply(-dy, Quat.getUp(orientation)));
|
dragOffset = Vec3.sum(dragOffset, Vec3.multiply(-dy, Quat.getUp(orientation)));
|
||||||
var axis = Vec3.cross(dragOffset, Quat.getFront(orientation));
|
var axis = Vec3.cross(dragOffset, Quat.getFront(orientation));
|
||||||
var axis = Vec3.normalize(axis);
|
// var axis = Vec3.normalize(axis);
|
||||||
var ROTATE_STRENGTH = 8.0; // magic number tuned by hand
|
// var ROTATE_STRENGTH = 8.0; // magic number tuned by hand
|
||||||
gAngularVelocity = Vec3.multiply(ROTATE_STRENGTH, axis);
|
// gAngularVelocity = Vec3.multiply(ROTATE_STRENGTH, axis);
|
||||||
|
|
||||||
|
var targetRotation = Quat.angleAxis(Vec3.length(axis), Vec3.normalize(axis));
|
||||||
|
actionArgs = {targetRotation: targetRotation, angularTimeScale: 1.0};
|
||||||
} else {
|
} else {
|
||||||
var newTargetPosition;
|
var newTargetPosition;
|
||||||
if (gGrabMode === "verticalCylinder") {
|
if (gGrabMode === "verticalCylinder") {
|
||||||
|
@ -284,9 +293,18 @@ function mouseMoveEvent(event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gTargetPosition = Vec3.sum(newTargetPosition, gGrabOffset);
|
gTargetPosition = Vec3.sum(newTargetPosition, gGrabOffset);
|
||||||
|
actionArgs = {targetPosition: gTargetPosition, linearTimeScale: 0.1};
|
||||||
}
|
}
|
||||||
gPreviousMouse = { x: event.x, y: event.y };
|
gPreviousMouse = { x: event.x, y: event.y };
|
||||||
gMouseCursorLocation = { x: Window.getCursorPositionX(), y: Window.getCursorPositionY() };
|
gMouseCursorLocation = { x: Window.getCursorPositionX(), y: Window.getCursorPositionY() };
|
||||||
|
|
||||||
|
if (!gActionID) {
|
||||||
|
gActionID = Entities.addAction("spring", gGrabbedEntity, actionArgs);
|
||||||
|
} else {
|
||||||
|
Entities.updateAction(gGrabbedEntity, gActionID, actionArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDropLine(gTargetPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
function keyReleaseEvent(event) {
|
function keyReleaseEvent(event) {
|
||||||
|
@ -309,38 +327,37 @@ function keyPressEvent(event) {
|
||||||
computeNewGrabPlane();
|
computeNewGrabPlane();
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(deltaTime) {
|
// function update(deltaTime) {
|
||||||
if (!gIsGrabbing) {
|
// if (!gIsGrabbing) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
var entityProperties = Entities.getEntityProperties(gGrabbedEntity);
|
// var entityProperties = Entities.getEntityProperties(gGrabbedEntity);
|
||||||
gCurrentPosition = entityProperties.position;
|
// gCurrentPosition = entityProperties.position;
|
||||||
if (gGrabMode === "rotate") {
|
// if (gGrabMode === "rotate") {
|
||||||
gAngularVelocity = Vec3.subtract(gAngularVelocity, Vec3.multiply(gAngularVelocity, ANGULAR_DAMPING_RATE));
|
// gAngularVelocity = Vec3.subtract(gAngularVelocity, Vec3.multiply(gAngularVelocity, ANGULAR_DAMPING_RATE));
|
||||||
Entities.editEntity(gGrabbedEntity, { angularVelocity: gAngularVelocity, });
|
// Entities.editEntity(gGrabbedEntity, { angularVelocity: gAngularVelocity, });
|
||||||
}
|
// }
|
||||||
|
|
||||||
// always push toward linear grab position, even when rotating
|
// // always push toward linear grab position, even when rotating
|
||||||
var newVelocity = ZERO_VEC3;
|
// var newVelocity = ZERO_VEC3;
|
||||||
var dPosition = Vec3.subtract(gTargetPosition, gCurrentPosition);
|
// var dPosition = Vec3.subtract(gTargetPosition, gCurrentPosition);
|
||||||
var delta = Vec3.length(dPosition);
|
// var delta = Vec3.length(dPosition);
|
||||||
if (delta > CLOSE_ENOUGH) {
|
// if (delta > CLOSE_ENOUGH) {
|
||||||
var MAX_POSITION_DELTA = 4.0;
|
// var MAX_POSITION_DELTA = 4.0;
|
||||||
if (delta > MAX_POSITION_DELTA) {
|
// if (delta > MAX_POSITION_DELTA) {
|
||||||
dPosition = Vec3.multiply(dPosition, MAX_POSITION_DELTA / delta);
|
// dPosition = Vec3.multiply(dPosition, MAX_POSITION_DELTA / delta);
|
||||||
}
|
// }
|
||||||
// desired speed is proportional to displacement by the inverse of timescale
|
// // desired speed is proportional to displacement by the inverse of timescale
|
||||||
// (for critically damped motion)
|
// // (for critically damped motion)
|
||||||
newVelocity = Vec3.multiply(dPosition, INV_MOVE_TIMESCALE);
|
// newVelocity = Vec3.multiply(dPosition, INV_MOVE_TIMESCALE);
|
||||||
}
|
// }
|
||||||
Entities.editEntity(gGrabbedEntity, { velocity: newVelocity, });
|
// Entities.editEntity(gGrabbedEntity, { velocity: newVelocity, });
|
||||||
updateDropLine(gTargetPosition);
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||||
Controller.mousePressEvent.connect(mousePressEvent);
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||||
Controller.keyPressEvent.connect(keyPressEvent);
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||||
Script.update.connect(update);
|
// Script.update.connect(update);
|
||||||
|
|
|
@ -28,6 +28,10 @@ ObjectActionPullToPoint::~ObjectActionPullToPoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectActionPullToPoint::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
|
void ObjectActionPullToPoint::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
|
||||||
|
if (!_ownerEntity) {
|
||||||
|
qDebug() << "ObjectActionPullToPoint::updateAction no owner entity";
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!tryLockForRead()) {
|
if (!tryLockForRead()) {
|
||||||
// don't risk hanging the thread running the physics simulation
|
// don't risk hanging the thread running the physics simulation
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -28,6 +28,10 @@ ObjectActionSpring::~ObjectActionSpring() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectActionSpring::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
|
void ObjectActionSpring::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
|
||||||
|
if (!_ownerEntity) {
|
||||||
|
qDebug() << "ObjectActionSpring::updateAction no owner entity";
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!tryLockForRead()) {
|
if (!tryLockForRead()) {
|
||||||
// don't risk hanging the thread running the physics simulation
|
// don't risk hanging the thread running the physics simulation
|
||||||
return;
|
return;
|
||||||
|
@ -111,6 +115,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
||||||
|
|
||||||
if (rtOk) {
|
if (rtOk) {
|
||||||
_rotationalTarget = rotationalTarget;
|
_rotationalTarget = rotationalTarget;
|
||||||
|
_rotationalTargetSet = true;
|
||||||
|
|
||||||
if (rscOk) {
|
if (rscOk) {
|
||||||
_angularTimeScale = angularTimeScale;
|
_angularTimeScale = angularTimeScale;
|
||||||
|
|
Loading…
Reference in a new issue