mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:24:07 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into js-hmd-position-orientation
Conflicts: interface/src/Application.cpp interface/src/scripting/HMDScriptingInterface.h libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h
This commit is contained in:
commit
953ff6caa7
32 changed files with 477 additions and 355 deletions
|
@ -79,8 +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 GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js
|
||||
var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js
|
||||
|
||||
function getTag() {
|
||||
return "grab-" + MyAvatar.sessionUUID;
|
||||
|
@ -312,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;
|
||||
|
@ -336,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 {
|
||||
|
@ -439,9 +440,9 @@ function MyController(hand, triggerAction) {
|
|||
|
||||
this.lineOff();
|
||||
|
||||
this.activateEntity(this.grabbedEntity);
|
||||
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]);
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity,
|
||||
["position", "rotation", "gravity", "ignoreForCollisions"]);
|
||||
this.activateEntity(this.grabbedEntity, grabbedProperties);
|
||||
|
||||
var handRotation = this.getHandRotation();
|
||||
var handPosition = this.getHandPosition();
|
||||
|
@ -454,7 +455,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,
|
||||
|
@ -640,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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
|
@ -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) {
|
||||
|
|
|
@ -79,13 +79,21 @@ 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);
|
||||
}
|
||||
|
||||
getEntityCustomData = function(customKey, id, defaultValue) {
|
||||
var userData = getEntityUserData(id);
|
||||
return userData[customKey] ? userData[customKey] : defaultValue;
|
||||
if (undefined != userData[customKey]) {
|
||||
return userData[customKey];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
mergeObjects = function(proto, custom) {
|
||||
|
|
|
@ -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,
|
||||
|
@ -25,14 +25,15 @@ 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: {
|
||||
x:0.67,
|
||||
y: 0.14,
|
||||
z: 0.09
|
||||
x: 0.08,
|
||||
y: 0.21,
|
||||
z: 0.47
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
});
|
||||
|
@ -40,4 +41,4 @@ var pingPongGun = Entities.addEntity({
|
|||
function cleanUp() {
|
||||
Entities.deleteEntity(pingPongGun);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanUp);
|
||||
Script.scriptEnding.connect(cleanUp);
|
|
@ -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 = 15;
|
||||
var GUN_FORCE = 9;
|
||||
var BALL_RESTITUTION = 0.6;
|
||||
var BALL_LINEAR_DAMPING = 0.4;
|
||||
var BALL_GRAVITY = {
|
||||
x: 0,
|
||||
y: -9.8,
|
||||
y: -4.8,
|
||||
z: 0
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -81,10 +80,14 @@
|
|||
},
|
||||
|
||||
releaseGrab: function() {
|
||||
var _t = this;
|
||||
this.canShootTimeout = Script.setTimeout(function() {
|
||||
_t.canShoot = false;
|
||||
}, 250)
|
||||
var _this = this;
|
||||
|
||||
if (this.whichHand === this.hand) {
|
||||
this.whichHand = null;
|
||||
this.canShootTimeout = Script.setTimeout(function() {
|
||||
_this.canShoot = false;
|
||||
}, 250);
|
||||
}
|
||||
},
|
||||
|
||||
checkTriggerPressure: function(gunHand) {
|
||||
|
@ -97,18 +100,20 @@
|
|||
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;
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
|
||||
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);
|
||||
|
||||
var properties = {
|
||||
type: 'Sphere',
|
||||
color: BALL_COLOR,
|
||||
|
@ -130,7 +135,7 @@
|
|||
|
||||
playSoundAtCurrentPosition: function(position) {
|
||||
var audioProperties = {
|
||||
volume: 0.1,
|
||||
volume: 0.2,
|
||||
position: position
|
||||
};
|
||||
|
||||
|
@ -139,12 +144,14 @@
|
|||
|
||||
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);
|
||||
|
||||
return gunTipPosition;
|
||||
},
|
||||
|
||||
|
|
|
@ -300,7 +300,6 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
auto desktopScriptingInterface = DependencyManager::set<DesktopScriptingInterface>();
|
||||
auto entityScriptingInterface = DependencyManager::set<EntityScriptingInterface>();
|
||||
auto windowScriptingInterface = DependencyManager::set<WindowScriptingInterface>();
|
||||
auto hmdScriptingInterface = DependencyManager::set<HMDScriptingInterface>();
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
auto speechRecognizer = DependencyManager::set<SpeechRecognizer>();
|
||||
#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<HMDScriptingInterface>();
|
||||
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 = extractTranslation(eyeToHead);
|
||||
// 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<PathUtils>().data());
|
||||
|
||||
scriptEngine->registerGlobalObject("HMD", DependencyManager::get<HMDScriptingInterface>().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<HMDScriptingInterface>();
|
||||
float IPDScale = hmdInterface->getIPDScale();
|
||||
auto displayPlugin = getActiveDisplayPlugin();
|
||||
mat4 headPose = displayPlugin->getHeadPose();
|
||||
mat4 eyeToHead = displayPlugin->getEyeToHeadTransform((Eye)eye);
|
||||
{
|
||||
vec3 eyeOffset = extractTranslation(eyeToHead);
|
||||
// Apply IPD scaling
|
||||
mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * IPDScale);
|
||||
eyeToHead[3] = vec4(eyeOffset, 1.0);
|
||||
return getActiveDisplayPlugin()->getEyePose((Eye)eye);
|
||||
}
|
||||
return eyeToHead * headPose;
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
|
||||
#include <avatar/AvatarActionHold.h>
|
||||
#include <avatar/AvatarActionKinematicHold.h>
|
||||
#include <ObjectActionOffset.h>
|
||||
#include <ObjectActionSpring.h>
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<void(bool)> 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;
|
||||
|
|
188
interface/src/avatar/AvatarActionKinematicHold.cpp
Normal file
188
interface/src/avatar/AvatarActionKinematicHold.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
//
|
||||
// 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),
|
||||
_previousPositionalTarget(Vectors::ZERO),
|
||||
_previousRotationalTarget(Quaternions::IDENTITY)
|
||||
{
|
||||
_type = ACTION_TYPE_KINEMATIC_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;
|
||||
}
|
||||
|
||||
assert(deltaTimeStep > 0.0f);
|
||||
|
||||
glm::quat rotation;
|
||||
glm::vec3 position;
|
||||
glm::vec3 offset;
|
||||
bool gotLock = withTryReadLock([&]{
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->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<ObjectMotionState*>(physicsInfo);
|
||||
btRigidBody* rigidBody = motionState ? motionState->getRigidBody() : nullptr;
|
||||
if (!rigidBody) {
|
||||
qDebug() << "ObjectActionSpring::updateActionWorker no rigidBody";
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
worldTrans.setOrigin(glmToBullet(_positionalTarget));
|
||||
worldTrans.setRotation(glmToBullet(_rotationalTarget));
|
||||
rigidBody->setWorldTransform(worldTrans);
|
||||
|
||||
_previousPositionalTarget = _positionalTarget;
|
||||
_previousRotationalTarget = _rotationalTarget;
|
||||
_previousSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (gotLock) {
|
||||
ObjectActionSpring::updateActionWorker(deltaTimeStep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AvatarActionKinematicHold::updateArguments(QVariantMap arguments) {
|
||||
if (!ObjectAction::updateArguments(arguments)) {
|
||||
return false;
|
||||
}
|
||||
bool ok = true;
|
||||
glm::vec3 relativePosition =
|
||||
EntityActionInterface::extractVec3Argument("kinematic-hold", arguments, "relativePosition", ok, false);
|
||||
if (!ok) {
|
||||
relativePosition = _relativePosition;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
glm::quat relativeRotation =
|
||||
EntityActionInterface::extractQuatArgument("kinematic-hold", arguments, "relativeRotation", ok, false);
|
||||
if (!ok) {
|
||||
relativeRotation = _relativeRotation;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
QString hand =
|
||||
EntityActionInterface::extractStringArgument("kinematic-hold", arguments, "hand", ok, false);
|
||||
if (!ok || !(hand == "left" || hand == "right")) {
|
||||
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) {
|
||||
withWriteLock([&] {
|
||||
_relativePosition = relativePosition;
|
||||
_relativeRotation = relativeRotation;
|
||||
_hand = hand;
|
||||
_setVelocity = setVelocity;
|
||||
|
||||
_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["setVelocity"] = _setVelocity;
|
||||
arguments["hand"] = _hand;
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
||||
|
||||
void AvatarActionKinematicHold::deserialize(QByteArray serializedArguments) {
|
||||
if (!_mine) {
|
||||
ObjectActionSpring::deserialize(serializedArguments);
|
||||
}
|
||||
}
|
47
interface/src/avatar/AvatarActionKinematicHold.h
Normal file
47
interface/src/avatar/AvatarActionKinematicHold.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// 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 <QUuid>
|
||||
|
||||
#include <EntityItem.h>
|
||||
#include <ObjectActionSpring.h>
|
||||
|
||||
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;
|
||||
|
||||
bool _previousSet = false;
|
||||
glm::vec3 _previousPositionalTarget;
|
||||
glm::quat _previousRotationalTarget;
|
||||
|
||||
bool _setVelocity = false;
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarActionKinematicHold_h
|
|
@ -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,
|
||||
|
|
|
@ -10,46 +10,12 @@
|
|||
//
|
||||
|
||||
#include "HMDScriptingInterface.h"
|
||||
|
||||
#include <QtScript/QScriptContext>
|
||||
|
||||
#include "display-plugins/DisplayPlugin.h"
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include "Application.h"
|
||||
|
||||
HMDScriptingInterface::HMDScriptingInterface() {
|
||||
}
|
||||
|
||||
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {
|
||||
glm::vec3 hudIntersection;
|
||||
auto instance = DependencyManager::get<HMDScriptingInterface>();
|
||||
if (instance->getHUDLookAtPosition3D(hudIntersection)) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->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<glm::vec2>(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<HMDScriptingInterface>();
|
||||
if (instance->getHUDLookAtPosition3D(result)) {
|
||||
return qScriptValueFromValue<glm::vec3>(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 {
|
||||
|
@ -64,6 +30,34 @@ 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<AvatarManager>()->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<glm::vec2>(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<glm::vec3>(engine, result);
|
||||
}
|
||||
return QScriptValue::NullValue;
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getIPD() const {
|
||||
return Application::getInstance()->getActiveDisplayPlugin()->getIPD();
|
||||
}
|
||||
|
||||
glm::vec3 HMDScriptingInterface::getPosition() const {
|
||||
if (Application::getInstance()->getActiveDisplayPlugin()->isHmd()) {
|
||||
return glm::vec3(Application::getInstance()->getActiveDisplayPlugin()->getHeadPose()[3]);
|
||||
|
|
|
@ -12,30 +12,32 @@
|
|||
#ifndef hifi_HMDScriptingInterface_h
|
||||
#define hifi_HMDScriptingInterface_h
|
||||
|
||||
#include <QtScript/QScriptValue>
|
||||
class QScriptContext;
|
||||
class QScriptEngine;
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <display-plugins/AbstractHMDScriptingInterface.h>
|
||||
|
||||
#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)
|
||||
Q_PROPERTY(glm::vec3 position READ getPosition)
|
||||
Q_PROPERTY(glm::quat orientation READ getOrientation)
|
||||
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;
|
||||
|
||||
// Get the position of the HMD
|
||||
glm::vec3 getPosition() const;
|
||||
|
||||
|
@ -43,6 +45,7 @@ private:
|
|||
glm::quat getOrientation() const;
|
||||
|
||||
bool getHUDLookAtPosition3D(glm::vec3& result) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_HMDScriptingInterface_h
|
||||
|
|
|
@ -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 <SettingHandle.h>
|
||||
|
||||
#include "DisplayPlugin.h"
|
||||
#include <plugins/PluginContainer.h>
|
||||
#include <OVR_CAPI_Keys.h>
|
||||
|
||||
static Setting::Handle<float> 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();
|
||||
}
|
|
@ -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 <GLMHelpers.h>
|
||||
|
||||
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
|
|
@ -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() {}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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 = extractTranslation(m) / m[3].w;
|
||||
glm::quat orientation = glm::quat_cast(m);
|
||||
ovrPosef result;
|
||||
result.Orientation = ovrFromGlm(orientation);
|
||||
result.Position = ovrFromGlm(translation);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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<QAction*> _screenActions;
|
||||
void StereoDisplayPlugin::activate() {
|
||||
auto screens = qApp->screens();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -100,6 +100,9 @@ EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeS
|
|||
if (normalizedActionTypeString == "hold") {
|
||||
return ACTION_TYPE_HOLD;
|
||||
}
|
||||
if (normalizedActionTypeString == "kinematichold") {
|
||||
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";
|
||||
|
@ -244,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)) {
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -69,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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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<void(bool)> 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;
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
@ -468,9 +467,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,
|
||||
});
|
||||
|
@ -478,8 +477,6 @@ function createPingPongBallGun() {
|
|||
setEntityCustomData(resetKey, pingPongGun, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
function createBasketballHoop() {
|
||||
|
|
Loading…
Reference in a new issue