From 7f841b3828d78d144b21dea7b5ef7bf1c33c67dc Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 1 Oct 2015 17:55:47 -0700 Subject: [PATCH 01/20] prevent most other-hand accidental firing --- examples/toys/ping_pong_gun/pingPongGun.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index a980fc1bd3..8610c48a96 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -84,6 +84,7 @@ var _t = this; this.canShootTimeout = Script.setTimeout(function() { _t.canShoot = false; + _t.whichHand=null; }, 250) }, @@ -97,7 +98,7 @@ if (this.triggerValue < RELOAD_THRESHOLD) { // print('RELOAD'); this.canShoot = true; - } else if (this.triggerValue >= RELOAD_THRESHOLD && this.canShoot === true) { + } else if (this.triggerValue >= RELOAD_THRESHOLD && this.canShoot === true && this.hand === this.whichHand) { var gunProperties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); this.shootBall(gunProperties); this.canShoot = false; From 6131875f674637ef052cf1ab6df7a44617892dfc Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 1 Oct 2015 18:49:07 -0700 Subject: [PATCH 02/20] set whichhand to null on release --- examples/toys/ping_pong_gun/pingPongGun.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 8610c48a96..1616d9c7e2 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -82,10 +82,15 @@ releaseGrab: function() { var _t = this; - this.canShootTimeout = Script.setTimeout(function() { - _t.canShoot = false; - _t.whichHand=null; - }, 250) + + if (this.whichHand === this.hand) { + _t.whichHand = null; + this.canShootTimeout = Script.setTimeout(function() { + _t.canShoot = false; + + }, 250) + } + }, checkTriggerPressure: function(gunHand) { From 82828fdd14053fc489fcf7acae5b371adf95080e Mon Sep 17 00:00:00 2001 From: James Pollack Date: Fri, 2 Oct 2015 10:41:49 -0700 Subject: [PATCH 03/20] reduce gravity and gun force so ball goes through less objects --- examples/toys/ping_pong_gun/pingPongGun.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 1616d9c7e2..7afb467eb0 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -23,12 +23,12 @@ var RELOAD_THRESHOLD = 0.95; var GUN_TIP_FWD_OFFSET = 0.45; var GUN_TIP_UP_OFFSET = 0.040; - var GUN_FORCE = 15; + var GUN_FORCE = 8; var BALL_RESTITUTION = 0.6; var BALL_LINEAR_DAMPING = 0.4; var BALL_GRAVITY = { x: 0, - y: -9.8, + y: -5.8, z: 0 }; From c6fa132dc2d88f29a547f7b000f076dd755adba5 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Fri, 2 Oct 2015 10:44:26 -0700 Subject: [PATCH 04/20] cleanup --- examples/toys/ping_pong_gun/pingPongGun.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 7afb467eb0..b3545ce529 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -36,14 +36,14 @@ x: 0.04, y: 0.04, z: 0.04 - } + }; var BALL_COLOR = { red: 255, green: 255, blue: 255 - } + }; PingPongGun.prototype = { hand: null, @@ -87,8 +87,7 @@ _t.whichHand = null; this.canShootTimeout = Script.setTimeout(function() { _t.canShoot = false; - - }, 250) + }, 250); } }, From cf8955a8c5801dbf38f62926861030752b745dce Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 15:27:01 -0700 Subject: [PATCH 05/20] kinematic grab --- interface/src/InterfaceActionFactory.cpp | 3 + .../src/avatar/AvatarActionKinematicHold.cpp | 162 ++++++++++++++++++ .../src/avatar/AvatarActionKinematicHold.h | 41 +++++ .../entities/src/EntityActionInterface.cpp | 5 + .../entities/src/EntityActionInterface.h | 3 +- 5 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 interface/src/avatar/AvatarActionKinematicHold.cpp create mode 100644 interface/src/avatar/AvatarActionKinematicHold.h diff --git a/interface/src/InterfaceActionFactory.cpp b/interface/src/InterfaceActionFactory.cpp index 2879c19eaa..b4bd7c45ae 100644 --- a/interface/src/InterfaceActionFactory.cpp +++ b/interface/src/InterfaceActionFactory.cpp @@ -12,6 +12,7 @@ #include +#include #include #include @@ -28,6 +29,8 @@ EntityActionPointer interfaceActionFactory(EntityActionType type, const QUuid& i return (EntityActionPointer) new ObjectActionSpring(id, ownerEntity); case ACTION_TYPE_HOLD: return (EntityActionPointer) new AvatarActionHold(id, ownerEntity); + case ACTION_TYPE_KINEMATIC_HOLD: + return (EntityActionPointer) new AvatarActionKinematicHold(id, ownerEntity); } assert(false); diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp new file mode 100644 index 0000000000..14b80efd64 --- /dev/null +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -0,0 +1,162 @@ +// +// AvatarActionKinematicHold.cpp +// interface/src/avatar/ +// +// Created by Seth Alves 2015-6-9 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "QVariantGLM.h" +#include "avatar/MyAvatar.h" +#include "avatar/AvatarManager.h" + +#include "AvatarActionKinematicHold.h" + +const uint16_t AvatarActionKinematicHold::holdVersion = 1; + +AvatarActionKinematicHold::AvatarActionKinematicHold(const QUuid& id, EntityItemPointer ownerEntity) : + ObjectActionSpring(id, ownerEntity), + _relativePosition(glm::vec3(0.0f)), + _relativeRotation(glm::quat()), + _hand("right"), + _mine(false) +{ + _type = ACTION_TYPE_HOLD; + #if WANT_DEBUG + qDebug() << "AvatarActionKinematicHold::AvatarActionKinematicHold"; + #endif +} + +AvatarActionKinematicHold::~AvatarActionKinematicHold() { + #if WANT_DEBUG + qDebug() << "AvatarActionKinematicHold::~AvatarActionKinematicHold"; + #endif +} + +void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { + if (!_mine) { + // if a local script isn't updating this, then we are just getting spring-action data over the wire. + // let the super-class handle it. + ObjectActionSpring::updateActionWorker(deltaTimeStep); + return; + } + + glm::quat rotation; + glm::vec3 position; + glm::vec3 offset; + bool gotLock = withTryReadLock([&]{ + auto myAvatar = DependencyManager::get()->getMyAvatar(); + glm::vec3 palmPosition; + glm::quat palmRotation; + if (_hand == "right") { + palmPosition = myAvatar->getRightPalmPosition(); + palmRotation = myAvatar->getRightPalmRotation(); + } else { + palmPosition = myAvatar->getLeftPalmPosition(); + palmRotation = myAvatar->getLeftPalmRotation(); + } + + rotation = palmRotation * _relativeRotation; + offset = rotation * _relativePosition; + position = palmPosition + offset; + }); + + if (gotLock) { + gotLock = withTryWriteLock([&]{ + if (_positionalTarget != position || _rotationalTarget != rotation) { + _positionalTarget = position; + _rotationalTarget = rotation; + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setActionDataDirty(true); + void* physicsInfo = ownerEntity->getPhysicsInfo(); + if (physicsInfo) { + ObjectMotionState* motionState = static_cast(physicsInfo); + btRigidBody* rigidBody = motionState->getRigidBody(); + if (!rigidBody) { + qDebug() << "ObjectActionSpring::updateActionWorker no rigidBody"; + return; + } + + btTransform worldTrans; + worldTrans.setOrigin(glmToBullet(_positionalTarget)); + worldTrans.setRotation(glmToBullet(_rotationalTarget)); + rigidBody->setWorldTransform(worldTrans); + } + } + } + }); + } + + if (gotLock) { + ObjectActionSpring::updateActionWorker(deltaTimeStep); + } +} + + +bool AvatarActionKinematicHold::updateArguments(QVariantMap arguments) { + if (!ObjectAction::updateArguments(arguments)) { + return false; + } + bool ok = true; + glm::vec3 relativePosition = + EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); + if (!ok) { + relativePosition = _relativePosition; + } + + ok = true; + glm::quat relativeRotation = + EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false); + if (!ok) { + relativeRotation = _relativeRotation; + } + + ok = true; + QString hand = + EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false); + if (!ok || !(hand == "left" || hand == "right")) { + hand = _hand; + } + + if (relativePosition != _relativePosition + || relativeRotation != _relativeRotation + || hand != _hand) { + withWriteLock([&] { + _relativePosition = relativePosition; + _relativeRotation = relativeRotation; + _hand = hand; + + _mine = true; + _active = true; + activateBody(); + }); + } + return true; +} + + +QVariantMap AvatarActionKinematicHold::getArguments() { + QVariantMap arguments = ObjectAction::getArguments(); + withReadLock([&]{ + if (!_mine) { + arguments = ObjectActionSpring::getArguments(); + return; + } + + arguments["relativePosition"] = glmToQMap(_relativePosition); + arguments["relativeRotation"] = glmToQMap(_relativeRotation); + arguments["hand"] = _hand; + }); + return arguments; +} + + +void AvatarActionKinematicHold::deserialize(QByteArray serializedArguments) { + if (!_mine) { + ObjectActionSpring::deserialize(serializedArguments); + } +} diff --git a/interface/src/avatar/AvatarActionKinematicHold.h b/interface/src/avatar/AvatarActionKinematicHold.h new file mode 100644 index 0000000000..6bd7dca01a --- /dev/null +++ b/interface/src/avatar/AvatarActionKinematicHold.h @@ -0,0 +1,41 @@ +// +// AvatarActionKinematicHold.h +// interface/src/avatar/ +// +// Created by Seth Alves 2015-10-2 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AvatarActionKinematicHold_h +#define hifi_AvatarActionKinematicHold_h + +#include + +#include +#include + +class AvatarActionKinematicHold : public ObjectActionSpring { +public: + AvatarActionKinematicHold(const QUuid& id, EntityItemPointer ownerEntity); + virtual ~AvatarActionKinematicHold(); + + virtual bool updateArguments(QVariantMap arguments); + virtual QVariantMap getArguments(); + + virtual void updateActionWorker(float deltaTimeStep); + + virtual void deserialize(QByteArray serializedArguments); + +private: + static const uint16_t holdVersion; + + glm::vec3 _relativePosition; + glm::quat _relativeRotation; + QString _hand; + bool _mine = false; +}; + +#endif // hifi_AvatarActionKinematicHold_h diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityActionInterface.cpp index ba7f3afea4..d821dcdc2f 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityActionInterface.cpp @@ -100,6 +100,9 @@ EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeS if (normalizedActionTypeString == "hold") { return ACTION_TYPE_HOLD; } + if (normalizedActionTypeString == "kinematic-hold") { + return ACTION_TYPE_KINEMATIC_HOLD; + } qDebug() << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString; return ACTION_TYPE_NONE; @@ -115,6 +118,8 @@ QString EntityActionInterface::actionTypeToString(EntityActionType actionType) { return "spring"; case ACTION_TYPE_HOLD: return "hold"; + case ACTION_TYPE_KINEMATIC_HOLD: + return "kinematic-hold"; } assert(false); return "none"; diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index e61019c98c..567b88d4b0 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -23,7 +23,8 @@ enum EntityActionType { ACTION_TYPE_NONE = 0, ACTION_TYPE_OFFSET = 1000, ACTION_TYPE_SPRING = 2000, - ACTION_TYPE_HOLD = 3000 + ACTION_TYPE_HOLD = 3000, + ACTION_TYPE_KINEMATIC_HOLD = 4000 }; From 9427ba1a5ac38d9569ddfe2f4c482fe33c566544 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Fri, 2 Oct 2015 15:56:26 -0700 Subject: [PATCH 06/20] ping pong gun --- examples/toys/ping_pong_gun/createPingPongGun.js | 12 ++++++------ examples/toys/ping_pong_gun/pingPongGun.js | 11 +++++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/toys/ping_pong_gun/createPingPongGun.js b/examples/toys/ping_pong_gun/createPingPongGun.js index 4b7ed27643..4969a0bc72 100644 --- a/examples/toys/ping_pong_gun/createPingPongGun.js +++ b/examples/toys/ping_pong_gun/createPingPongGun.js @@ -13,8 +13,8 @@ Script.include("../../utilities.js"); var scriptURL = Script.resolvePath('pingPongGun.js'); -var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx' -var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; +var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx?123' +var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj?123'; var center = Vec3.sum(Vec3.sum(MyAvatar.position, { x: 0, @@ -30,9 +30,9 @@ var pingPongGun = Entities.addEntity({ script: scriptURL, position: center, dimensions: { - x:0.67, - y: 0.14, - z: 0.09 + x: 0.08, + y: 0.21, + z: 0.47 }, collisionsWillMove: true, }); @@ -40,4 +40,4 @@ var pingPongGun = Entities.addEntity({ function cleanUp() { Entities.deleteEntity(pingPongGun); } -Script.scriptEnding.connect(cleanUp); +Script.scriptEnding.connect(cleanUp); \ No newline at end of file diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index b3545ce529..298d93a523 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -81,15 +81,14 @@ }, releaseGrab: function() { - var _t = this; + var _this = this; if (this.whichHand === this.hand) { - _t.whichHand = null; + this.whichHand = null; this.canShootTimeout = Script.setTimeout(function() { - _t.canShoot = false; + _this.canShoot = false; }, 250); } - }, checkTriggerPressure: function(gunHand) { @@ -107,6 +106,7 @@ this.shootBall(gunProperties); this.canShoot = false; } + return; }, @@ -114,6 +114,7 @@ var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, -90, 0))); forwardVec = Vec3.normalize(forwardVec); forwardVec = Vec3.multiply(forwardVec, GUN_FORCE); + var properties = { type: 'Sphere', color: BALL_COLOR, @@ -148,8 +149,10 @@ var frontOffset = Vec3.multiply(frontVector, GUN_TIP_FWD_OFFSET); var upVector = Quat.getRight(properties.rotation); var upOffset = Vec3.multiply(upVector, GUN_TIP_UP_OFFSET); + var gunTipPosition = Vec3.sum(properties.position, frontOffset); gunTipPosition = Vec3.sum(gunTipPosition, upOffset); + return gunTipPosition; }, From 01044e3c056178c28b7ed1f9e8d5d351f18e7764 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Fri, 2 Oct 2015 15:57:46 -0700 Subject: [PATCH 07/20] adjust gun dimensions in toybox master script --- unpublishedScripts/masterReset.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index d6759e2b48..13445ca438 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -98,7 +98,7 @@ function createAllToys() { function deleteAllToys() { var entities = Entities.findEntities(MyAvatar.position, 100); - entities.forEach(function (entity) { + entities.forEach(function(entity) { //params: customKey, id, defaultValue var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; if (shouldReset === true) { @@ -468,9 +468,9 @@ function createPingPongBallGun() { z: 0 }, dimensions: { - x: 0.67, - y: 0.14, - z: 0.09 + x: 0.08, + y: 0.21, + z: 0.47 }, collisionsWillMove: true, }); @@ -831,4 +831,4 @@ function cleanup() { if (shouldDeleteOnEndScript) { Script.scriptEnding.connect(cleanup); -} +} \ No newline at end of file From 89c848d8c8c4351d656361f8a6c0fbdd2ba02be9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 17:14:53 -0700 Subject: [PATCH 08/20] fix up kinematic hold --- examples/controllers/handControllerGrab.js | 2 +- .../src/avatar/AvatarActionKinematicHold.cpp | 24 +++++++++++++++++-- .../src/avatar/AvatarActionKinematicHold.h | 4 ++++ .../entities/src/EntityActionInterface.cpp | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 5705bd4498..a8a95cb4ca 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -444,7 +444,7 @@ function MyController(hand, triggerAction) { var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset); this.actionID = NULL_ACTION_ID; - this.actionID = Entities.addAction("hold", this.grabbedEntity, { + this.actionID = Entities.addAction("kinematic-hold", this.grabbedEntity, { hand: this.hand === RIGHT_HAND ? "right" : "left", timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, relativePosition: offsetPosition, diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index 14b80efd64..e890d8cbd8 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -22,7 +22,9 @@ AvatarActionKinematicHold::AvatarActionKinematicHold(const QUuid& id, EntityItem _relativePosition(glm::vec3(0.0f)), _relativeRotation(glm::quat()), _hand("right"), - _mine(false) + _mine(false), + _previousPositionalTarget(Vectors::ZERO), + _previousRotationalTarget(Quaternions::IDENTITY) { _type = ACTION_TYPE_HOLD; #if WANT_DEBUG @@ -44,6 +46,10 @@ void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { return; } + if (deltaTimeStep <= 0.0f) { + return; + } + glm::quat rotation; glm::vec3 position; glm::vec3 offset; @@ -81,10 +87,24 @@ void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { return; } - btTransform worldTrans; + btTransform worldTrans = rigidBody->getWorldTransform(); worldTrans.setOrigin(glmToBullet(_positionalTarget)); worldTrans.setRotation(glmToBullet(_rotationalTarget)); rigidBody->setWorldTransform(worldTrans); + + if (_previousSet) { + glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep; + rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); + + glm::quat rotationalDelta = glm::inverse(_previousRotationalTarget) * _rotationalTarget; + glm::vec3 rotationalDeltaAxis = glm::axis(rotationalDelta); + float rotationalDeltaAngle = glm::angle(rotationalDelta); + glm::vec3 rotationalVelocity = glm::normalize(rotationalDeltaAxis) * rotationalDeltaAngle / deltaTimeStep; + rigidBody->setAngularVelocity(glmToBullet(rotationalVelocity)); + } + _previousPositionalTarget = _positionalTarget; + _previousRotationalTarget = _rotationalTarget; + _previousSet = true; } } } diff --git a/interface/src/avatar/AvatarActionKinematicHold.h b/interface/src/avatar/AvatarActionKinematicHold.h index 6bd7dca01a..95e9605c2b 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.h +++ b/interface/src/avatar/AvatarActionKinematicHold.h @@ -36,6 +36,10 @@ private: glm::quat _relativeRotation; QString _hand; bool _mine = false; + + bool _previousSet = false; + glm::vec3 _previousPositionalTarget; + glm::quat _previousRotationalTarget; }; #endif // hifi_AvatarActionKinematicHold_h diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityActionInterface.cpp index d821dcdc2f..25f61fcf25 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityActionInterface.cpp @@ -100,7 +100,7 @@ EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeS if (normalizedActionTypeString == "hold") { return ACTION_TYPE_HOLD; } - if (normalizedActionTypeString == "kinematic-hold") { + if (normalizedActionTypeString == "kinematichold") { return ACTION_TYPE_KINEMATIC_HOLD; } From 6a770a870b98be3d9120d50fcfcd3ad0fd7fc026 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 17:31:45 -0700 Subject: [PATCH 09/20] set correct type in kinematic hold --- interface/src/avatar/AvatarActionKinematicHold.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index e890d8cbd8..21f2989299 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -26,7 +26,7 @@ AvatarActionKinematicHold::AvatarActionKinematicHold(const QUuid& id, EntityItem _previousPositionalTarget(Vectors::ZERO), _previousRotationalTarget(Quaternions::IDENTITY) { - _type = ACTION_TYPE_HOLD; + _type = ACTION_TYPE_KINEMATIC_HOLD; #if WANT_DEBUG qDebug() << "AvatarActionKinematicHold::AvatarActionKinematicHold"; #endif @@ -95,12 +95,6 @@ void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { if (_previousSet) { glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep; rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); - - glm::quat rotationalDelta = glm::inverse(_previousRotationalTarget) * _rotationalTarget; - glm::vec3 rotationalDeltaAxis = glm::axis(rotationalDelta); - float rotationalDeltaAngle = glm::angle(rotationalDelta); - glm::vec3 rotationalVelocity = glm::normalize(rotationalDeltaAxis) * rotationalDeltaAngle / deltaTimeStep; - rigidBody->setAngularVelocity(glmToBullet(rotationalVelocity)); } _previousPositionalTarget = _positionalTarget; _previousRotationalTarget = _rotationalTarget; @@ -123,21 +117,21 @@ bool AvatarActionKinematicHold::updateArguments(QVariantMap arguments) { } bool ok = true; glm::vec3 relativePosition = - EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); + EntityActionInterface::extractVec3Argument("kinematic-hold", arguments, "relativePosition", ok, false); if (!ok) { relativePosition = _relativePosition; } ok = true; glm::quat relativeRotation = - EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false); + EntityActionInterface::extractQuatArgument("kinematic-hold", arguments, "relativeRotation", ok, false); if (!ok) { relativeRotation = _relativeRotation; } ok = true; QString hand = - EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false); + EntityActionInterface::extractStringArgument("kinematic-hold", arguments, "hand", ok, false); if (!ok || !(hand == "left" || hand == "right")) { hand = _hand; } From 26310d8ce421369193be808b451cf09d7418c787 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 17:54:09 -0700 Subject: [PATCH 10/20] kill gravity in near-held objects --- examples/controllers/handControllerGrab.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index a8a95cb4ca..d143df1e83 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -431,7 +431,7 @@ function MyController(hand, triggerAction) { this.activateEntity(this.grabbedEntity); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity"]); var handRotation = this.getHandRotation(); var handPosition = this.getHandPosition(); @@ -443,6 +443,9 @@ function MyController(hand, triggerAction) { var offset = Vec3.subtract(currentObjectPosition, handPosition); var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset); + this.saveGravity = grabbedProperties.gravity; + Entities.editEntity(this.grabbedEntity, {gravity: {x:0, y:0, z:0}}); + this.actionID = NULL_ACTION_ID; this.actionID = Entities.addAction("kinematic-hold", this.grabbedEntity, { hand: this.hand === RIGHT_HAND ? "right" : "left", @@ -472,6 +475,7 @@ function MyController(hand, triggerAction) { this.continueNearGrabbing = function() { if (this.triggerSmoothedReleased()) { this.state = STATE_RELEASE; + Entities.editEntity(this.grabbedEntity, {gravity: this.saveGravity}); return; } From 65ae811c9c50a4200d85686f1d0d40f1ec02da76 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 5 Oct 2015 11:16:55 -0700 Subject: [PATCH 11/20] make ping pong balls bigger and slower, change out gun model and adjust tip calculations, increase volume, add to master reset script --- .../toys/ping_pong_gun/createPingPongGun.js | 5 +++-- examples/toys/ping_pong_gun/pingPongGun.js | 17 ++++++++--------- unpublishedScripts/masterReset.js | 5 +---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/examples/toys/ping_pong_gun/createPingPongGun.js b/examples/toys/ping_pong_gun/createPingPongGun.js index 4969a0bc72..cf56d6f790 100644 --- a/examples/toys/ping_pong_gun/createPingPongGun.js +++ b/examples/toys/ping_pong_gun/createPingPongGun.js @@ -25,8 +25,9 @@ var center = Vec3.sum(Vec3.sum(MyAvatar.position, { var pingPongGun = Entities.addEntity({ type: "Model", modelURL: MODEL_URL, - shapeType: 'compound', - compoundShapeURL: COLLISION_HULL_URL, + shapeType:'box', + // shapeType: 'compound', + // compoundShapeURL: COLLISION_HULL_URL, script: scriptURL, position: center, dimensions: { diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 298d93a523..1b5973c8bb 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -21,14 +21,14 @@ //if the trigger value goes below this value, reload the gun. var RELOAD_THRESHOLD = 0.95; - var GUN_TIP_FWD_OFFSET = 0.45; + var GUN_TIP_FWD_OFFSET =-0.35; var GUN_TIP_UP_OFFSET = 0.040; - var GUN_FORCE = 8; + var GUN_FORCE = 9; var BALL_RESTITUTION = 0.6; var BALL_LINEAR_DAMPING = 0.4; var BALL_GRAVITY = { x: 0, - y: -5.8, + y: -4.8, z: 0 }; @@ -68,7 +68,6 @@ }, continueNearGrab: function() { - if (this.whichHand === null) { //only set the active hand once -- if we always read the current hand, our 'holding' hand will get overwritten this.setWhichHand(); @@ -111,7 +110,7 @@ }, shootBall: function(gunProperties) { - var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, -90, 0))); + var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, 180, 0))); forwardVec = Vec3.normalize(forwardVec); forwardVec = Vec3.multiply(forwardVec, GUN_FORCE); @@ -136,7 +135,7 @@ playSoundAtCurrentPosition: function(position) { var audioProperties = { - volume: 0.1, + volume: 0.2, position: position }; @@ -145,11 +144,11 @@ getGunTipPosition: function(properties) { //the tip of the gun is going to be in a different place than the center, so we move in space relative to the model to find that position - var frontVector = Quat.getRight(properties.rotation); + var frontVector = Quat.getFront(properties.rotation); var frontOffset = Vec3.multiply(frontVector, GUN_TIP_FWD_OFFSET); - var upVector = Quat.getRight(properties.rotation); + var upVector = Quat.getUp(properties.rotation); var upOffset = Vec3.multiply(upVector, GUN_TIP_UP_OFFSET); - + var gunTipPosition = Vec3.sum(properties.position, frontOffset); gunTipPosition = Vec3.sum(gunTipPosition, upOffset); diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 13445ca438..a3d4bcc70d 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -457,8 +457,7 @@ function createPingPongBallGun() { var pingPongGun = Entities.addEntity({ type: "Model", modelURL: MODEL_URL, - shapeType: 'compound', - compoundShapeURL: COLLISION_HULL_URL, + shapeType: 'box', script: scriptURL, position: position, rotation: rotation, @@ -478,8 +477,6 @@ function createPingPongBallGun() { setEntityCustomData(resetKey, pingPongGun, { resetMe: true }); - - } function createBasketballHoop() { From 7f84e882c5537591184d897b9163bbe861a6a8c3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Oct 2015 13:06:39 -0700 Subject: [PATCH 12/20] attempt to keep ignoreForCollisions the same before and after grab --- examples/controllers/handControllerGrab.js | 23 ++++++++++++++++++---- examples/libraries/utils.js | 6 +++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index d143df1e83..eba69c2150 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -81,6 +81,8 @@ var STATE_RELEASE = 8; var GRAB_USER_DATA_KEY = "grabKey"; var GRABBABLE_DATA_KEY = "grabbableKey"; +var GRAVITY_USER_DATA_KEY = "preGrabGravity"; +var IGNORE_FOR_COLLISIONS_USER_DATA_KEY = "preGrabIgnoreForCollisions"; function getTag() { return "grab-" + MyAvatar.sessionUUID; @@ -431,7 +433,8 @@ function MyController(hand, triggerAction) { this.activateEntity(this.grabbedEntity); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity"]); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, + ["position", "rotation", "gravity", "ignoreForCollisions"]); var handRotation = this.getHandRotation(); var handPosition = this.getHandPosition(); @@ -443,8 +446,17 @@ function MyController(hand, triggerAction) { var offset = Vec3.subtract(currentObjectPosition, handPosition); var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset); - this.saveGravity = grabbedProperties.gravity; - Entities.editEntity(this.grabbedEntity, {gravity: {x:0, y:0, z:0}}); + // zero gravity and set ignoreForCollisions to true, but in a way that lets us put them back, after all grabs are done + this.saveGravity = getEntityCustomData(GRAVITY_USER_DATA_KEY, this.grabbedEntity, grabbedProperties.gravity); + setEntityCustomData(GRAVITY_USER_DATA_KEY, this.grabbedEntity, this.saveGravity); + + this.saveIgnoreForCollisions = getEntityCustomData(IGNORE_FOR_COLLISIONS_USER_DATA_KEY, this.grabbedEntity, + grabbedProperties.ignoreForCollisions); + setEntityCustomData(IGNORE_FOR_COLLISIONS_USER_DATA_KEY, this.grabbedEntity, this.saveIgnoreForCollisions); + + print("this.ifc = " + this.saveIgnoreForCollisions + ", props.ifc = " + grabbedProperties.ignoreForCollisions); + + Entities.editEntity(this.grabbedEntity, {gravity: {x:0, y:0, z:0}, ignoreForCollisions: true}); this.actionID = NULL_ACTION_ID; this.actionID = Entities.addAction("kinematic-hold", this.grabbedEntity, { @@ -475,7 +487,10 @@ function MyController(hand, triggerAction) { this.continueNearGrabbing = function() { if (this.triggerSmoothedReleased()) { this.state = STATE_RELEASE; - Entities.editEntity(this.grabbedEntity, {gravity: this.saveGravity}); + Entities.editEntity(this.grabbedEntity, + {gravity: this.saveGravity, ignoreForCollisions: this.saveIgnoreForCollisions}); + setEntityCustomData(IGNORE_FOR_COLLISIONS_USER_DATA_KEY, this.grabbedEntity, null); + setEntityCustomData(GRAVITY_USER_DATA_KEY, this.grabbedEntity, null); return; } diff --git a/examples/libraries/utils.js b/examples/libraries/utils.js index fa0f36cbb1..f876d48777 100644 --- a/examples/libraries/utils.js +++ b/examples/libraries/utils.js @@ -79,7 +79,11 @@ getEntityUserData = function(id) { // Non-destructively modify the user data of an entity. setEntityCustomData = function(customKey, id, data) { var userData = getEntityUserData(id); - userData[customKey] = data; + if (data == null) { + delete userData[customKey]; + } else { + userData[customKey] = data; + } setEntityUserData(id, userData); } From 7f8411d947a714e11d7a3aceb04f8cb2b58d5fc8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Oct 2015 14:15:38 -0700 Subject: [PATCH 13/20] reference count grabs on an entity --- examples/controllers/handControllerGrab.js | 66 +++++++++++----------- examples/grab.js | 49 ++++++++++++---- 2 files changed, 70 insertions(+), 45 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 90b85b15da..cdcb15d9dc 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -79,10 +79,8 @@ var STATE_NEAR_GRABBING_NON_COLLIDING = 6; var STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING = 7; var STATE_RELEASE = 8; -var GRAB_USER_DATA_KEY = "grabKey"; -var GRABBABLE_DATA_KEY = "grabbableKey"; -var GRAVITY_USER_DATA_KEY = "preGrabGravity"; -var IGNORE_FOR_COLLISIONS_USER_DATA_KEY = "preGrabIgnoreForCollisions"; +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js function getTag() { return "grab-" + MyAvatar.sessionUUID; @@ -314,7 +312,8 @@ function MyController(hand, triggerAction) { var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", + "gravity", "ignoreForCollisions"]); // add the action and initialize some variables this.currentObjectPosition = grabbedProperties.position; @@ -338,7 +337,7 @@ function MyController(hand, triggerAction) { if (this.actionID !== null) { this.setState(STATE_CONTINUE_DISTANCE_HOLDING); - this.activateEntity(this.grabbedEntity); + this.activateEntity(this.grabbedEntity, grabbedProperties); if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); } else { @@ -441,10 +440,9 @@ function MyController(hand, triggerAction) { this.lineOff(); - this.activateEntity(this.grabbedEntity); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity", "ignoreForCollisions"]); + this.activateEntity(this.grabbedEntity, grabbedProperties); var handRotation = this.getHandRotation(); var handPosition = this.getHandPosition(); @@ -456,14 +454,6 @@ function MyController(hand, triggerAction) { var offset = Vec3.subtract(currentObjectPosition, handPosition); var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset); - // zero gravity and set ignoreForCollisions to true, but in a way that lets us put them back, after all grabs are done - this.saveGravity = getEntityCustomData(GRAVITY_USER_DATA_KEY, this.grabbedEntity, grabbedProperties.gravity); - setEntityCustomData(GRAVITY_USER_DATA_KEY, this.grabbedEntity, this.saveGravity); - this.saveIgnoreForCollisions = getEntityCustomData(IGNORE_FOR_COLLISIONS_USER_DATA_KEY, this.grabbedEntity, - grabbedProperties.ignoreForCollisions); - setEntityCustomData(IGNORE_FOR_COLLISIONS_USER_DATA_KEY, this.grabbedEntity, this.saveIgnoreForCollisions); - Entities.editEntity(this.grabbedEntity, {gravity: {x:0, y:0, z:0}, ignoreForCollisions: true}); - this.actionID = NULL_ACTION_ID; this.actionID = Entities.addAction("kinematic-hold", this.grabbedEntity, { hand: this.hand === RIGHT_HAND ? "right" : "left", @@ -492,12 +482,7 @@ function MyController(hand, triggerAction) { this.continueNearGrabbing = function() { if (this.triggerSmoothedReleased()) { - this.setState(STATE_RELEASE); - Entities.editEntity(this.grabbedEntity, - {gravity: this.saveGravity, ignoreForCollisions: this.saveIgnoreForCollisions}); - setEntityCustomData(IGNORE_FOR_COLLISIONS_USER_DATA_KEY, this.grabbedEntity, null); - setEntityCustomData(GRAVITY_USER_DATA_KEY, this.grabbedEntity, null); return; } @@ -656,20 +641,35 @@ function MyController(hand, triggerAction) { this.release(); }; - this.activateEntity = function() { - var data = { - activated: true, - avatarId: MyAvatar.sessionUUID - }; - setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data); + this.activateEntity = function(entityID, grabbedProperties) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + data["activated"] = true; + data["avatarId"] = MyAvatar.sessionUUID; + data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1; + // zero gravity and set ignoreForCollisions to true, but in a way that lets us put them back, after all grabs are done + if (data["refCount"] == 1) { + data["gravity"] = grabbedProperties.gravity; + data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + Entities.editEntity(entityID, {gravity: {x:0, y:0, z:0}, ignoreForCollisions: true}); + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); }; - this.deactivateEntity = function() { - var data = { - activated: false, - avatarId: null - }; - setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data); + this.deactivateEntity = function(entityID) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + if (data && data["refCount"]) { + data["refCount"] = data["refCount"] - 1; + if (data["refCount"] < 1) { + Entities.editEntity(entityID, { + gravity: data["gravity"], + ignoreForCollisions: data["ignoreForCollisions"] + }); + data = null; + } + } else { + data = null; + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); }; } diff --git a/examples/grab.js b/examples/grab.js index 1e0adf9f1b..1c49775a49 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -26,7 +26,8 @@ var IDENTITY_QUAT = { z: 0, w: 0 }; -var GRABBABLE_DATA_KEY = "grabbableKey"; +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with handControllerGrab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with handControllerGrab.js var defaultGrabbableData = { grabbable: true @@ -247,7 +248,6 @@ Grabber = function() { this.currentPosition = ZERO_VEC3; this.planeNormal = ZERO_VEC3; - this.originalGravity = ZERO_VEC3; // maxDistance is a function of the size of the object. this.maxDistance; @@ -346,14 +346,11 @@ Grabber.prototype.pressEvent = function(event) { return; } - Entities.editEntity(clickedEntity, { - gravity: ZERO_VEC3 - }); + this.activateEntity(clickedEntity, entityProperties); this.isGrabbing = true; this.entityID = clickedEntity; this.currentPosition = entityProperties.position; - this.originalGravity = entityProperties.gravity; this.targetPosition = { x: this.startPosition.x, y: this.startPosition.y, @@ -379,12 +376,7 @@ Grabber.prototype.pressEvent = function(event) { Grabber.prototype.releaseEvent = function() { if (this.isGrabbing) { - if (Vec3.length(this.originalGravity) != 0) { - Entities.editEntity(this.entityID, { - gravity: this.originalGravity - }); - } - + this.deactivateEntity(this.entityID); this.isGrabbing = false Entities.deleteAction(this.entityID, this.actionID); this.actionID = null; @@ -503,6 +495,39 @@ Grabber.prototype.keyPressEvent = function(event) { this.computeNewGrabPlane(); } +Grabber.prototype.activateEntity = function(entityID, grabbedProperties) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + data["activated"] = true; + data["avatarId"] = MyAvatar.sessionUUID; + data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1; + // zero gravity and set ignoreForCollisions to true, but in a way that lets us put them back, after all grabs are done + if (data["refCount"] == 1) { + data["gravity"] = grabbedProperties.gravity; + data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + Entities.editEntity(entityID, {gravity: {x:0, y:0, z:0}, ignoreForCollisions: true}); + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); +}; + +Grabber.prototype.deactivateEntity = function(entityID) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + if (data && data["refCount"]) { + data["refCount"] = data["refCount"] - 1; + if (data["refCount"] < 1) { + Entities.editEntity(entityID, { + gravity: data["gravity"], + ignoreForCollisions: data["ignoreForCollisions"] + }); + data = null; + } + } else { + data = null; + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); +}; + + + var grabber = new Grabber(); function pressEvent(event) { From 99be44f92d77dfc18c4d1a7678bc2157c39534df Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Oct 2015 14:58:42 -0700 Subject: [PATCH 14/20] smooth out vibrating appearance for kinematic hold --- interface/src/avatar/AvatarActionKinematicHold.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index 21f2989299..84310cd35f 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -87,15 +87,19 @@ void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { return; } + if (_previousSet) { + glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep; + rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); + + // back up along velocity a bit in order to smooth out a "vibrating" appearance + _positionalTarget -= positionalVelocity * deltaTimeStep / 2.0f; + } + btTransform worldTrans = rigidBody->getWorldTransform(); worldTrans.setOrigin(glmToBullet(_positionalTarget)); worldTrans.setRotation(glmToBullet(_rotationalTarget)); rigidBody->setWorldTransform(worldTrans); - if (_previousSet) { - glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep; - rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); - } _previousPositionalTarget = _positionalTarget; _previousRotationalTarget = _rotationalTarget; _previousSet = true; From 91f5a6fec6b79a43e2a1013a04b0e07dc9531057 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 6 Oct 2015 08:08:33 -0700 Subject: [PATCH 15/20] make setting of rigid-body velocity controlled by an action argument --- .../src/avatar/AvatarActionKinematicHold.cpp | 23 +++++++++++++------ .../src/avatar/AvatarActionKinematicHold.h | 2 ++ .../entities/src/EntityActionInterface.cpp | 22 ++++++++++++++++++ .../entities/src/EntityActionInterface.h | 2 ++ 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index 84310cd35f..781d895a32 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -81,18 +81,19 @@ void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { void* physicsInfo = ownerEntity->getPhysicsInfo(); if (physicsInfo) { ObjectMotionState* motionState = static_cast(physicsInfo); - btRigidBody* rigidBody = motionState->getRigidBody(); + btRigidBody* rigidBody = motionState ? motionState->getRigidBody() : nullptr; if (!rigidBody) { qDebug() << "ObjectActionSpring::updateActionWorker no rigidBody"; return; } - if (_previousSet) { - glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep; - rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); - - // back up along velocity a bit in order to smooth out a "vibrating" appearance - _positionalTarget -= positionalVelocity * deltaTimeStep / 2.0f; + if (_setVelocity) { + if (_previousSet) { + glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep; + rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); + // back up along velocity a bit in order to smooth out a "vibrating" appearance + _positionalTarget -= positionalVelocity * deltaTimeStep / 2.0f; + } } btTransform worldTrans = rigidBody->getWorldTransform(); @@ -140,6 +141,13 @@ bool AvatarActionKinematicHold::updateArguments(QVariantMap arguments) { hand = _hand; } + ok = true; + int setVelocity = + EntityActionInterface::extractIntegerArgument("kinematic-hold", arguments, "setVelocity", ok, false); + if (!ok) { + setVelocity = false; + } + if (relativePosition != _relativePosition || relativeRotation != _relativeRotation || hand != _hand) { @@ -147,6 +155,7 @@ bool AvatarActionKinematicHold::updateArguments(QVariantMap arguments) { _relativePosition = relativePosition; _relativeRotation = relativeRotation; _hand = hand; + _setVelocity = setVelocity; _mine = true; _active = true; diff --git a/interface/src/avatar/AvatarActionKinematicHold.h b/interface/src/avatar/AvatarActionKinematicHold.h index 95e9605c2b..b4fceab1e7 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.h +++ b/interface/src/avatar/AvatarActionKinematicHold.h @@ -40,6 +40,8 @@ private: bool _previousSet = false; glm::vec3 _previousPositionalTarget; glm::quat _previousRotationalTarget; + + bool _setVelocity = false; }; #endif // hifi_AvatarActionKinematicHold_h diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityActionInterface.cpp index 25f61fcf25..c34f072601 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityActionInterface.cpp @@ -249,6 +249,28 @@ float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMa return v; } +int EntityActionInterface::extractIntegerArgument(QString objectName, QVariantMap arguments, + QString argumentName, bool& ok, bool required) { + if (!arguments.contains(argumentName)) { + if (required) { + qDebug() << objectName << "requires argument:" << argumentName; + } + ok = false; + return 0.0f; + } + + QVariant vV = arguments[argumentName]; + bool vOk = true; + int v = vV.toInt(&vOk); + + if (!vOk || v != v) { + ok = false; + return 0; + } + + return v; +} + QString EntityActionInterface::extractStringArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index b5d277587c..57f605c3e3 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -70,6 +70,8 @@ protected: QString argumentName, bool& ok, bool required = true); static float extractFloatArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required = true); + static int extractIntegerArgument(QString objectName, QVariantMap arguments, + QString argumentName, bool& ok, bool required = true); static QString extractStringArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required = true); From c3142ab90b2079615b4a34bb67eb4c40f732461d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 6 Oct 2015 09:20:07 -0700 Subject: [PATCH 16/20] include setVelocity in returned arguments --- interface/src/avatar/AvatarActionKinematicHold.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index 781d895a32..521230adc6 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -176,6 +176,7 @@ QVariantMap AvatarActionKinematicHold::getArguments() { arguments["relativePosition"] = glmToQMap(_relativePosition); arguments["relativeRotation"] = glmToQMap(_relativeRotation); + arguments["setVelocity"] = glmToQMap((int)_setVelocity); arguments["hand"] = _hand; }); return arguments; From 18b5b994b4e41e8f8cfa1b43173320000560facb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 6 Oct 2015 09:23:38 -0700 Subject: [PATCH 17/20] include setVelocity in returned arguments --- interface/src/avatar/AvatarActionKinematicHold.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index 521230adc6..b792058846 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -176,7 +176,7 @@ QVariantMap AvatarActionKinematicHold::getArguments() { arguments["relativePosition"] = glmToQMap(_relativePosition); arguments["relativeRotation"] = glmToQMap(_relativeRotation); - arguments["setVelocity"] = glmToQMap((int)_setVelocity); + arguments["setVelocity"] = glmToQMap((quint8)_setVelocity); arguments["hand"] = _hand; }); return arguments; From 5abaf38efd6acb314dd29b78a953ab26cfaf7be7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 6 Oct 2015 09:24:18 -0700 Subject: [PATCH 18/20] include setVelocity in returned arguments --- interface/src/avatar/AvatarActionKinematicHold.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index b792058846..9831fca47c 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -176,7 +176,7 @@ QVariantMap AvatarActionKinematicHold::getArguments() { arguments["relativePosition"] = glmToQMap(_relativePosition); arguments["relativeRotation"] = glmToQMap(_relativeRotation); - arguments["setVelocity"] = glmToQMap((quint8)_setVelocity); + arguments["setVelocity"] = _setVelocity; arguments["hand"] = _hand; }); return arguments; From 8caa7abca67d7a15856ecffec1cdbd52cd37ee21 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 6 Oct 2015 09:35:54 -0700 Subject: [PATCH 19/20] assert that deltaTimeStep is always greater than zero --- interface/src/avatar/AvatarActionKinematicHold.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp index 9831fca47c..680363877f 100644 --- a/interface/src/avatar/AvatarActionKinematicHold.cpp +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -46,9 +46,7 @@ void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { return; } - if (deltaTimeStep <= 0.0f) { - return; - } + assert(deltaTimeStep > 0.0f); glm::quat rotation; glm::vec3 position; From 8090bc8e8d7d2b65963aa1ad17e5fb45e06c61a5 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 6 Oct 2015 10:16:42 -0700 Subject: [PATCH 20/20] Revert "Enabling programmatic access to the IPD scale" --- examples/example/hmd/ipdScalingTest.js | 42 ------------ interface/src/Application.cpp | 47 ++++--------- interface/src/PluginContainerProxy.cpp | 7 -- interface/src/PluginContainerProxy.h | 3 - interface/src/avatar/MyAvatar.cpp | 8 +-- .../src/scripting/HMDScriptingInterface.cpp | 68 +++++++++---------- .../src/scripting/HMDScriptingInterface.h | 23 ++++--- .../AbstractHMDScriptingInterface.cpp | 52 -------------- .../AbstractHMDScriptingInterface.h | 39 ----------- .../src/display-plugins/DisplayPlugin.h | 17 ++--- .../oculus/OculusBaseDisplayPlugin.cpp | 16 ++--- .../oculus/OculusBaseDisplayPlugin.h | 11 ++- .../display-plugins/oculus/OculusHelpers.h | 8 --- .../oculus/OculusLegacyDisplayPlugin.cpp | 4 +- .../oculus/OculusLegacyDisplayPlugin.h | 2 +- .../openvr/OpenVrDisplayPlugin.cpp | 4 +- .../openvr/OpenVrDisplayPlugin.h | 2 +- .../stereo/StereoDisplayPlugin.cpp | 4 ++ .../stereo/StereoDisplayPlugin.h | 9 +-- .../plugins/src/plugins/PluginContainer.cpp | 10 --- .../plugins/src/plugins/PluginContainer.h | 4 -- 21 files changed, 90 insertions(+), 290 deletions(-) delete mode 100644 examples/example/hmd/ipdScalingTest.js delete mode 100644 libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp delete mode 100644 libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h diff --git a/examples/example/hmd/ipdScalingTest.js b/examples/example/hmd/ipdScalingTest.js deleted file mode 100644 index daa11170e4..0000000000 --- a/examples/example/hmd/ipdScalingTest.js +++ /dev/null @@ -1,42 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/10/04 -// Copyright 2013-2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -IPDScalingTest = function() { - // Switch every 5 seconds between normal IPD and 0 IPD (in seconds) - this.UPDATE_INTERVAL = 10.0; - this.lastUpdateInterval = 0; - this.scaled = false; - - var that = this; - Script.scriptEnding.connect(function() { - that.onCleanup(); - }); - - Script.update.connect(function(deltaTime) { - that.lastUpdateInterval += deltaTime; - if (that.lastUpdateInterval >= that.UPDATE_INTERVAL) { - that.onUpdate(that.lastUpdateInterval); - that.lastUpdateInterval = 0; - } - }); -} - -IPDScalingTest.prototype.onCleanup = function() { - HMD.setIPDScale(1.0); -} - -IPDScalingTest.prototype.onUpdate = function(deltaTime) { - this.scaled = !this.scaled; - if (this.scaled) { - HMD.ipdScale = 0.0; - } else { - HMD.ipdScale = 1.0; - } -} - -new IPDScalingTest(); \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 025e448e29..b25f3aa6a5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -300,7 +300,6 @@ bool setupEssentials(int& argc, char** argv) { auto desktopScriptingInterface = DependencyManager::set(); auto entityScriptingInterface = DependencyManager::set(); auto windowScriptingInterface = DependencyManager::set(); - auto hmdScriptingInterface = DependencyManager::set(); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) auto speechRecognizer = DependencyManager::set(); #endif @@ -1204,11 +1203,9 @@ void Application::paintGL() { // right eye. There are FIXMEs in the relevant plugins _myCamera.setProjection(displayPlugin->getProjection(Mono, _myCamera.getProjection())); renderArgs._context->enableStereo(true); - mat4 eyeOffsets[2]; + mat4 eyeViews[2]; mat4 eyeProjections[2]; auto baseProjection = renderArgs._viewFrustum->getProjection(); - auto hmdInterface = DependencyManager::get(); - float IPDScale = hmdInterface->getIPDScale(); // FIXME we probably don't need to set the projection matrix every frame, // only when the display plugin changes (or in non-HMD modes when the user // changes the FOV manually, which right now I don't think they can. @@ -1217,24 +1214,14 @@ void Application::paintGL() { // applied to the avatar, so we need to get the difference between the head // pose applied to the avatar and the per eye pose, and use THAT as // the per-eye stereo matrix adjustment. - mat4 eyeToHead = displayPlugin->getEyeToHeadTransform(eye); - // Grab the translation - vec3 eyeOffset = glm::vec3(eyeToHead[3]); - // Apply IPD scaling - mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * IPDScale); - eyeOffsets[eye] = eyeOffsetTransform; - - // Tell the plugin what pose we're using to render. In this case we're just using the - // unmodified head pose because the only plugin that cares (the Oculus plugin) uses it - // for rotational timewarp. If we move to support positonal timewarp, we need to - // ensure this contains the full pose composed with the eye offsets. + mat4 eyePose = displayPlugin->getEyePose(eye); mat4 headPose = displayPlugin->getHeadPose(); - displayPlugin->setEyeRenderPose(eye, headPose); - + mat4 eyeView = glm::inverse(eyePose) * headPose; + eyeViews[eye] = eyeView; eyeProjections[eye] = displayPlugin->getProjection(eye, baseProjection); }); renderArgs._context->setStereoProjections(eyeProjections); - renderArgs._context->setStereoViews(eyeOffsets); + renderArgs._context->setStereoViews(eyeViews); } displaySide(&renderArgs, _myCamera); renderArgs._context->enableStereo(false); @@ -4143,7 +4130,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Paths", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("HMD", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("HMD", &HMDScriptingInterface::getInstance()); scriptEngine->registerFunction("HMD", "getHUDLookAtPosition2D", HMDScriptingInterface::getHUDLookAtPosition2D, 0); scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0); @@ -4993,25 +4980,19 @@ mat4 Application::getEyeProjection(int eye) const { mat4 Application::getEyePose(int eye) const { if (isHMDMode()) { - auto hmdInterface = DependencyManager::get(); - float IPDScale = hmdInterface->getIPDScale(); - auto displayPlugin = getActiveDisplayPlugin(); - mat4 headPose = displayPlugin->getHeadPose(); - mat4 eyeToHead = displayPlugin->getEyeToHeadTransform((Eye)eye); - { - vec3 eyeOffset = glm::vec3(eyeToHead[3]); - // Apply IPD scaling - mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * IPDScale); - eyeToHead[3] = vec4(eyeOffset, 1.0); - } - return eyeToHead * headPose; + return getActiveDisplayPlugin()->getEyePose((Eye)eye); } + return mat4(); } mat4 Application::getEyeOffset(int eye) const { - // FIXME invert? - return getActiveDisplayPlugin()->getEyeToHeadTransform((Eye)eye); + if (isHMDMode()) { + mat4 identity; + return getActiveDisplayPlugin()->getView((Eye)eye, identity); + } + + return mat4(); } mat4 Application::getHMDSensorPose() const { diff --git a/interface/src/PluginContainerProxy.cpp b/interface/src/PluginContainerProxy.cpp index d31231e11c..469e7f7c77 100644 --- a/interface/src/PluginContainerProxy.cpp +++ b/interface/src/PluginContainerProxy.cpp @@ -16,9 +16,6 @@ PluginContainerProxy::PluginContainerProxy() { Plugin::setContainer(this); } -PluginContainerProxy::~PluginContainerProxy() { -} - bool PluginContainerProxy::isForeground() { return qApp->_isForeground && !qApp->getWindow()->isMinimized(); } @@ -154,7 +151,3 @@ void PluginContainerProxy::showDisplayPluginsTools() { QGLWidget* PluginContainerProxy::getPrimarySurface() { return qApp->_glWidget; } - -const DisplayPlugin* PluginContainerProxy::getActiveDisplayPlugin() const { - return qApp->getActiveDisplayPlugin(); -} diff --git a/interface/src/PluginContainerProxy.h b/interface/src/PluginContainerProxy.h index 79f8287b66..95865609c8 100644 --- a/interface/src/PluginContainerProxy.h +++ b/interface/src/PluginContainerProxy.h @@ -11,7 +11,6 @@ class PluginContainerProxy : public QObject, PluginContainer { Q_OBJECT PluginContainerProxy(); - virtual ~PluginContainerProxy(); virtual void addMenu(const QString& menuName) override; virtual void removeMenu(const QString& menuName) override; virtual QAction* addMenuItem(const QString& path, const QString& name, std::function onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") override; @@ -24,8 +23,6 @@ class PluginContainerProxy : public QObject, PluginContainer { virtual void requestReset() override; virtual QGLWidget* getPrimarySurface() override; virtual bool isForeground() override; - virtual const DisplayPlugin* getActiveDisplayPlugin() const override; - QRect _savedGeometry{ 10, 120, 800, 600 }; friend class Application; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 71698fa4ea..9654305d70 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1341,13 +1341,11 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl if (qApp->isHMDMode()) { glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); - glm::mat4 headPose = Application::getInstance()->getActiveDisplayPlugin()->getHeadPose(); - glm::mat4 leftEyePose = Application::getInstance()->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Left); - leftEyePose = leftEyePose * headPose; + glm::mat4 leftEyePose = Application::getInstance()->getActiveDisplayPlugin()->getEyePose(Eye::Left); glm::vec3 leftEyePosition = glm::vec3(leftEyePose[3]); - glm::mat4 rightEyePose = Application::getInstance()->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Right); - rightEyePose = rightEyePose * headPose; + glm::mat4 rightEyePose = Application::getInstance()->getActiveDisplayPlugin()->getEyePose(Eye::Right); glm::vec3 rightEyePosition = glm::vec3(rightEyePose[3]); + glm::mat4 headPose = Application::getInstance()->getActiveDisplayPlugin()->getHeadPose(); glm::vec3 headPosition = glm::vec3(headPose[3]); getHead()->renderLookAts(renderArgs, diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index f6bf7f8b3c..68ac511eaf 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -10,46 +10,12 @@ // #include "HMDScriptingInterface.h" - -#include - #include "display-plugins/DisplayPlugin.h" #include -#include "Application.h" -HMDScriptingInterface::HMDScriptingInterface() { -} - -QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) { - glm::vec3 hudIntersection; - auto instance = DependencyManager::get(); - if (instance->getHUDLookAtPosition3D(hudIntersection)) { - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - glm::vec3 sphereCenter = myAvatar->getDefaultEyePosition(); - glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * (hudIntersection - sphereCenter); - glm::quat rotation = ::rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), direction); - glm::vec3 eulers = ::safeEulerAngles(rotation); - return qScriptValueFromValue(engine, Application::getInstance()->getApplicationCompositor() - .sphericalToOverlay(glm::vec2(eulers.y, -eulers.x))); - } - return QScriptValue::NullValue; -} - -QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) { - glm::vec3 result; - auto instance = DependencyManager::get(); - if (instance->getHUDLookAtPosition3D(result)) { - return qScriptValueFromValue(engine, result); - } - return QScriptValue::NullValue; -} - -void HMDScriptingInterface::toggleMagnifier() { - qApp->getApplicationCompositor().toggleMagnifier(); -} - -bool HMDScriptingInterface::getMagnifier() const { - return Application::getInstance()->getApplicationCompositor().hasMagnifier(); +HMDScriptingInterface& HMDScriptingInterface::getInstance() { + static HMDScriptingInterface sharedInstance; + return sharedInstance; } bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const { @@ -63,3 +29,31 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const { return compositor.calculateRayUICollisionPoint(position, direction, result); } + +QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) { + + glm::vec3 hudIntersection; + + if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(hudIntersection)) { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + glm::vec3 sphereCenter = myAvatar->getDefaultEyePosition(); + glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * (hudIntersection - sphereCenter); + glm::quat rotation = ::rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), direction); + glm::vec3 eulers = ::safeEulerAngles(rotation); + return qScriptValueFromValue(engine, Application::getInstance()->getApplicationCompositor() + .sphericalToOverlay(glm::vec2(eulers.y, -eulers.x))); + } + return QScriptValue::NullValue; +} + +QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) { + glm::vec3 result; + if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) { + return qScriptValueFromValue(engine, result); + } + return QScriptValue::NullValue; +} + +float HMDScriptingInterface::getIPD() const { + return Application::getInstance()->getActiveDisplayPlugin()->getIPD(); +} diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index c097cde5e3..82b444abaa 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -12,29 +12,32 @@ #ifndef hifi_HMDScriptingInterface_h #define hifi_HMDScriptingInterface_h -#include -class QScriptContext; -class QScriptEngine; - #include -#include -#include +#include "Application.h" -class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency { +class HMDScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(bool magnifier READ getMagnifier) + Q_PROPERTY(bool active READ isHMDMode) + Q_PROPERTY(float ipd READ getIPD) public: - HMDScriptingInterface(); + static HMDScriptingInterface& getInstance(); + static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine); static QScriptValue getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine); public slots: - void toggleMagnifier(); + void toggleMagnifier() { Application::getInstance()->getApplicationCompositor().toggleMagnifier(); }; private: - bool getMagnifier() const; + HMDScriptingInterface() {}; + bool getMagnifier() const { return Application::getInstance()->getApplicationCompositor().hasMagnifier(); }; + bool isHMDMode() const { return Application::getInstance()->isHMDMode(); } + float getIPD() const; + bool getHUDLookAtPosition3D(glm::vec3& result) const; + }; #endif // hifi_HMDScriptingInterface_h diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp deleted file mode 100644 index 9987ae345c..0000000000 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/10/04 -// Copyright 2013-2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "AbstractHMDScriptingInterface.h" - -#include - -#include "DisplayPlugin.h" -#include -#include - -static Setting::Handle IPD_SCALE_HANDLE("hmd.ipdScale", 1.0f); - -AbstractHMDScriptingInterface::AbstractHMDScriptingInterface() { - _IPDScale = IPD_SCALE_HANDLE.get(); -} - -float AbstractHMDScriptingInterface::getIPD() const { - return PluginContainer::getInstance().getActiveDisplayPlugin()->getIPD(); -} - -float AbstractHMDScriptingInterface::getEyeHeight() const { - // FIXME update the display plugin interface to expose per-plugin settings - return OVR_DEFAULT_EYE_HEIGHT; -} - -float AbstractHMDScriptingInterface::getPlayerHeight() const { - // FIXME update the display plugin interface to expose per-plugin settings - return OVR_DEFAULT_PLAYER_HEIGHT; -} - -float AbstractHMDScriptingInterface::getIPDScale() const { - return _IPDScale; -} - -void AbstractHMDScriptingInterface::setIPDScale(float IPDScale) { - IPDScale = glm::clamp(IPDScale, -1.0f, 3.0f); - if (IPDScale != _IPDScale) { - _IPDScale = IPDScale; - IPD_SCALE_HANDLE.set(IPDScale); - emit IPDScaleChanged(); - } -} - -bool AbstractHMDScriptingInterface::isHMDMode() const { - return PluginContainer::getInstance().getActiveDisplayPlugin()->isHmd(); -} diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h deleted file mode 100644 index 5df58ce677..0000000000 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/10/04 -// Copyright 2013-2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#pragma once -#ifndef hifi_AbstractHMDScriptingInterface_h -#define hifi_AbstractHMDScriptingInterface_h - -#include - -class AbstractHMDScriptingInterface : public QObject { - Q_OBJECT - Q_PROPERTY(bool active READ isHMDMode) - Q_PROPERTY(float ipd READ getIPD) - Q_PROPERTY(float eyeHeight READ getEyeHeight) - Q_PROPERTY(float playerHeight READ getPlayerHeight) - Q_PROPERTY(float ipdScale READ getIPDScale WRITE setIPDScale NOTIFY IPDScaleChanged) - -public: - AbstractHMDScriptingInterface(); - float getIPD() const; - float getEyeHeight() const; - float getPlayerHeight() const; - float getIPDScale() const; - void setIPDScale(float ipdScale); - bool isHMDMode() const; - -signals: - void IPDScaleChanged(); - -private: - float _IPDScale{ 1.0 }; -}; - -#endif // hifi_AbstractHMDScriptingInterface_h diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h index b4ae6be97f..8b9d249bd4 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h @@ -46,8 +46,6 @@ void for_each_eye(F f, FF ff) { class QWindow; -#define AVERAGE_HUMAN_IPD 0.064f - class DisplayPlugin : public Plugin { Q_OBJECT public: @@ -109,22 +107,21 @@ public: return baseProjection; } + virtual glm::mat4 getView(Eye eye, const glm::mat4& baseView) const { + return glm::inverse(getEyePose(eye)) * baseView; + } + // HMD specific methods // TODO move these into another class? - virtual glm::mat4 getEyeToHeadTransform(Eye eye) const { - static const glm::mat4 transform; return transform; + virtual glm::mat4 getEyePose(Eye eye) const { + static const glm::mat4 pose; return pose; } virtual glm::mat4 getHeadPose() const { static const glm::mat4 pose; return pose; } - // Needed for timewarp style features - virtual void setEyeRenderPose(Eye eye, const glm::mat4& pose) { - // NOOP - } - - virtual float getIPD() const { return AVERAGE_HUMAN_IPD; } + virtual float getIPD() const { return 0.0f; } virtual void abandonCalibration() {} virtual void resetSensors() {} diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp index 859a4a810a..f2a7b06510 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp @@ -19,6 +19,7 @@ void OculusBaseDisplayPlugin::preRender() { #if (OVR_MAJOR_VERSION >= 6) ovrFrameTiming ftiming = ovr_GetFrameTiming(_hmd, _frameIndex); _trackingState = ovr_GetTrackingState(_hmd, ftiming.DisplayMidpointSeconds); + ovr_CalcEyePoses(_trackingState.HeadPose.ThePose, _eyeOffsets, _eyePoses); #endif } @@ -32,19 +33,14 @@ void OculusBaseDisplayPlugin::resetSensors() { #endif } -glm::mat4 OculusBaseDisplayPlugin::getEyeToHeadTransform(Eye eye) const { - return glm::translate(mat4(), toGlm(_eyeOffsets[eye])); +glm::mat4 OculusBaseDisplayPlugin::getEyePose(Eye eye) const { + return toGlm(_eyePoses[eye]); } glm::mat4 OculusBaseDisplayPlugin::getHeadPose() const { return toGlm(_trackingState.HeadPose.ThePose); } -void OculusBaseDisplayPlugin::setEyeRenderPose(Eye eye, const glm::mat4& pose) { - _eyePoses[eye] = ovrPoseFromGlm(pose); -} - - bool OculusBaseDisplayPlugin::isSupported() const { #if (OVR_MAJOR_VERSION >= 6) if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { @@ -155,9 +151,9 @@ void OculusBaseDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sce } float OculusBaseDisplayPlugin::getIPD() const { - float result = OVR_DEFAULT_IPD; + float result = 0.0f; #if (OVR_MAJOR_VERSION >= 6) - result = ovr_GetFloat(_hmd, OVR_KEY_IPD, result); + result = ovr_GetFloat(_hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD); #endif return result; -} +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h index 6307f6bbf9..d879085b8f 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h @@ -29,9 +29,8 @@ public: virtual glm::uvec2 getRecommendedRenderSize() const override final; virtual glm::uvec2 getRecommendedUiSize() const override final { return uvec2(1920, 1080); } virtual void resetSensors() override final; - virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override final; + virtual glm::mat4 getEyePose(Eye eye) const override final; virtual glm::mat4 getHeadPose() const override final; - virtual void setEyeRenderPose(Eye eye, const glm::mat4& pose) override final; virtual float getIPD() const override final; protected: @@ -40,7 +39,6 @@ protected: protected: ovrPosef _eyePoses[2]; - ovrVector3f _eyeOffsets[2]; mat4 _eyeProjections[3]; mat4 _compositeEyeProjections[2]; @@ -52,12 +50,13 @@ protected: ovrHmd _hmd; float _ipd{ OVR_DEFAULT_IPD }; ovrEyeRenderDesc _eyeRenderDescs[2]; + ovrVector3f _eyeOffsets[2]; ovrFovPort _eyeFovs[2]; - ovrHmdDesc _hmdDesc; - ovrLayerEyeFov _sceneLayer; + ovrHmdDesc _hmdDesc; + ovrLayerEyeFov _sceneLayer; #endif #if (OVR_MAJOR_VERSION == 7) - ovrGraphicsLuid _luid; + ovrGraphicsLuid _luid; #endif }; diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h b/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h index 5a6999075b..df0a6c5228 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h @@ -79,11 +79,3 @@ inline ovrQuatf ovrFromGlm(const glm::quat & q) { return{ q.x, q.y, q.z, q.w }; } -inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) { - glm::vec3 translation = glm::vec3(m[3]) / m[3].w; - glm::quat orientation = glm::quat_cast(m); - ovrPosef result; - result.Orientation = ovrFromGlm(orientation); - result.Position = ovrFromGlm(translation); - return result; -} diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.cpp index 1ad61513d6..ade34afcae 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.cpp @@ -59,11 +59,11 @@ void OculusLegacyDisplayPlugin::resetSensors() { #endif } -glm::mat4 OculusLegacyDisplayPlugin::getEyeToHeadTransform(Eye eye) const { +glm::mat4 OculusLegacyDisplayPlugin::getEyePose(Eye eye) const { #if (OVR_MAJOR_VERSION == 5) return toGlm(_eyePoses[eye]); #else - return WindowOpenGLDisplayPlugin::getEyeToHeadTransform(eye); + return WindowOpenGLDisplayPlugin::getEyePose(eye); #endif } diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.h index 9e2e47f434..5bce032948 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusLegacyDisplayPlugin.h @@ -31,7 +31,7 @@ public: virtual glm::uvec2 getRecommendedRenderSize() const override; virtual glm::uvec2 getRecommendedUiSize() const override { return uvec2(1920, 1080); } virtual void resetSensors() override; - virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override; + virtual glm::mat4 getEyePose(Eye eye) const override; virtual glm::mat4 getHeadPose() const override; protected: diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp index faf5a7b781..fab9cc5dd4 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp @@ -160,8 +160,8 @@ void OpenVrDisplayPlugin::resetSensors() { _sensorResetMat = glm::inverse(cancelOutRollAndPitch(_trackedDevicePoseMat4[0])); } -glm::mat4 OpenVrDisplayPlugin::getEyeToHeadTransform(Eye eye) const { - return _eyesData[eye]._eyeOffset; +glm::mat4 OpenVrDisplayPlugin::getEyePose(Eye eye) const { + return getHeadPose() * _eyesData[eye]._eyeOffset; } glm::mat4 OpenVrDisplayPlugin::getHeadPose() const { diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 7849623552..afe024e72b 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -29,7 +29,7 @@ public: virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; virtual void resetSensors() override; - virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override; + virtual glm::mat4 getEyePose(Eye eye) const override; virtual glm::mat4 getHeadPose() const override; protected: diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp index 2ea79ed2e0..77906d1857 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp @@ -61,6 +61,10 @@ glm::mat4 StereoDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProje return eyeProjection; } +glm::mat4 StereoDisplayPlugin::getEyePose(Eye eye) const { + return mat4(); +} + std::vector _screenActions; void StereoDisplayPlugin::activate() { auto screens = qApp->screens(); diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h index 33b0b09b0d..86f35c1260 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h @@ -21,14 +21,7 @@ public: virtual float getRecommendedAspectRatio() const override; virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; - - // NOTE, because Stereo displays don't include head tracking, and therefore - // can't include roll or pitch, the eye separation is embedded into the projection - // matrix. However, this eliminates the possibility of easily mainpulating - // the IPD at the Application level, the way we now allow with HMDs. - // If that becomes an issue then we'll need to break up the functionality similar - // to the HMD plugins. - // virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override; + virtual glm::mat4 getEyePose(Eye eye) const override; protected: void updateScreen(); diff --git a/libraries/plugins/src/plugins/PluginContainer.cpp b/libraries/plugins/src/plugins/PluginContainer.cpp index 8afac745f3..b27f076eb6 100644 --- a/libraries/plugins/src/plugins/PluginContainer.cpp +++ b/libraries/plugins/src/plugins/PluginContainer.cpp @@ -9,17 +9,7 @@ static PluginContainer* INSTANCE{ nullptr }; -PluginContainer& PluginContainer::getInstance() { - Q_ASSERT(INSTANCE); - return *INSTANCE; -} - PluginContainer::PluginContainer() { Q_ASSERT(!INSTANCE); INSTANCE = this; }; - -PluginContainer::~PluginContainer() { - Q_ASSERT(INSTANCE == this); - INSTANCE = nullptr; -}; diff --git a/libraries/plugins/src/plugins/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h index f013bfe3bf..f938758161 100644 --- a/libraries/plugins/src/plugins/PluginContainer.h +++ b/libraries/plugins/src/plugins/PluginContainer.h @@ -13,13 +13,10 @@ class QAction; class QGLWidget; class QScreen; -class DisplayPlugin; class PluginContainer { public: - static PluginContainer& getInstance(); PluginContainer(); - virtual ~PluginContainer(); virtual void addMenu(const QString& menuName) = 0; virtual void removeMenu(const QString& menuName) = 0; virtual QAction* addMenuItem(const QString& path, const QString& name, std::function onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0; @@ -32,5 +29,4 @@ public: virtual void requestReset() = 0; virtual QGLWidget* getPrimarySurface() = 0; virtual bool isForeground() = 0; - virtual const DisplayPlugin* getActiveDisplayPlugin() const = 0; };