mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 01:12:48 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into correct-target-frame-rate
This commit is contained in:
commit
83078b9d8c
43 changed files with 806 additions and 750 deletions
11
cmake/externals/LibOVR/CMakeLists.txt
vendored
11
cmake/externals/LibOVR/CMakeLists.txt
vendored
|
@ -15,17 +15,16 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
|||
# 0.6 public
|
||||
# URL http://static.oculus.com/sdk-downloads/0.6.0.1/Public/1435190862/ovr_sdk_win_0.6.0.1.zip
|
||||
# URL_MD5 4b3ef825f9a1d6d3035c9f6820687da9
|
||||
# 0.7 alpha
|
||||
# URL https://s3.amazonaws.com/static.oculus.com/sdk-downloads/0.7.0.0/Public/Alpha/ovr_sdk_win_0.7.0.0_RC1.zip
|
||||
# URL_MD5 a562bb9d117087b2cf9d86653ea70fd8
|
||||
|
||||
# 0.8 public
|
||||
# URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
|
||||
# URL_MD5 54944b03b95149d6010f84eb701b9647
|
||||
|
||||
if (WIN32)
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://static.oculus.com/sdk-downloads/0.6.0.1/Public/1435190862/ovr_sdk_win_0.6.0.1.zip
|
||||
URL_MD5 4b3ef825f9a1d6d3035c9f6820687da9
|
||||
URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
|
||||
URL_MD5 54944b03b95149d6010f84eb701b9647
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
|
5
cmake/externals/openvr/CMakeLists.txt
vendored
5
cmake/externals/openvr/CMakeLists.txt
vendored
|
@ -7,9 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
|||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
#URL https://github.com/ValveSoftware/openvr/archive/0.9.1.zip
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/openvr-0.9.1.zip
|
||||
URL_MD5 f986f5a6815e9454c53c5bf58ce02fdc
|
||||
URL https://github.com/ValveSoftware/openvr/archive/v0.9.12.zip
|
||||
URL_MD5 c08dced68ce4e341e1467e6814ae419d
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
|
|
@ -202,31 +202,41 @@ function entityIsGrabbedByOther(entityID) {
|
|||
}
|
||||
|
||||
function getSpatialOffsetPosition(hand, spatialKey) {
|
||||
var position = Vec3.ZERO;
|
||||
|
||||
if (hand !== RIGHT_HAND && spatialKey.leftRelativePosition) {
|
||||
return spatialKey.leftRelativePosition;
|
||||
position = spatialKey.leftRelativePosition;
|
||||
}
|
||||
if (hand === RIGHT_HAND && spatialKey.rightRelativePosition) {
|
||||
return spatialKey.rightRelativePosition;
|
||||
position = spatialKey.rightRelativePosition;
|
||||
}
|
||||
if (spatialKey.relativePosition) {
|
||||
return spatialKey.relativePosition;
|
||||
position = spatialKey.relativePosition;
|
||||
}
|
||||
|
||||
return Vec3.ZERO;
|
||||
return position;
|
||||
}
|
||||
|
||||
var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y);
|
||||
function getSpatialOffsetRotation(hand, spatialKey) {
|
||||
var rotation = Quat.IDENTITY;
|
||||
|
||||
if (hand !== RIGHT_HAND && spatialKey.leftRelativeRotation) {
|
||||
return spatialKey.leftRelativeRotation;
|
||||
rotation = spatialKey.leftRelativeRotation;
|
||||
}
|
||||
if (hand === RIGHT_HAND && spatialKey.rightRelativeRotation) {
|
||||
return spatialKey.rightRelativeRotation;
|
||||
rotation = spatialKey.rightRelativeRotation;
|
||||
}
|
||||
if (spatialKey.relativeRotation) {
|
||||
return spatialKey.relativeRotation;
|
||||
rotation = spatialKey.relativeRotation;
|
||||
}
|
||||
|
||||
return Quat.IDENTITY;
|
||||
// Flip left hand
|
||||
if (hand !== RIGHT_HAND) {
|
||||
rotation = Quat.multiply(yFlip, rotation);
|
||||
}
|
||||
|
||||
return rotation;
|
||||
}
|
||||
|
||||
function MyController(hand) {
|
||||
|
@ -254,6 +264,7 @@ function MyController(hand) {
|
|||
|
||||
this.overlayLine = null;
|
||||
|
||||
this.ignoreIK = false;
|
||||
this.offsetPosition = Vec3.ZERO;
|
||||
this.offsetRotation = Quat.IDENTITY;
|
||||
|
||||
|
@ -853,9 +864,12 @@ function MyController(hand) {
|
|||
|
||||
if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) {
|
||||
// if an object is "equipped" and has a spatialKey, use it.
|
||||
this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false;
|
||||
this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
|
||||
this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
|
||||
} else {
|
||||
this.ignoreIK = false;
|
||||
|
||||
var objectRotation = grabbedProperties.rotation;
|
||||
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||
|
||||
|
@ -872,7 +886,8 @@ function MyController(hand) {
|
|||
relativeRotation: this.offsetRotation,
|
||||
ttl: ACTION_TTL,
|
||||
kinematic: NEAR_GRABBING_KINEMATIC,
|
||||
kinematicSetVelocity: true
|
||||
kinematicSetVelocity: true,
|
||||
ignoreIK: this.ignoreIK
|
||||
});
|
||||
if (this.actionID === NULL_ACTION_ID) {
|
||||
this.actionID = null;
|
||||
|
@ -956,7 +971,8 @@ function MyController(hand) {
|
|||
relativeRotation: this.offsetRotation,
|
||||
ttl: ACTION_TTL,
|
||||
kinematic: NEAR_GRABBING_KINEMATIC,
|
||||
kinematicSetVelocity: true
|
||||
kinematicSetVelocity: true,
|
||||
ignoreIK: this.ignoreIK
|
||||
});
|
||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||
}
|
||||
|
@ -982,6 +998,7 @@ function MyController(hand) {
|
|||
// use a spring to pull the object to where it will be when equipped
|
||||
var relativeRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
|
||||
var relativePosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
|
||||
var ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false;
|
||||
var handRotation = this.getHandRotation();
|
||||
var handPosition = this.getHandPosition();
|
||||
var targetRotation = Quat.multiply(handRotation, relativeRotation);
|
||||
|
@ -996,7 +1013,8 @@ function MyController(hand) {
|
|||
linearTimeScale: EQUIP_SPRING_TIMEFRAME,
|
||||
targetRotation: targetRotation,
|
||||
angularTimeScale: EQUIP_SPRING_TIMEFRAME,
|
||||
ttl: ACTION_TTL
|
||||
ttl: ACTION_TTL,
|
||||
ignoreIK: ignoreIK
|
||||
});
|
||||
if (this.equipSpringID === NULL_ACTION_ID) {
|
||||
this.equipSpringID = null;
|
||||
|
@ -1009,7 +1027,8 @@ function MyController(hand) {
|
|||
linearTimeScale: EQUIP_SPRING_TIMEFRAME,
|
||||
targetRotation: targetRotation,
|
||||
angularTimeScale: EQUIP_SPRING_TIMEFRAME,
|
||||
ttl: ACTION_TTL
|
||||
ttl: ACTION_TTL,
|
||||
ignoreIK: ignoreIK
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -298,7 +298,6 @@
|
|||
var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame");
|
||||
var elModelAnimationLoop = document.getElementById("property-model-animation-loop");
|
||||
var elModelAnimationHold = document.getElementById("property-model-animation-hold");
|
||||
var elModelAnimationStartAutomatically = document.getElementById("property-model-animation-start-automatically");
|
||||
var elModelTextures = document.getElementById("property-model-textures");
|
||||
var elModelOriginalTextures = document.getElementById("property-model-original-textures");
|
||||
|
||||
|
@ -532,7 +531,6 @@
|
|||
elModelAnimationLastFrame.value = properties.animation.lastFrame;
|
||||
elModelAnimationLoop.checked = properties.animation.loop;
|
||||
elModelAnimationHold.checked = properties.animation.hold;
|
||||
elModelAnimationStartAutomatically.checked = properties.animation.startAutomatically;
|
||||
elModelTextures.value = properties.textures;
|
||||
elModelOriginalTextures.value = properties.originalTextures;
|
||||
} else if (properties.type == "Web") {
|
||||
|
@ -785,7 +783,6 @@
|
|||
elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame'));
|
||||
elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop'));
|
||||
elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold'));
|
||||
elModelAnimationStartAutomatically.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'startAutomatically'));
|
||||
|
||||
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
|
||||
|
||||
|
@ -1348,12 +1345,6 @@
|
|||
<input type='checkbox' id="property-model-animation-hold">
|
||||
</span>
|
||||
</div>
|
||||
<div class="model-section property">
|
||||
<span class="label">Animation Start Automatically</span>
|
||||
<span class="value">
|
||||
<input type='checkbox' id="property-model-animation-start-automatically">
|
||||
</span>
|
||||
</div>
|
||||
<div class="model-section property">
|
||||
<div class="label">Textures</div>
|
||||
<div class="value">
|
||||
|
|
|
@ -74,7 +74,9 @@ var keysToIgnore = [
|
|||
'shapeType',
|
||||
'isEmitting',
|
||||
'sittingPoints',
|
||||
'originalTextures'
|
||||
'originalTextures',
|
||||
'parentJointIndex',
|
||||
'parentID'
|
||||
];
|
||||
|
||||
var individualKeys = [];
|
||||
|
|
|
@ -66,21 +66,6 @@
|
|||
max2: 15
|
||||
}
|
||||
|
||||
var BOW_SPATIAL_KEY = {
|
||||
leftRelativePosition: {
|
||||
x: 0.05,
|
||||
y: 0.06,
|
||||
z: -0.05
|
||||
},
|
||||
rightRelativePosition: {
|
||||
x: -0.05,
|
||||
y: 0.06,
|
||||
z: -0.05
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(0, 90, -90)
|
||||
}
|
||||
|
||||
|
||||
var USE_DEBOUNCE = false;
|
||||
|
||||
var TRIGGER_CONTROLS = [
|
||||
|
@ -168,11 +153,9 @@
|
|||
var handToDisable = this.initialHand === 'right' ? 'left' : 'right';
|
||||
Messages.sendMessage('Hifi-Hand-Disabler', handToDisable);
|
||||
|
||||
setEntityCustomData('grabbableKey', this.entityID, {
|
||||
grabbable: false,
|
||||
invertSolidWhileHeld: true,
|
||||
spatialKey: BOW_SPATIAL_KEY
|
||||
});
|
||||
var data = getEntityCustomData('grabbableKey', this.entityID, {});
|
||||
data.grabbable = false;
|
||||
setEntityCustomData('grabbableKey', this.entityID, data);
|
||||
|
||||
},
|
||||
continueNearGrab: function() {
|
||||
|
@ -226,11 +209,10 @@
|
|||
this.isGrabbed = false;
|
||||
this.stringDrawn = false;
|
||||
this.deleteStrings();
|
||||
setEntityCustomData('grabbableKey', this.entityID, {
|
||||
grabbable: true,
|
||||
invertSolidWhileHeld: true,
|
||||
spatialKey: BOW_SPATIAL_KEY
|
||||
});
|
||||
|
||||
var data = getEntityCustomData('grabbableKey', this.entityID, {});
|
||||
data.grabbable = true;
|
||||
setEntityCustomData('grabbableKey', this.entityID, data);
|
||||
Entities.deleteEntity(this.preNotchString);
|
||||
Entities.deleteEntity(this.arrow);
|
||||
this.aiming = false;
|
||||
|
|
|
@ -49,14 +49,14 @@ var bow = Entities.addEntity({
|
|||
invertSolidWhileHeld: true,
|
||||
spatialKey: {
|
||||
leftRelativePosition: {
|
||||
x: 0.05,
|
||||
y: 0.06,
|
||||
z: -0.05
|
||||
x: -0.02,
|
||||
y: 0.08,
|
||||
z: 0.09
|
||||
},
|
||||
rightRelativePosition: {
|
||||
x: -0.05,
|
||||
y: 0.06,
|
||||
z: -0.05
|
||||
relativePosition: {
|
||||
x: 0.02,
|
||||
y: 0.08,
|
||||
z: 0.09
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(0, 90, -90)
|
||||
}
|
||||
|
|
|
@ -53,8 +53,13 @@ var wand = Entities.addEntity({
|
|||
y: 0.1,
|
||||
z: 0
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(0, 0, 90)
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(0, 0, -90)
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
function scriptEnding() {
|
||||
Entities.deleteEntity(wand);
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
//we are creating lights that we don't want to get stranded so lets make sure that we can get rid of them
|
||||
var startTime = Date.now();
|
||||
//if you're going to be using this in a dungeon or something and holding it for a long time, increase this lifetime value.
|
||||
var LIFETIME = 25;
|
||||
var LIFETIME = 100;
|
||||
var MSEC_PER_SEC = 1000.0;
|
||||
|
||||
// this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember
|
||||
|
@ -85,9 +85,14 @@
|
|||
this.hand = 'LEFT';
|
||||
},
|
||||
|
||||
startNearGrab: function() {
|
||||
startNearGrab: function(entityID) {
|
||||
if (!this.hasSpotlight) {
|
||||
|
||||
var modelProperties = Entities.getEntityProperties(this.entityID, ['position', 'rotation']);
|
||||
var lightTransform = evalLightWorldTransform(modelProperties.position, modelProperties.rotation);
|
||||
var glowLightTransform = glowLightWorldTransform(modelProperties.position, modelProperties.rotation);
|
||||
|
||||
|
||||
//this light casts the beam
|
||||
this.spotlight = Entities.addEntity({
|
||||
type: "Light",
|
||||
|
@ -97,6 +102,7 @@
|
|||
y: 2,
|
||||
z: 20
|
||||
},
|
||||
parentID: this.entityID,
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
|
@ -105,7 +111,9 @@
|
|||
intensity: 2,
|
||||
exponent: 0.3,
|
||||
cutoff: 20,
|
||||
lifetime: LIFETIME
|
||||
lifetime: LIFETIME,
|
||||
position: lightTransform.p,
|
||||
rotation: lightTransform.q,
|
||||
});
|
||||
|
||||
//this light creates the effect of a bulb at the end of the flashlight
|
||||
|
@ -116,6 +124,7 @@
|
|||
y: 0.25,
|
||||
z: 0.25
|
||||
},
|
||||
parentID: this.entityID,
|
||||
isSpotlight: false,
|
||||
color: {
|
||||
red: 255,
|
||||
|
@ -123,8 +132,11 @@
|
|||
blue: 255
|
||||
},
|
||||
exponent: 0,
|
||||
lifetime: LIFETIME,
|
||||
cutoff: 90, // in degrees
|
||||
lifetime: LIFETIME
|
||||
position: glowLightTransform.p,
|
||||
rotation: glowLightTransform.q,
|
||||
|
||||
});
|
||||
|
||||
this.hasSpotlight = true;
|
||||
|
@ -142,7 +154,6 @@
|
|||
//only set the active hand once -- if we always read the current hand, our 'holding' hand will get overwritten
|
||||
this.setWhichHand();
|
||||
} else {
|
||||
this.updateLightPositions();
|
||||
this.changeLightWithTriggerPressure(this.whichHand);
|
||||
}
|
||||
},
|
||||
|
@ -159,29 +170,7 @@
|
|||
this.lightOn = false;
|
||||
}
|
||||
},
|
||||
|
||||
updateLightPositions: function() {
|
||||
var modelProperties = Entities.getEntityProperties(this.entityID, ['position', 'rotation']);
|
||||
|
||||
//move the two lights along the vectors we set above
|
||||
var lightTransform = evalLightWorldTransform(modelProperties.position, modelProperties.rotation);
|
||||
var glowLightTransform = glowLightWorldTransform(modelProperties.position, modelProperties.rotation);
|
||||
|
||||
//move them with the entity model
|
||||
Entities.editEntity(this.spotlight, {
|
||||
position: lightTransform.p,
|
||||
rotation: lightTransform.q,
|
||||
lifetime: (Date.now() - startTime) / MSEC_PER_SEC + LIFETIME
|
||||
});
|
||||
|
||||
Entities.editEntity(this.glowLight, {
|
||||
position: glowLightTransform.p,
|
||||
rotation: glowLightTransform.q,
|
||||
lifetime: (Date.now() - startTime) / MSEC_PER_SEC + LIFETIME
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
|
||||
changeLightWithTriggerPressure: function(flashLightHand) {
|
||||
|
||||
if (flashLightHand === 'LEFT') {
|
||||
|
|
|
@ -28,10 +28,10 @@ var pistol = Entities.addEntity({
|
|||
spatialKey: {
|
||||
relativePosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
y: 0.05,
|
||||
z: -0.08
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(45, 90, 0)
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0)
|
||||
},
|
||||
invertSolidWhileHeld: true
|
||||
}
|
||||
|
|
|
@ -1058,7 +1058,7 @@ void MyAvatar::rebuildSkeletonBody() {
|
|||
void MyAvatar::prepareForPhysicsSimulation() {
|
||||
relayDriveKeysToCharacterController();
|
||||
_characterController.setTargetVelocity(getTargetVelocity());
|
||||
_characterController.setAvatarPositionAndOrientation(getPosition(), getOrientation());
|
||||
_characterController.setPositionAndOrientation(getPosition(), getOrientation());
|
||||
if (qApp->isHMDMode()) {
|
||||
updateHMDFollowVelocity();
|
||||
} else if (_followSpeed > 0.0f) {
|
||||
|
@ -1071,7 +1071,7 @@ void MyAvatar::prepareForPhysicsSimulation() {
|
|||
void MyAvatar::harvestResultsFromPhysicsSimulation() {
|
||||
glm::vec3 position = getPosition();
|
||||
glm::quat orientation = getOrientation();
|
||||
_characterController.getAvatarPositionAndOrientation(position, orientation);
|
||||
_characterController.getPositionAndOrientation(position, orientation);
|
||||
nextAttitude(position, orientation);
|
||||
if (_followSpeed > 0.0f) {
|
||||
adjustSensorTransform();
|
||||
|
|
|
@ -11,255 +11,25 @@
|
|||
|
||||
#include "MyCharacterController.h"
|
||||
|
||||
#include <BulletCollision/CollisionShapes/btMultiSphereShape.h>
|
||||
#include <BulletDynamics/Dynamics/btRigidBody.h>
|
||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
||||
#include <LinearMath/btDefaultMotionState.h>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <PhysicsLogging.h>
|
||||
#include <PhysicsCollisionGroups.h>
|
||||
#include <BulletUtil.h>
|
||||
|
||||
#include "MyAvatar.h"
|
||||
|
||||
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
|
||||
const float DEFAULT_GRAVITY = -5.0f;
|
||||
const float JUMP_SPEED = 3.5f;
|
||||
|
||||
const float MAX_FALL_HEIGHT = 20.0f;
|
||||
|
||||
// TODO: improve walking up steps
|
||||
// TODO: make avatars able to walk up and down steps/slopes
|
||||
// TODO: make avatars stand on steep slope
|
||||
// TODO: make avatars not snag on low ceilings
|
||||
|
||||
// helper class for simple ray-traces from character
|
||||
class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback {
|
||||
public:
|
||||
ClosestNotMe(btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0f, 0.0f, 0.0f), btVector3(0.0f, 0.0f, 0.0f)) {
|
||||
_me = me;
|
||||
}
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) {
|
||||
if (rayResult.m_collisionObject == _me) {
|
||||
return 1.0f;
|
||||
}
|
||||
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
||||
}
|
||||
protected:
|
||||
btRigidBody* _me;
|
||||
};
|
||||
|
||||
MyCharacterController::MyCharacterController(MyAvatar* avatar) {
|
||||
_halfHeight = 1.0f;
|
||||
|
||||
assert(avatar);
|
||||
_avatar = avatar;
|
||||
|
||||
_enabled = false;
|
||||
|
||||
_floorDistance = MAX_FALL_HEIGHT;
|
||||
|
||||
_walkVelocity.setValue(0.0f, 0.0f, 0.0f);
|
||||
_followVelocity.setValue(0.0f, 0.0f, 0.0f);
|
||||
_jumpSpeed = JUMP_SPEED;
|
||||
_isOnGround = false;
|
||||
_isJumping = false;
|
||||
_isFalling = false;
|
||||
_isHovering = true;
|
||||
_isPushingUp = false;
|
||||
_jumpToHoverStart = 0;
|
||||
_followTime = 0.0f;
|
||||
|
||||
_pendingFlags = PENDING_FLAG_UPDATE_SHAPE;
|
||||
updateShapeIfNecessary();
|
||||
}
|
||||
|
||||
MyCharacterController::~MyCharacterController() {
|
||||
}
|
||||
|
||||
void MyCharacterController::preStep(btCollisionWorld* collisionWorld) {
|
||||
// trace a ray straight down to see if we're standing on the ground
|
||||
const btTransform& xform = _rigidBody->getWorldTransform();
|
||||
|
||||
// rayStart is at center of bottom sphere
|
||||
btVector3 rayStart = xform.getOrigin() - _halfHeight * _currentUp;
|
||||
|
||||
// rayEnd is some short distance outside bottom sphere
|
||||
const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius;
|
||||
btScalar rayLength = _radius + FLOOR_PROXIMITY_THRESHOLD;
|
||||
btVector3 rayEnd = rayStart - rayLength * _currentUp;
|
||||
|
||||
// scan down for nearby floor
|
||||
ClosestNotMe rayCallback(_rigidBody);
|
||||
rayCallback.m_closestHitFraction = 1.0f;
|
||||
collisionWorld->rayTest(rayStart, rayEnd, rayCallback);
|
||||
if (rayCallback.hasHit()) {
|
||||
_floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius;
|
||||
}
|
||||
}
|
||||
|
||||
void MyCharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) {
|
||||
btVector3 actualVelocity = _rigidBody->getLinearVelocity();
|
||||
btScalar actualSpeed = actualVelocity.length();
|
||||
|
||||
btVector3 desiredVelocity = _walkVelocity;
|
||||
btScalar desiredSpeed = desiredVelocity.length();
|
||||
|
||||
const btScalar MIN_UP_PUSH = 0.1f;
|
||||
if (desiredVelocity.dot(_currentUp) < MIN_UP_PUSH) {
|
||||
_isPushingUp = false;
|
||||
}
|
||||
|
||||
const btScalar MIN_SPEED = 0.001f;
|
||||
if (_isHovering) {
|
||||
if (desiredSpeed < MIN_SPEED) {
|
||||
if (actualSpeed < MIN_SPEED) {
|
||||
_rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
const btScalar HOVER_BRAKING_TIMESCALE = 0.1f;
|
||||
btScalar tau = glm::max(dt / HOVER_BRAKING_TIMESCALE, 1.0f);
|
||||
_rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity);
|
||||
}
|
||||
} else {
|
||||
const btScalar HOVER_ACCELERATION_TIMESCALE = 0.1f;
|
||||
btScalar tau = dt / HOVER_ACCELERATION_TIMESCALE;
|
||||
_rigidBody->setLinearVelocity(actualVelocity - tau * (actualVelocity - desiredVelocity));
|
||||
}
|
||||
} else {
|
||||
if (onGround()) {
|
||||
// walking on ground
|
||||
if (desiredSpeed < MIN_SPEED) {
|
||||
if (actualSpeed < MIN_SPEED) {
|
||||
_rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
const btScalar HOVER_BRAKING_TIMESCALE = 0.1f;
|
||||
btScalar tau = dt / HOVER_BRAKING_TIMESCALE;
|
||||
_rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity);
|
||||
}
|
||||
} else {
|
||||
// TODO: modify desiredVelocity using floor normal
|
||||
const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f;
|
||||
btScalar tau = dt / WALK_ACCELERATION_TIMESCALE;
|
||||
btVector3 velocityCorrection = tau * (desiredVelocity - actualVelocity);
|
||||
// subtract vertical component
|
||||
velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp;
|
||||
_rigidBody->setLinearVelocity(actualVelocity + velocityCorrection);
|
||||
}
|
||||
} else {
|
||||
// transitioning to flying
|
||||
btVector3 velocityCorrection = desiredVelocity - actualVelocity;
|
||||
const btScalar FLY_ACCELERATION_TIMESCALE = 0.2f;
|
||||
btScalar tau = dt / FLY_ACCELERATION_TIMESCALE;
|
||||
if (!_isPushingUp) {
|
||||
// actually falling --> compute a different velocity attenuation factor
|
||||
const btScalar FALL_ACCELERATION_TIMESCALE = 2.0f;
|
||||
tau = dt / FALL_ACCELERATION_TIMESCALE;
|
||||
// zero vertical component
|
||||
velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp;
|
||||
}
|
||||
_rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection);
|
||||
}
|
||||
}
|
||||
|
||||
// Rather than add _followVelocity to the velocity of the RigidBody, we explicitly teleport
|
||||
// the RigidBody forward according to the formula: distance = rate * time
|
||||
if (_followVelocity.length2() > 0.0f) {
|
||||
btTransform bodyTransform = _rigidBody->getWorldTransform();
|
||||
bodyTransform.setOrigin(bodyTransform.getOrigin() + dt * _followVelocity);
|
||||
_rigidBody->setWorldTransform(bodyTransform);
|
||||
}
|
||||
_followTime += dt;
|
||||
}
|
||||
|
||||
void MyCharacterController::jump() {
|
||||
// check for case where user is holding down "jump" key...
|
||||
// we'll eventually tansition to "hover"
|
||||
if (!_isJumping) {
|
||||
if (!_isHovering) {
|
||||
_jumpToHoverStart = usecTimestampNow();
|
||||
_pendingFlags |= PENDING_FLAG_JUMP;
|
||||
}
|
||||
} else {
|
||||
quint64 now = usecTimestampNow();
|
||||
const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100);
|
||||
if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) {
|
||||
_isPushingUp = true;
|
||||
setHovering(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MyCharacterController::onGround() const {
|
||||
const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius;
|
||||
return _floorDistance < FLOOR_PROXIMITY_THRESHOLD;
|
||||
}
|
||||
|
||||
void MyCharacterController::setHovering(bool hover) {
|
||||
if (hover != _isHovering) {
|
||||
_isHovering = hover;
|
||||
_isJumping = false;
|
||||
|
||||
if (_rigidBody) {
|
||||
if (hover) {
|
||||
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
_rigidBody->setGravity(DEFAULT_GRAVITY * _currentUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyCharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) {
|
||||
_boxScale = scale;
|
||||
|
||||
float x = _boxScale.x;
|
||||
float z = _boxScale.z;
|
||||
float radius = 0.5f * sqrtf(0.5f * (x * x + z * z));
|
||||
float halfHeight = 0.5f * _boxScale.y - radius;
|
||||
float MIN_HALF_HEIGHT = 0.1f;
|
||||
if (halfHeight < MIN_HALF_HEIGHT) {
|
||||
halfHeight = MIN_HALF_HEIGHT;
|
||||
}
|
||||
|
||||
// compare dimensions
|
||||
float radiusDelta = glm::abs(radius - _radius);
|
||||
float heightDelta = glm::abs(halfHeight - _halfHeight);
|
||||
if (radiusDelta < FLT_EPSILON && heightDelta < FLT_EPSILON) {
|
||||
// shape hasn't changed --> nothing to do
|
||||
} else {
|
||||
if (_dynamicsWorld) {
|
||||
// must REMOVE from world prior to shape update
|
||||
_pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION;
|
||||
}
|
||||
_pendingFlags |= PENDING_FLAG_UPDATE_SHAPE;
|
||||
// only need to ADD back when we happen to be enabled
|
||||
if (_enabled) {
|
||||
_pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION;
|
||||
}
|
||||
}
|
||||
|
||||
// it's ok to change offset immediately -- there are no thread safety issues here
|
||||
_shapeLocalOffset = corner + 0.5f * _boxScale;
|
||||
}
|
||||
|
||||
void MyCharacterController::setEnabled(bool enabled) {
|
||||
if (enabled != _enabled) {
|
||||
if (enabled) {
|
||||
// Don't bother clearing REMOVE bit since it might be paired with an UPDATE_SHAPE bit.
|
||||
// Setting the ADD bit here works for all cases so we don't even bother checking other bits.
|
||||
_pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION;
|
||||
} else {
|
||||
if (_dynamicsWorld) {
|
||||
_pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION;
|
||||
}
|
||||
_pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION;
|
||||
_isOnGround = false;
|
||||
}
|
||||
setHovering(true);
|
||||
_enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void MyCharacterController::updateShapeIfNecessary() {
|
||||
if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) {
|
||||
_pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE;
|
||||
|
@ -300,7 +70,7 @@ void MyCharacterController::updateShapeIfNecessary() {
|
|||
if (_isHovering) {
|
||||
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
_rigidBody->setGravity(DEFAULT_GRAVITY * _currentUp);
|
||||
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
||||
}
|
||||
//_rigidBody->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
} else {
|
||||
|
@ -309,98 +79,3 @@ void MyCharacterController::updateShapeIfNecessary() {
|
|||
}
|
||||
}
|
||||
|
||||
void MyCharacterController::updateUpAxis(const glm::quat& rotation) {
|
||||
btVector3 oldUp = _currentUp;
|
||||
_currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS);
|
||||
if (!_isHovering) {
|
||||
const btScalar MIN_UP_ERROR = 0.01f;
|
||||
if (oldUp.distance(_currentUp) > MIN_UP_ERROR) {
|
||||
_rigidBody->setGravity(DEFAULT_GRAVITY * _currentUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyCharacterController::setAvatarPositionAndOrientation(
|
||||
const glm::vec3& position,
|
||||
const glm::quat& orientation) {
|
||||
// TODO: update gravity if up has changed
|
||||
updateUpAxis(orientation);
|
||||
|
||||
btQuaternion bodyOrientation = glmToBullet(orientation);
|
||||
btVector3 bodyPosition = glmToBullet(position + orientation * _shapeLocalOffset);
|
||||
_avatarBodyTransform = btTransform(bodyOrientation, bodyPosition);
|
||||
}
|
||||
|
||||
void MyCharacterController::getAvatarPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const {
|
||||
if (_enabled && _rigidBody) {
|
||||
const btTransform& avatarTransform = _rigidBody->getWorldTransform();
|
||||
rotation = bulletToGLM(avatarTransform.getRotation());
|
||||
position = bulletToGLM(avatarTransform.getOrigin()) - rotation * _shapeLocalOffset;
|
||||
}
|
||||
}
|
||||
|
||||
void MyCharacterController::setTargetVelocity(const glm::vec3& velocity) {
|
||||
//_walkVelocity = glmToBullet(_avatarData->getTargetVelocity());
|
||||
_walkVelocity = glmToBullet(velocity);
|
||||
}
|
||||
|
||||
void MyCharacterController::setFollowVelocity(const glm::vec3& velocity) {
|
||||
_followVelocity = glmToBullet(velocity);
|
||||
}
|
||||
|
||||
glm::vec3 MyCharacterController::getLinearVelocity() const {
|
||||
glm::vec3 velocity(0.0f);
|
||||
if (_rigidBody) {
|
||||
velocity = bulletToGLM(_rigidBody->getLinearVelocity());
|
||||
}
|
||||
return velocity;
|
||||
}
|
||||
|
||||
void MyCharacterController::preSimulation() {
|
||||
if (_enabled && _dynamicsWorld) {
|
||||
// slam body to where it is supposed to be
|
||||
_rigidBody->setWorldTransform(_avatarBodyTransform);
|
||||
|
||||
// scan for distant floor
|
||||
// rayStart is at center of bottom sphere
|
||||
btVector3 rayStart = _avatarBodyTransform.getOrigin() - _halfHeight * _currentUp;
|
||||
|
||||
// rayEnd is straight down MAX_FALL_HEIGHT
|
||||
btScalar rayLength = _radius + MAX_FALL_HEIGHT;
|
||||
btVector3 rayEnd = rayStart - rayLength * _currentUp;
|
||||
|
||||
ClosestNotMe rayCallback(_rigidBody);
|
||||
rayCallback.m_closestHitFraction = 1.0f;
|
||||
_dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback);
|
||||
if (rayCallback.hasHit()) {
|
||||
_floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius;
|
||||
const btScalar MIN_HOVER_HEIGHT = 3.0f;
|
||||
if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) {
|
||||
setHovering(false);
|
||||
}
|
||||
// TODO: use collision events rather than ray-trace test to disable jumping
|
||||
const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius;
|
||||
if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) {
|
||||
_isJumping = false;
|
||||
}
|
||||
} else {
|
||||
_floorDistance = FLT_MAX;
|
||||
setHovering(true);
|
||||
}
|
||||
|
||||
if (_pendingFlags & PENDING_FLAG_JUMP) {
|
||||
_pendingFlags &= ~ PENDING_FLAG_JUMP;
|
||||
if (onGround()) {
|
||||
_isJumping = true;
|
||||
btVector3 velocity = _rigidBody->getLinearVelocity();
|
||||
velocity += _jumpSpeed * _currentUp;
|
||||
_rigidBody->setLinearVelocity(velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
_followTime = 0.0f;
|
||||
}
|
||||
|
||||
void MyCharacterController::postSimulation() {
|
||||
// postSimulation() exists for symmetry and just in case we need to do something here later
|
||||
}
|
||||
|
|
|
@ -13,12 +13,8 @@
|
|||
#ifndef hifi_MyCharacterController_h
|
||||
#define hifi_MyCharacterController_h
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <BulletUtil.h>
|
||||
#include <CharacterController.h>
|
||||
#include <SharedUtil.h>
|
||||
//#include <SharedUtil.h>
|
||||
|
||||
class btCollisionShape;
|
||||
class MyAvatar;
|
||||
|
@ -28,79 +24,10 @@ public:
|
|||
MyCharacterController(MyAvatar* avatar);
|
||||
~MyCharacterController ();
|
||||
|
||||
// TODO: implement these when needed
|
||||
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); }
|
||||
virtual void reset(btCollisionWorld* collisionWorld) override { }
|
||||
virtual void warp(const btVector3& origin) override { }
|
||||
virtual void debugDraw(btIDebugDraw* debugDrawer) override { }
|
||||
virtual void setUpInterpolate(bool value) override { }
|
||||
|
||||
// overrides from btCharacterControllerInterface
|
||||
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override {
|
||||
preStep(collisionWorld);
|
||||
playerStep(collisionWorld, deltaTime);
|
||||
}
|
||||
virtual void preStep(btCollisionWorld* collisionWorld) override;
|
||||
virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt) override;
|
||||
virtual bool canJump() const override { assert(false); return false; } // never call this
|
||||
virtual void jump() override; // call this every frame the jump button is pressed
|
||||
virtual bool onGround() const override;
|
||||
|
||||
// overrides from CharacterController
|
||||
virtual void preSimulation() override;
|
||||
virtual void postSimulation() override;
|
||||
|
||||
bool isHovering() const { return _isHovering; }
|
||||
void setHovering(bool enabled);
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
bool isEnabled() const { return _enabled && _dynamicsWorld; }
|
||||
|
||||
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
|
||||
|
||||
virtual void updateShapeIfNecessary() override;
|
||||
|
||||
void setAvatarPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation);
|
||||
void getAvatarPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const;
|
||||
|
||||
void setTargetVelocity(const glm::vec3& velocity);
|
||||
void setFollowVelocity(const glm::vec3& velocity);
|
||||
float getFollowTime() const { return _followTime; }
|
||||
|
||||
glm::vec3 getLinearVelocity() const;
|
||||
|
||||
protected:
|
||||
void updateUpAxis(const glm::quat& rotation);
|
||||
|
||||
protected:
|
||||
btVector3 _currentUp;
|
||||
btVector3 _walkVelocity;
|
||||
btVector3 _followVelocity;
|
||||
btTransform _avatarBodyTransform;
|
||||
|
||||
glm::vec3 _shapeLocalOffset;
|
||||
glm::vec3 _boxScale; // used to compute capsule shape
|
||||
|
||||
quint64 _jumpToHoverStart;
|
||||
|
||||
MyAvatar* _avatar { nullptr };
|
||||
|
||||
btScalar _halfHeight;
|
||||
btScalar _radius;
|
||||
|
||||
btScalar _floorDistance;
|
||||
|
||||
btScalar _gravity;
|
||||
|
||||
btScalar _jumpSpeed;
|
||||
btScalar _followTime;
|
||||
|
||||
bool _enabled;
|
||||
bool _isOnGround;
|
||||
bool _isJumping;
|
||||
bool _isFalling;
|
||||
bool _isHovering;
|
||||
bool _isPushingUp;
|
||||
};
|
||||
|
||||
#endif // hifi_MyCharacterController_h
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#include "stereo/InterleavedStereoDisplayPlugin.h"
|
||||
#include "Basic2DWindowOpenGLDisplayPlugin.h"
|
||||
|
||||
#include "openvr/OpenVrDisplayPlugin.h"
|
||||
|
||||
const QString& DisplayPlugin::MENU_PATH() {
|
||||
static const QString value = "Display";
|
||||
return value;
|
||||
|
@ -25,22 +23,14 @@ const QString& DisplayPlugin::MENU_PATH() {
|
|||
DisplayPluginList getDisplayPlugins() {
|
||||
DisplayPlugin* PLUGIN_POOL[] = {
|
||||
new Basic2DWindowOpenGLDisplayPlugin(),
|
||||
new NullDisplayPlugin(),
|
||||
#ifdef DEBUG
|
||||
new NullDisplayPlugin(),
|
||||
#endif
|
||||
|
||||
// Stereo modes
|
||||
|
||||
// SBS left/right
|
||||
new SideBySideStereoDisplayPlugin(),
|
||||
// Interleaved left/right
|
||||
new InterleavedStereoDisplayPlugin(),
|
||||
|
||||
// HMDs
|
||||
//#ifdef Q_OS_WIN
|
||||
// // SteamVR SDK
|
||||
// new OpenVrDisplayPlugin(),
|
||||
//#endif
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <QtOpenGL/QGLWidget>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
|
||||
#include <gl/GLWidget.h>
|
||||
#include <NumericalConstants.h>
|
||||
|
@ -103,8 +104,12 @@ public:
|
|||
|
||||
// take the latest texture and present it
|
||||
_context->makeCurrent();
|
||||
currentPlugin->present();
|
||||
_context->doneCurrent();
|
||||
if (QOpenGLContext::currentContext() == _context->contextHandle()) {
|
||||
currentPlugin->present();
|
||||
_context->doneCurrent();
|
||||
} else {
|
||||
qWarning() << "Makecurrent failed";
|
||||
}
|
||||
}
|
||||
|
||||
_context->makeCurrent();
|
||||
|
|
|
@ -74,7 +74,7 @@ protected:
|
|||
ProgramPtr _program;
|
||||
ShapeWrapperPtr _plane;
|
||||
|
||||
Mutex _mutex;
|
||||
mutable Mutex _mutex;
|
||||
SimpleMovingAverage _usecsPerFrame { 10 };
|
||||
QMap<uint32_t, uint32_t> _sceneTextureToFrameIndexMap;
|
||||
|
||||
|
|
|
@ -60,9 +60,6 @@ public:
|
|||
void setTexture(gpu::TexturePointer texture) { _texture = texture; }
|
||||
const gpu::TexturePointer& getTexture() const { return _texture; }
|
||||
|
||||
bool getVisibleFlag() const { return _visibleFlag; }
|
||||
void setVisibleFlag(bool visibleFlag) { _visibleFlag = visibleFlag; }
|
||||
|
||||
void render(RenderArgs* args) const {
|
||||
assert(_pipeline);
|
||||
|
||||
|
@ -81,23 +78,23 @@ public:
|
|||
auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t);
|
||||
batch.drawIndexed(gpu::TRIANGLES, numIndices);
|
||||
}
|
||||
|
||||
EntityItemPointer _entity;
|
||||
|
||||
protected:
|
||||
EntityItemPointer _entity;
|
||||
Transform _modelTransform;
|
||||
AABox _bound;
|
||||
gpu::PipelinePointer _pipeline;
|
||||
gpu::Stream::FormatPointer _vertexFormat;
|
||||
gpu::BufferPointer _vertexBuffer;
|
||||
gpu::BufferPointer _indexBuffer;
|
||||
gpu::TexturePointer _texture;
|
||||
bool _visibleFlag = true;
|
||||
gpu::TexturePointer _texture;
|
||||
};
|
||||
|
||||
namespace render {
|
||||
template <>
|
||||
const ItemKey payloadGetKey(const ParticlePayload::Pointer& payload) {
|
||||
if (payload->getVisibleFlag()) {
|
||||
if (payload->_entity->getVisible()) {
|
||||
return ItemKey::Builder::transparentShape();
|
||||
} else {
|
||||
return ItemKey::Builder().withInvisible().build();
|
||||
|
@ -111,7 +108,10 @@ namespace render {
|
|||
|
||||
template <>
|
||||
void payloadRender(const ParticlePayload::Pointer& payload, RenderArgs* args) {
|
||||
payload->render(args);
|
||||
if (payload->_entity->getVisible()) {
|
||||
payload->render(args);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desire
|
|||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame, _animationLoop->getFirstFrame);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame, _animationLoop->getLastFrame);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold, _animationLoop->getHold);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically, _animationLoop->getStartAutomatically);
|
||||
} else {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
|
||||
|
@ -38,7 +37,6 @@ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desire
|
|||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +56,6 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo
|
|||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, firstFrame, float, _animationLoop->setFirstFrame);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, lastFrame, float, _animationLoop->setLastFrame);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, _animationLoop->setHold);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, startAutomatically, bool, _animationLoop->setStartAutomatically);
|
||||
|
||||
// legacy property support
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, _animationLoop->setFPS, _animationLoop->getFPS);
|
||||
|
@ -73,7 +70,6 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo
|
|||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, firstFrame, float, setFirstFrame);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, lastFrame, float, setLastFrame);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, setHold);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, startAutomatically, bool, setStartAutomatically);
|
||||
|
||||
// legacy property support
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, setFPS, getFPS);
|
||||
|
@ -95,7 +91,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
|
|||
float lastFrame = _animationLoop ? _animationLoop->getLastFrame() : getLastFrame();
|
||||
bool loop = _animationLoop ? _animationLoop->getLoop() : getLoop();
|
||||
bool hold = _animationLoop ? _animationLoop->getHold() : getHold();
|
||||
bool startAutomatically = _animationLoop ? _animationLoop->getStartAutomatically() : getStartAutomatically();
|
||||
|
||||
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
|
||||
QJsonObject settingsAsJsonObject = settingsAsJson.object();
|
||||
|
@ -130,10 +125,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
|
|||
running = settingsMap["hold"].toBool();
|
||||
}
|
||||
|
||||
if (settingsMap.contains("startAutomatically")) {
|
||||
running = settingsMap["startAutomatically"].toBool();
|
||||
}
|
||||
|
||||
if (_animationLoop) {
|
||||
_animationLoop->setFPS(fps);
|
||||
_animationLoop->setCurrentFrame(currentFrame);
|
||||
|
@ -142,7 +133,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
|
|||
_animationLoop->setLastFrame(lastFrame);
|
||||
_animationLoop->setLoop(loop);
|
||||
_animationLoop->setHold(hold);
|
||||
_animationLoop->setStartAutomatically(startAutomatically);
|
||||
} else {
|
||||
setFPS(fps);
|
||||
setCurrentFrame(currentFrame);
|
||||
|
@ -151,7 +141,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
|
|||
setLastFrame(lastFrame);
|
||||
setLoop(loop);
|
||||
setHold(hold);
|
||||
setStartAutomatically(startAutomatically);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +183,6 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, _animationLoop->getFirstFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, _animationLoop->getLastFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, _animationLoop->getHold());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, _animationLoop->getStartAutomatically());
|
||||
} else {
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
|
||||
|
@ -203,7 +191,6 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, getStartAutomatically());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -226,7 +213,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF
|
|||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, _animationLoop->setFirstFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, _animationLoop->setLastFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, _animationLoop->setHold);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, _animationLoop->setStartAutomatically);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
|
||||
|
@ -235,7 +221,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF
|
|||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, setStartAutomatically);
|
||||
}
|
||||
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_URL, URL);
|
||||
|
@ -246,7 +231,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF
|
|||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FIRST_FRAME, FirstFrame);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_START_AUTOMATICALLY, StartAutomatically);
|
||||
|
||||
processedBytes += bytesRead;
|
||||
|
||||
|
@ -273,7 +257,6 @@ EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FIRST_FRAME, firstFrame);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_START_AUTOMATICALLY, startAutomatically);
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
|
@ -288,7 +271,6 @@ void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) con
|
|||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, _animationLoop->getFirstFrame);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, _animationLoop->getLastFrame);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, _animationLoop->getHold);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, StartAutomatically, _animationLoop->getStartAutomatically);
|
||||
} else {
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FPS, getFPS);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentFrame, getCurrentFrame);
|
||||
|
@ -297,7 +279,6 @@ void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) con
|
|||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, getFirstFrame);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, getLastFrame);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, getHold);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, StartAutomatically, getStartAutomatically);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +294,6 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie
|
|||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, _animationLoop->setFirstFrame);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, _animationLoop->setLastFrame);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, _animationLoop->setHold);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, StartAutomatically, startAutomatically, _animationLoop->setStartAutomatically);
|
||||
} else {
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FPS, fps, setFPS);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentFrame, currentFrame, setCurrentFrame);
|
||||
|
@ -322,7 +302,6 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie
|
|||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, setFirstFrame);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, setLastFrame);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, setHold);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, StartAutomatically, startAutomatically, setStartAutomatically);
|
||||
}
|
||||
|
||||
return somethingChanged;
|
||||
|
@ -339,7 +318,6 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP
|
|||
requestedProperties += PROP_ANIMATION_FIRST_FRAME;
|
||||
requestedProperties += PROP_ANIMATION_LAST_FRAME;
|
||||
requestedProperties += PROP_ANIMATION_HOLD;
|
||||
requestedProperties += PROP_ANIMATION_START_AUTOMATICALLY;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -363,7 +341,6 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, _animationLoop->getFirstFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, _animationLoop->getLastFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, _animationLoop->getHold());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, _animationLoop->getStartAutomatically());
|
||||
} else {
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
|
||||
|
@ -372,7 +349,6 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, getStartAutomatically());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,7 +371,6 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char
|
|||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, _animationLoop->setFirstFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, _animationLoop->setLastFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, _animationLoop->setHold);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, _animationLoop->setStartAutomatically);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
|
||||
|
@ -404,7 +379,6 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char
|
|||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, setStartAutomatically);
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
|
|
|
@ -80,7 +80,6 @@ public:
|
|||
DEFINE_PROPERTY(PROP_ANIMATION_FIRST_FRAME, FirstFrame, firstFrame, float, 0.0f); // was animationSettings.firstFrame
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, AnimationLoop::MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, StartAutomatically, startAutomatically, bool, false); // was animationSettings.startAutomatically
|
||||
|
||||
protected:
|
||||
void setFromOldAnimationSettings(const QString& value);
|
||||
|
|
|
@ -747,7 +747,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically);
|
||||
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_CENTER, Atmosphere, atmosphere, Center, center);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_INNER_RADIUS, Atmosphere, atmosphere, InnerRadius, innerRadius);
|
||||
|
|
|
@ -384,11 +384,6 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
|
|||
setAnimationHold(hold);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("startAutomatically")) {
|
||||
bool startAutomatically = settingsMap["startAutomatically"].toBool();
|
||||
setAnimationStartAutomatically(startAutomatically);
|
||||
}
|
||||
|
||||
_dirtyFlags |= Simulation::DIRTY_UPDATEABLE;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,9 +97,6 @@ public:
|
|||
void setAnimationHold(bool hold) { _animationLoop.setHold(hold); }
|
||||
bool getAnimationHold() const { return _animationLoop.getHold(); }
|
||||
|
||||
void setAnimationStartAutomatically(bool startAutomatically) { _animationLoop.setStartAutomatically(startAutomatically); }
|
||||
bool getAnimationStartAutomatically() const { return _animationLoop.getStartAutomatically(); }
|
||||
|
||||
void setAnimationFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); }
|
||||
float getAnimationFirstFrame() const { return _animationLoop.getFirstFrame(); }
|
||||
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
set(TARGET_NAME input-plugins)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared plugins controllers script-engine render-utils)
|
||||
link_hifi_libraries(shared plugins controllers)
|
||||
|
||||
GroupSources("src/input-plugins")
|
||||
|
||||
if (WIN32)
|
||||
add_dependency_external_projects(OpenVR)
|
||||
find_package(OpenVR REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES})
|
||||
endif()
|
||||
|
||||
target_sdl2()
|
||||
target_sixense()
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "KeyboardMouseDevice.h"
|
||||
#include "SDL2Manager.h"
|
||||
#include "SixenseManager.h"
|
||||
#include "ViveControllerManager.h"
|
||||
|
||||
// TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class
|
||||
InputPluginList getInputPlugins() {
|
||||
|
@ -23,7 +22,6 @@ InputPluginList getInputPlugins() {
|
|||
new KeyboardMouseDevice(),
|
||||
new SDL2Manager(),
|
||||
new SixenseManager(),
|
||||
new ViveControllerManager(),
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <controllers/UserInputMapper.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <DebugDraw.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
|
@ -48,6 +49,8 @@ const QString MENU_PARENT = "Avatar";
|
|||
const QString MENU_NAME = "Sixense";
|
||||
const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
||||
const QString TOGGLE_SMOOTH = "Smooth Sixense Movement";
|
||||
const QString SHOW_DEBUG_RAW = "Debug Draw Raw Data";
|
||||
const QString SHOW_DEBUG_CALIBRATED = "Debug Draw Calibrated Data";
|
||||
|
||||
bool SixenseManager::isSupported() const {
|
||||
#ifdef HAVE_SIXENSE
|
||||
|
@ -72,6 +75,14 @@ void SixenseManager::activate() {
|
|||
[this] (bool clicked) { setSixenseFilter(clicked); },
|
||||
true, true);
|
||||
|
||||
_container->addMenuItem(PluginType::INPUT_PLUGIN, MENU_PATH, SHOW_DEBUG_RAW,
|
||||
[this] (bool clicked) { _inputDevice->setDebugDrawRaw(clicked); },
|
||||
true, false);
|
||||
|
||||
_container->addMenuItem(PluginType::INPUT_PLUGIN, MENU_PATH, SHOW_DEBUG_CALIBRATED,
|
||||
[this] (bool clicked) { _inputDevice->setDebugDrawCalibrated(clicked); },
|
||||
true, false);
|
||||
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->registerDevice(_inputDevice);
|
||||
|
||||
|
@ -149,6 +160,9 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
|||
// we only support two controllers
|
||||
SixenseControllerData controllers[2];
|
||||
|
||||
// store the raw controller data for debug rendering
|
||||
controller::Pose rawPoses[2];
|
||||
|
||||
int numActiveControllers = 0;
|
||||
for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) {
|
||||
if (!sixenseIsControllerEnabled(i)) {
|
||||
|
@ -175,7 +189,7 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
|||
// Rotation of Palm
|
||||
glm::quat rotation(data->rot_quat[3], data->rot_quat[0], data->rot_quat[1], data->rot_quat[2]);
|
||||
handlePoseEvent(deltaTime, position, rotation, left);
|
||||
|
||||
rawPoses[i] = controller::Pose(position, rotation, glm::vec3(0), glm::quat());
|
||||
} else {
|
||||
_poseStateMap.clear();
|
||||
_collectedSamples.clear();
|
||||
|
@ -197,9 +211,54 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
|||
_axisStateMap[axisState.first] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (_debugDrawCalibrated) {
|
||||
auto poseIter = _poseStateMap.find(controller::StandardPoseChannel::LEFT_HAND);
|
||||
if (poseIter != _poseStateMap.end() && poseIter->second.isValid()) {
|
||||
DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_CALIBRATED_LEFT", poseIter->second.rotation, poseIter->second.translation, glm::vec4(1));
|
||||
} else {
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_LEFT");
|
||||
}
|
||||
poseIter = _poseStateMap.find(controller::StandardPoseChannel::RIGHT_HAND);
|
||||
if (poseIter != _poseStateMap.end() && poseIter->second.isValid()) {
|
||||
DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_CALIBRATED_RIGHT", poseIter->second.rotation, poseIter->second.translation, glm::vec4(1));
|
||||
} else {
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_RIGHT");
|
||||
}
|
||||
}
|
||||
|
||||
if (_debugDrawRaw) {
|
||||
if (rawPoses[0].isValid()) {
|
||||
DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_RAW_LEFT", rawPoses[0].rotation, rawPoses[0].translation, glm::vec4(1));
|
||||
} else {
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_LEFT");
|
||||
}
|
||||
if (rawPoses[1].isValid()) {
|
||||
DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_RAW_RIGHT", rawPoses[1].rotation, rawPoses[1].translation, glm::vec4(1));
|
||||
} else {
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_RIGHT");
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_SIXENSE
|
||||
}
|
||||
|
||||
void SixenseManager::InputDevice::setDebugDrawRaw(bool flag) {
|
||||
_debugDrawRaw = flag;
|
||||
if (!flag) {
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_LEFT");
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_RIGHT");
|
||||
}
|
||||
}
|
||||
|
||||
void SixenseManager::InputDevice::setDebugDrawCalibrated(bool flag) {
|
||||
_debugDrawCalibrated = flag;
|
||||
if (!flag) {
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_LEFT");
|
||||
DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_RIGHT");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIXENSE
|
||||
|
||||
// the calibration sequence is:
|
||||
|
|
|
@ -60,6 +60,8 @@ private:
|
|||
class InputDevice : public controller::InputDevice {
|
||||
public:
|
||||
InputDevice() : controller::InputDevice("Hydra") {}
|
||||
void setDebugDrawRaw(bool flag);
|
||||
void setDebugDrawCalibrated(bool flag);
|
||||
private:
|
||||
// Device functions
|
||||
virtual controller::Input::NamedVector getAvailableInputs() const override;
|
||||
|
@ -82,6 +84,8 @@ private:
|
|||
|
||||
float _lastDistance;
|
||||
bool _requestReset { false };
|
||||
bool _debugDrawRaw { false };
|
||||
bool _debugDrawCalibrated { false };
|
||||
// these are measured values used to compute the calibration results
|
||||
quint64 _lockExpiry;
|
||||
glm::vec3 _averageLeft;
|
||||
|
|
|
@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_ENTITIES_HAVE_PARENTS;
|
||||
return VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP;
|
||||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
return 17;
|
||||
|
|
|
@ -161,5 +161,6 @@ const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48;
|
|||
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
|
||||
const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
|
||||
const PacketVersion VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -11,8 +11,55 @@
|
|||
|
||||
#include "CharacterController.h"
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
#include "BulletUtil.h"
|
||||
#include "PhysicsCollisionGroups.h"
|
||||
|
||||
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
|
||||
const float JUMP_SPEED = 3.5f;
|
||||
const float MAX_FALL_HEIGHT = 20.0f;
|
||||
|
||||
|
||||
// helper class for simple ray-traces from character
|
||||
class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback {
|
||||
public:
|
||||
ClosestNotMe(btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0f, 0.0f, 0.0f), btVector3(0.0f, 0.0f, 0.0f)) {
|
||||
_me = me;
|
||||
}
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) {
|
||||
if (rayResult.m_collisionObject == _me) {
|
||||
return 1.0f;
|
||||
}
|
||||
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
||||
}
|
||||
protected:
|
||||
btRigidBody* _me;
|
||||
};
|
||||
|
||||
|
||||
CharacterController::CharacterController() {
|
||||
_halfHeight = 1.0f;
|
||||
|
||||
_enabled = false;
|
||||
|
||||
_floorDistance = MAX_FALL_HEIGHT;
|
||||
|
||||
_walkVelocity.setValue(0.0f, 0.0f, 0.0f);
|
||||
_followVelocity.setValue(0.0f, 0.0f, 0.0f);
|
||||
_jumpSpeed = JUMP_SPEED;
|
||||
_isOnGround = false;
|
||||
_isJumping = false;
|
||||
_isFalling = false;
|
||||
_isHovering = true;
|
||||
_isPushingUp = false;
|
||||
_jumpToHoverStart = 0;
|
||||
_followTime = 0.0f;
|
||||
|
||||
_pendingFlags = PENDING_FLAG_UPDATE_SHAPE;
|
||||
|
||||
}
|
||||
|
||||
bool CharacterController::needsRemoval() const {
|
||||
return ((_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION) == PENDING_FLAG_REMOVE_FROM_SIMULATION);
|
||||
}
|
||||
|
@ -23,7 +70,7 @@ bool CharacterController::needsAddition() const {
|
|||
|
||||
void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
|
||||
if (_dynamicsWorld != world) {
|
||||
if (_dynamicsWorld) {
|
||||
if (_dynamicsWorld) {
|
||||
if (_rigidBody) {
|
||||
_dynamicsWorld->removeRigidBody(_rigidBody);
|
||||
_dynamicsWorld->removeAction(this);
|
||||
|
@ -33,9 +80,13 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
|
|||
if (world && _rigidBody) {
|
||||
_dynamicsWorld = world;
|
||||
_pendingFlags &= ~PENDING_FLAG_JUMP;
|
||||
// Before adding the RigidBody to the world we must save its oldGravity to the side
|
||||
// because adding an object to the world will overwrite it with the default gravity.
|
||||
btVector3 oldGravity = _rigidBody->getGravity();
|
||||
_dynamicsWorld->addRigidBody(_rigidBody, COLLISION_GROUP_MY_AVATAR, COLLISION_MASK_MY_AVATAR);
|
||||
_dynamicsWorld->addAction(this);
|
||||
//reset(_dynamicsWorld);
|
||||
// restore gravity settings
|
||||
_rigidBody->setGravity(oldGravity);
|
||||
}
|
||||
}
|
||||
if (_dynamicsWorld) {
|
||||
|
@ -48,5 +99,283 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
|
|||
} else {
|
||||
_pendingFlags &= ~PENDING_FLAG_REMOVE_FROM_SIMULATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::preStep(btCollisionWorld* collisionWorld) {
|
||||
// trace a ray straight down to see if we're standing on the ground
|
||||
const btTransform& xform = _rigidBody->getWorldTransform();
|
||||
|
||||
// rayStart is at center of bottom sphere
|
||||
btVector3 rayStart = xform.getOrigin() - _halfHeight * _currentUp;
|
||||
|
||||
// rayEnd is some short distance outside bottom sphere
|
||||
const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius;
|
||||
btScalar rayLength = _radius + FLOOR_PROXIMITY_THRESHOLD;
|
||||
btVector3 rayEnd = rayStart - rayLength * _currentUp;
|
||||
|
||||
// scan down for nearby floor
|
||||
ClosestNotMe rayCallback(_rigidBody);
|
||||
rayCallback.m_closestHitFraction = 1.0f;
|
||||
collisionWorld->rayTest(rayStart, rayEnd, rayCallback);
|
||||
if (rayCallback.hasHit()) {
|
||||
_floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius;
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) {
|
||||
btVector3 actualVelocity = _rigidBody->getLinearVelocity();
|
||||
btScalar actualSpeed = actualVelocity.length();
|
||||
|
||||
btVector3 desiredVelocity = _walkVelocity;
|
||||
btScalar desiredSpeed = desiredVelocity.length();
|
||||
|
||||
const btScalar MIN_UP_PUSH = 0.1f;
|
||||
if (desiredVelocity.dot(_currentUp) < MIN_UP_PUSH) {
|
||||
_isPushingUp = false;
|
||||
}
|
||||
|
||||
const btScalar MIN_SPEED = 0.001f;
|
||||
if (_isHovering) {
|
||||
if (desiredSpeed < MIN_SPEED) {
|
||||
if (actualSpeed < MIN_SPEED) {
|
||||
_rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
const btScalar HOVER_BRAKING_TIMESCALE = 0.1f;
|
||||
btScalar tau = glm::max(dt / HOVER_BRAKING_TIMESCALE, 1.0f);
|
||||
_rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity);
|
||||
}
|
||||
} else {
|
||||
const btScalar HOVER_ACCELERATION_TIMESCALE = 0.1f;
|
||||
btScalar tau = dt / HOVER_ACCELERATION_TIMESCALE;
|
||||
_rigidBody->setLinearVelocity(actualVelocity - tau * (actualVelocity - desiredVelocity));
|
||||
}
|
||||
} else {
|
||||
if (onGround()) {
|
||||
// walking on ground
|
||||
if (desiredSpeed < MIN_SPEED) {
|
||||
if (actualSpeed < MIN_SPEED) {
|
||||
_rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
const btScalar HOVER_BRAKING_TIMESCALE = 0.1f;
|
||||
btScalar tau = dt / HOVER_BRAKING_TIMESCALE;
|
||||
_rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity);
|
||||
}
|
||||
} else {
|
||||
// TODO: modify desiredVelocity using floor normal
|
||||
const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f;
|
||||
btScalar tau = dt / WALK_ACCELERATION_TIMESCALE;
|
||||
btVector3 velocityCorrection = tau * (desiredVelocity - actualVelocity);
|
||||
// subtract vertical component
|
||||
velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp;
|
||||
_rigidBody->setLinearVelocity(actualVelocity + velocityCorrection);
|
||||
}
|
||||
} else {
|
||||
// transitioning to flying
|
||||
btVector3 velocityCorrection = desiredVelocity - actualVelocity;
|
||||
const btScalar FLY_ACCELERATION_TIMESCALE = 0.2f;
|
||||
btScalar tau = dt / FLY_ACCELERATION_TIMESCALE;
|
||||
if (!_isPushingUp) {
|
||||
// actually falling --> compute a different velocity attenuation factor
|
||||
const btScalar FALL_ACCELERATION_TIMESCALE = 2.0f;
|
||||
tau = dt / FALL_ACCELERATION_TIMESCALE;
|
||||
// zero vertical component
|
||||
velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp;
|
||||
}
|
||||
_rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection);
|
||||
}
|
||||
}
|
||||
|
||||
// Rather than add _followVelocity to the velocity of the RigidBody, we explicitly teleport
|
||||
// the RigidBody forward according to the formula: distance = rate * time
|
||||
if (_followVelocity.length2() > 0.0f) {
|
||||
btTransform bodyTransform = _rigidBody->getWorldTransform();
|
||||
bodyTransform.setOrigin(bodyTransform.getOrigin() + dt * _followVelocity);
|
||||
_rigidBody->setWorldTransform(bodyTransform);
|
||||
}
|
||||
_followTime += dt;
|
||||
}
|
||||
|
||||
void CharacterController::jump() {
|
||||
// check for case where user is holding down "jump" key...
|
||||
// we'll eventually tansition to "hover"
|
||||
if (!_isJumping) {
|
||||
if (!_isHovering) {
|
||||
_jumpToHoverStart = usecTimestampNow();
|
||||
_pendingFlags |= PENDING_FLAG_JUMP;
|
||||
}
|
||||
} else {
|
||||
quint64 now = usecTimestampNow();
|
||||
const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100);
|
||||
if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) {
|
||||
_isPushingUp = true;
|
||||
setHovering(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterController::onGround() const {
|
||||
const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius;
|
||||
return _floorDistance < FLOOR_PROXIMITY_THRESHOLD;
|
||||
}
|
||||
|
||||
void CharacterController::setHovering(bool hover) {
|
||||
if (hover != _isHovering) {
|
||||
_isHovering = hover;
|
||||
_isJumping = false;
|
||||
|
||||
if (_rigidBody) {
|
||||
if (hover) {
|
||||
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) {
|
||||
_boxScale = scale;
|
||||
|
||||
float x = _boxScale.x;
|
||||
float z = _boxScale.z;
|
||||
float radius = 0.5f * sqrtf(0.5f * (x * x + z * z));
|
||||
float halfHeight = 0.5f * _boxScale.y - radius;
|
||||
float MIN_HALF_HEIGHT = 0.1f;
|
||||
if (halfHeight < MIN_HALF_HEIGHT) {
|
||||
halfHeight = MIN_HALF_HEIGHT;
|
||||
}
|
||||
|
||||
// compare dimensions
|
||||
float radiusDelta = glm::abs(radius - _radius);
|
||||
float heightDelta = glm::abs(halfHeight - _halfHeight);
|
||||
if (radiusDelta < FLT_EPSILON && heightDelta < FLT_EPSILON) {
|
||||
// shape hasn't changed --> nothing to do
|
||||
} else {
|
||||
if (_dynamicsWorld) {
|
||||
// must REMOVE from world prior to shape update
|
||||
_pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION;
|
||||
}
|
||||
_pendingFlags |= PENDING_FLAG_UPDATE_SHAPE;
|
||||
// only need to ADD back when we happen to be enabled
|
||||
if (_enabled) {
|
||||
_pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION;
|
||||
}
|
||||
}
|
||||
|
||||
// it's ok to change offset immediately -- there are no thread safety issues here
|
||||
_shapeLocalOffset = corner + 0.5f * _boxScale;
|
||||
}
|
||||
|
||||
void CharacterController::setEnabled(bool enabled) {
|
||||
if (enabled != _enabled) {
|
||||
if (enabled) {
|
||||
// Don't bother clearing REMOVE bit since it might be paired with an UPDATE_SHAPE bit.
|
||||
// Setting the ADD bit here works for all cases so we don't even bother checking other bits.
|
||||
_pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION;
|
||||
} else {
|
||||
if (_dynamicsWorld) {
|
||||
_pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION;
|
||||
}
|
||||
_pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION;
|
||||
_isOnGround = false;
|
||||
}
|
||||
setHovering(true);
|
||||
_enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::updateUpAxis(const glm::quat& rotation) {
|
||||
btVector3 oldUp = _currentUp;
|
||||
_currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS);
|
||||
if (!_isHovering) {
|
||||
const btScalar MIN_UP_ERROR = 0.01f;
|
||||
if (oldUp.distance(_currentUp) > MIN_UP_ERROR) {
|
||||
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::setPositionAndOrientation(
|
||||
const glm::vec3& position,
|
||||
const glm::quat& orientation) {
|
||||
// TODO: update gravity if up has changed
|
||||
updateUpAxis(orientation);
|
||||
|
||||
btQuaternion bodyOrientation = glmToBullet(orientation);
|
||||
btVector3 bodyPosition = glmToBullet(position + orientation * _shapeLocalOffset);
|
||||
_characterBodyTransform = btTransform(bodyOrientation, bodyPosition);
|
||||
}
|
||||
|
||||
void CharacterController::getPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const {
|
||||
if (_enabled && _rigidBody) {
|
||||
const btTransform& avatarTransform = _rigidBody->getWorldTransform();
|
||||
rotation = bulletToGLM(avatarTransform.getRotation());
|
||||
position = bulletToGLM(avatarTransform.getOrigin()) - rotation * _shapeLocalOffset;
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::setTargetVelocity(const glm::vec3& velocity) {
|
||||
//_walkVelocity = glmToBullet(_avatarData->getTargetVelocity());
|
||||
_walkVelocity = glmToBullet(velocity);
|
||||
}
|
||||
|
||||
void CharacterController::setFollowVelocity(const glm::vec3& velocity) {
|
||||
_followVelocity = glmToBullet(velocity);
|
||||
}
|
||||
|
||||
glm::vec3 CharacterController::getLinearVelocity() const {
|
||||
glm::vec3 velocity(0.0f);
|
||||
if (_rigidBody) {
|
||||
velocity = bulletToGLM(_rigidBody->getLinearVelocity());
|
||||
}
|
||||
return velocity;
|
||||
}
|
||||
|
||||
void CharacterController::preSimulation() {
|
||||
if (_enabled && _dynamicsWorld) {
|
||||
// slam body to where it is supposed to be
|
||||
_rigidBody->setWorldTransform(_characterBodyTransform);
|
||||
|
||||
// scan for distant floor
|
||||
// rayStart is at center of bottom sphere
|
||||
btVector3 rayStart = _characterBodyTransform.getOrigin() - _halfHeight * _currentUp;
|
||||
|
||||
// rayEnd is straight down MAX_FALL_HEIGHT
|
||||
btScalar rayLength = _radius + MAX_FALL_HEIGHT;
|
||||
btVector3 rayEnd = rayStart - rayLength * _currentUp;
|
||||
|
||||
ClosestNotMe rayCallback(_rigidBody);
|
||||
rayCallback.m_closestHitFraction = 1.0f;
|
||||
_dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback);
|
||||
if (rayCallback.hasHit()) {
|
||||
_floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius;
|
||||
const btScalar MIN_HOVER_HEIGHT = 3.0f;
|
||||
if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) {
|
||||
setHovering(false);
|
||||
}
|
||||
// TODO: use collision events rather than ray-trace test to disable jumping
|
||||
const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius;
|
||||
if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) {
|
||||
_isJumping = false;
|
||||
}
|
||||
} else {
|
||||
_floorDistance = FLT_MAX;
|
||||
setHovering(true);
|
||||
}
|
||||
|
||||
if (_pendingFlags & PENDING_FLAG_JUMP) {
|
||||
_pendingFlags &= ~ PENDING_FLAG_JUMP;
|
||||
if (onGround()) {
|
||||
_isJumping = true;
|
||||
btVector3 velocity = _rigidBody->getLinearVelocity();
|
||||
velocity += _jumpSpeed * _currentUp;
|
||||
_rigidBody->setLinearVelocity(velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
_followTime = 0.0f;
|
||||
}
|
||||
|
||||
void CharacterController::postSimulation() {
|
||||
// postSimulation() exists for symmetry and just in case we need to do something here later
|
||||
}
|
||||
|
|
|
@ -17,11 +17,14 @@
|
|||
#include <btBulletDynamicsCommon.h>
|
||||
#include <BulletDynamics/Character/btCharacterControllerInterface.h>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
const uint32_t PENDING_FLAG_ADD_TO_SIMULATION = 1U << 0;
|
||||
const uint32_t PENDING_FLAG_REMOVE_FROM_SIMULATION = 1U << 1;
|
||||
const uint32_t PENDING_FLAG_UPDATE_SHAPE = 1U << 2;
|
||||
const uint32_t PENDING_FLAG_JUMP = 1U << 3;
|
||||
|
||||
const float DEFAULT_CHARACTER_GRAVITY = -5.0f;
|
||||
|
||||
class btRigidBody;
|
||||
class btCollisionWorld;
|
||||
|
@ -29,31 +32,89 @@ class btDynamicsWorld;
|
|||
|
||||
class CharacterController : public btCharacterControllerInterface {
|
||||
public:
|
||||
CharacterController();
|
||||
virtual ~CharacterController() {}
|
||||
|
||||
bool needsRemoval() const;
|
||||
bool needsAddition() const;
|
||||
void setDynamicsWorld(btDynamicsWorld* world);
|
||||
btCollisionObject* getCollisionObject() { return _rigidBody; }
|
||||
|
||||
virtual void updateShapeIfNecessary() = 0;
|
||||
virtual void preSimulation() = 0;
|
||||
virtual void postSimulation() = 0;
|
||||
|
||||
// overrides from btCharacterControllerInterface
|
||||
virtual void setWalkDirection(const btVector3 &walkDirection) { assert(false); }
|
||||
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); }
|
||||
virtual void reset(btCollisionWorld* collisionWorld) override { }
|
||||
virtual void warp(const btVector3& origin) override { }
|
||||
virtual void debugDraw(btIDebugDraw* debugDrawer) override { }
|
||||
virtual void setUpInterpolate(bool value) override { }
|
||||
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override {
|
||||
preStep(collisionWorld);
|
||||
playerStep(collisionWorld, deltaTime);
|
||||
}
|
||||
virtual void preStep(btCollisionWorld *collisionWorld) override;
|
||||
virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override;
|
||||
virtual bool canJump() const override { assert(false); return false; } // never call this
|
||||
virtual void jump() override;
|
||||
virtual bool onGround() const;
|
||||
|
||||
void preSimulation();
|
||||
void postSimulation();
|
||||
|
||||
void setPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation);
|
||||
void getPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const;
|
||||
|
||||
void setTargetVelocity(const glm::vec3& velocity);
|
||||
void setFollowVelocity(const glm::vec3& velocity);
|
||||
float getFollowTime() const { return _followTime; }
|
||||
|
||||
glm::vec3 getLinearVelocity() const;
|
||||
|
||||
bool isHovering() const { return _isHovering; }
|
||||
void setHovering(bool enabled);
|
||||
|
||||
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
bool isEnabled() const { return _enabled && _dynamicsWorld; }
|
||||
|
||||
/* these from btCharacterControllerInterface remain to be overridden
|
||||
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual void warp(const btVector3 &origin) = 0;
|
||||
virtual void preStep(btCollisionWorld *collisionWorld) = 0;
|
||||
virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) = 0;
|
||||
virtual bool canJump() const = 0;
|
||||
virtual void jump() = 0;
|
||||
virtual bool onGround() const = 0;
|
||||
*/
|
||||
protected:
|
||||
void updateUpAxis(const glm::quat& rotation);
|
||||
|
||||
protected:
|
||||
btVector3 _currentUp;
|
||||
btVector3 _walkVelocity;
|
||||
btVector3 _followVelocity;
|
||||
btTransform _characterBodyTransform;
|
||||
|
||||
glm::vec3 _shapeLocalOffset;
|
||||
|
||||
glm::vec3 _boxScale; // used to compute capsule shape
|
||||
|
||||
quint64 _jumpToHoverStart;
|
||||
|
||||
btScalar _halfHeight;
|
||||
btScalar _radius;
|
||||
|
||||
btScalar _floorDistance;
|
||||
|
||||
btScalar _gravity;
|
||||
|
||||
btScalar _jumpSpeed;
|
||||
btScalar _followTime;
|
||||
|
||||
bool _enabled;
|
||||
bool _isOnGround;
|
||||
bool _isJumping;
|
||||
bool _isFalling;
|
||||
bool _isHovering;
|
||||
bool _isPushingUp;
|
||||
|
||||
btDynamicsWorld* _dynamicsWorld { nullptr };
|
||||
btRigidBody* _rigidBody { nullptr };
|
||||
uint32_t _pendingFlags { 0 };
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_CharacterControllerInterface_h
|
||||
|
|
|
@ -82,7 +82,7 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) {
|
|||
}
|
||||
|
||||
Q_DECLARE_METATYPE(controller::InputController*)
|
||||
static int inputControllerPointerId = qRegisterMetaType<controller::InputController*>();
|
||||
//static int inputControllerPointerId = qRegisterMetaType<controller::InputController*>();
|
||||
|
||||
QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) {
|
||||
return engine->newQObject(in);
|
||||
|
|
|
@ -20,9 +20,7 @@ glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseP
|
|||
}
|
||||
|
||||
void OculusBaseDisplayPlugin::resetSensors() {
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
ovr_RecenterPose(_hmd);
|
||||
#endif
|
||||
ovr_RecenterPose(_session);
|
||||
}
|
||||
|
||||
glm::mat4 OculusBaseDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
|
||||
|
@ -30,27 +28,39 @@ glm::mat4 OculusBaseDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
|
|||
}
|
||||
|
||||
glm::mat4 OculusBaseDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
auto frameTiming = ovr_GetFrameTiming(_hmd, frameIndex);
|
||||
auto trackingState = ovr_GetTrackingState(_hmd, frameTiming.DisplayMidpointSeconds);
|
||||
static uint32_t lastFrameSeen = 0;
|
||||
auto displayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
||||
auto trackingState = ovr_GetTrackingState(_session, displayTime, frameIndex > lastFrameSeen);
|
||||
if (frameIndex > lastFrameSeen) {
|
||||
lastFrameSeen = frameIndex;
|
||||
}
|
||||
return toGlm(trackingState.HeadPose.ThePose);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
||||
return false;
|
||||
}
|
||||
bool result = false;
|
||||
if (ovrHmd_Detect() > 0) {
|
||||
result = true;
|
||||
|
||||
ovrSession session { nullptr };
|
||||
ovrGraphicsLuid luid;
|
||||
auto result = ovr_Create(&session, &luid);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
ovrErrorInfo error;
|
||||
ovr_GetLastErrorInfo(&error);
|
||||
ovr_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto hmdDesc = ovr_GetHmdDesc(session);
|
||||
if (hmdDesc.Type == ovrHmd_None) {
|
||||
ovr_Destroy(session);
|
||||
ovr_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
ovr_Shutdown();
|
||||
return result;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// DLL based display plugins MUST initialize GLEW inside the DLL code.
|
||||
|
@ -69,28 +79,22 @@ void OculusBaseDisplayPlugin::deinit() {
|
|||
|
||||
void OculusBaseDisplayPlugin::activate() {
|
||||
WindowOpenGLDisplayPlugin::activate();
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
||||
qFatal("Could not init OVR");
|
||||
}
|
||||
|
||||
#if (OVR_MAJOR_VERSION == 6)
|
||||
if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) {
|
||||
#elif (OVR_MAJOR_VERSION == 7)
|
||||
if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) {
|
||||
#endif
|
||||
Q_ASSERT(false);
|
||||
if (!OVR_SUCCESS(ovr_Create(&_session, &_luid))) {
|
||||
qFatal("Failed to acquire HMD");
|
||||
}
|
||||
|
||||
_hmdDesc = ovr_GetHmdDesc(_hmd);
|
||||
_hmdDesc = ovr_GetHmdDesc(_session);
|
||||
|
||||
_ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd);
|
||||
_ipd = ovr_GetFloat(_session, OVR_KEY_IPD, _ipd);
|
||||
|
||||
glm::uvec2 eyeSizes[2];
|
||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
|
||||
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]);
|
||||
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
|
||||
ovrMatrix4f ovrPerspectiveProjection =
|
||||
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
|
||||
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
||||
|
@ -100,7 +104,7 @@ void OculusBaseDisplayPlugin::activate() {
|
|||
_compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
||||
|
||||
_eyeOffsets[eye] = erd.HmdToEyeViewOffset;
|
||||
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f));
|
||||
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
|
||||
});
|
||||
ovrFovPort combined = _eyeFovs[Left];
|
||||
combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan);
|
||||
|
@ -115,34 +119,33 @@ void OculusBaseDisplayPlugin::activate() {
|
|||
eyeSizes[0].x + eyeSizes[1].x,
|
||||
std::max(eyeSizes[0].y, eyeSizes[1].y));
|
||||
|
||||
if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd,
|
||||
if (!OVR_SUCCESS(ovr_ConfigureTracking(_session,
|
||||
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
|
||||
qFatal("Could not attach to sensor device");
|
||||
}
|
||||
|
||||
// Parent class relies on our _hmd intialization, so it must come after that.
|
||||
// Parent class relies on our _session intialization, so it must come after that.
|
||||
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
||||
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
|
||||
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
|
||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||
ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov;
|
||||
ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f);
|
||||
ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_session, eye, fov, 1.0f);
|
||||
_sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 };
|
||||
});
|
||||
|
||||
if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd,
|
||||
if (!OVR_SUCCESS(ovr_ConfigureTracking(_session,
|
||||
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
|
||||
qFatal("Could not attach to sensor device");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OculusBaseDisplayPlugin::deactivate() {
|
||||
WindowOpenGLDisplayPlugin::deactivate();
|
||||
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
ovr_Destroy(_hmd);
|
||||
_hmd = nullptr;
|
||||
ovr_Destroy(_session);
|
||||
_session = nullptr;
|
||||
ovr_Shutdown();
|
||||
#endif
|
||||
}
|
||||
|
@ -151,7 +154,7 @@ void OculusBaseDisplayPlugin::deactivate() {
|
|||
float OculusBaseDisplayPlugin::getIPD() const {
|
||||
float result = OVR_DEFAULT_IPD;
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
result = ovr_GetFloat(_hmd, OVR_KEY_IPD, result);
|
||||
result = ovr_GetFloat(_session, OVR_KEY_IPD, result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -43,17 +43,13 @@ protected:
|
|||
mat4 _compositeEyeProjections[2];
|
||||
uvec2 _desiredFramebufferSize;
|
||||
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
ovrHmd _hmd;
|
||||
ovrSession _session;
|
||||
ovrGraphicsLuid _luid;
|
||||
float _ipd{ OVR_DEFAULT_IPD };
|
||||
ovrEyeRenderDesc _eyeRenderDescs[2];
|
||||
ovrFovPort _eyeFovs[2];
|
||||
ovrHmdDesc _hmdDesc;
|
||||
ovrLayerEyeFov _sceneLayer;
|
||||
#endif
|
||||
#if (OVR_MAJOR_VERSION == 7)
|
||||
ovrGraphicsLuid _luid;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if (OVR_MAJOR_VERSION == 6)
|
||||
|
|
|
@ -23,12 +23,16 @@
|
|||
// ovr_CreateMirrorTextureGL, etc
|
||||
template <typename C>
|
||||
struct RiftFramebufferWrapper : public FramebufferWrapper<C, char> {
|
||||
ovrHmd hmd;
|
||||
RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) {
|
||||
ovrSession session;
|
||||
RiftFramebufferWrapper(const ovrSession& session) : session(session) {
|
||||
color = 0;
|
||||
depth = 0;
|
||||
};
|
||||
|
||||
~RiftFramebufferWrapper() {
|
||||
destroyColor();
|
||||
}
|
||||
|
||||
void Resize(const uvec2 & size) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo));
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
|
@ -39,6 +43,9 @@ struct RiftFramebufferWrapper : public FramebufferWrapper<C, char> {
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual void destroyColor() {
|
||||
}
|
||||
|
||||
virtual void initDepth() override final {
|
||||
}
|
||||
};
|
||||
|
@ -53,12 +60,6 @@ struct SwapFramebufferWrapper : public RiftFramebufferWrapper<ovrSwapTextureSet*
|
|||
: RiftFramebufferWrapper(hmd) {
|
||||
}
|
||||
|
||||
~SwapFramebufferWrapper() {
|
||||
if (color) {
|
||||
ovr_DestroySwapTextureSet(hmd, color);
|
||||
color = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Increment() {
|
||||
++color->CurrentIndex;
|
||||
|
@ -66,13 +67,17 @@ struct SwapFramebufferWrapper : public RiftFramebufferWrapper<ovrSwapTextureSet*
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual void initColor() override {
|
||||
virtual void destroyColor() override {
|
||||
if (color) {
|
||||
ovr_DestroySwapTextureSet(hmd, color);
|
||||
ovr_DestroySwapTextureSet(session, color);
|
||||
color = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!OVR_SUCCESS(ovr_CreateSwapTextureSetGL(hmd, GL_RGBA, size.x, size.y, &color))) {
|
||||
virtual void initColor() override {
|
||||
destroyColor();
|
||||
|
||||
if (!OVR_SUCCESS(ovr_CreateSwapTextureSetGL(session, GL_SRGB8_ALPHA8, size.x, size.y, &color))) {
|
||||
qFatal("Unable to create swap textures");
|
||||
}
|
||||
|
||||
|
@ -107,20 +112,17 @@ struct MirrorFramebufferWrapper : public RiftFramebufferWrapper<ovrGLTexture*> {
|
|||
MirrorFramebufferWrapper(const ovrHmd & hmd)
|
||||
: RiftFramebufferWrapper(hmd) { }
|
||||
|
||||
virtual ~MirrorFramebufferWrapper() {
|
||||
private:
|
||||
virtual void destroyColor() override {
|
||||
if (color) {
|
||||
ovr_DestroyMirrorTexture(hmd, (ovrTexture*)color);
|
||||
ovr_DestroyMirrorTexture(session, (ovrTexture*)color);
|
||||
color = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void initColor() override {
|
||||
if (color) {
|
||||
ovr_DestroyMirrorTexture(hmd, (ovrTexture*)color);
|
||||
color = nullptr;
|
||||
}
|
||||
ovrResult result = ovr_CreateMirrorTextureGL(hmd, GL_RGBA, size.x, size.y, (ovrTexture**)&color);
|
||||
destroyColor();
|
||||
ovrResult result = ovr_CreateMirrorTextureGL(session, GL_SRGB8_ALPHA8, size.x, size.y, (ovrTexture**)&color);
|
||||
Q_ASSERT(OVR_SUCCESS(result));
|
||||
}
|
||||
|
||||
|
@ -154,8 +156,7 @@ void OculusDisplayPlugin::activate() {
|
|||
|
||||
void OculusDisplayPlugin::customizeContext() {
|
||||
OculusBaseDisplayPlugin::customizeContext();
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd));
|
||||
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_session));
|
||||
_sceneFbo->Init(getRecommendedRenderSize());
|
||||
|
||||
// We're rendering both eyes to the same texture, so only one of the
|
||||
|
@ -163,7 +164,7 @@ void OculusDisplayPlugin::customizeContext() {
|
|||
_sceneLayer.ColorTexture[0] = _sceneFbo->color;
|
||||
// not needed since the structure was zeroed on init, but explicit
|
||||
_sceneLayer.ColorTexture[1] = nullptr;
|
||||
#endif
|
||||
|
||||
enableVsync(false);
|
||||
// Only enable mirroring if we know vsync is disabled
|
||||
_enablePreview = !isVsyncEnabled();
|
||||
|
@ -177,7 +178,6 @@ void OculusDisplayPlugin::uncustomizeContext() {
|
|||
}
|
||||
|
||||
void OculusDisplayPlugin::internalPresent() {
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
if (!_currentSceneTexture) {
|
||||
return;
|
||||
}
|
||||
|
@ -206,8 +206,10 @@ void OculusDisplayPlugin::internalPresent() {
|
|||
auto size = _sceneFbo->size;
|
||||
Context::Viewport(size.x, size.y);
|
||||
glBindTexture(GL_TEXTURE_2D, _currentSceneTexture);
|
||||
//glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
GLenum err = glGetError();
|
||||
drawUnitQuad();
|
||||
//glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
});
|
||||
|
||||
uint32_t frameIndex { 0 };
|
||||
|
@ -230,13 +232,12 @@ void OculusDisplayPlugin::internalPresent() {
|
|||
viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1];
|
||||
|
||||
ovrLayerHeader* layers = &_sceneLayer.Header;
|
||||
ovrResult result = ovr_SubmitFrame(_hmd, frameIndex, &viewScaleDesc, &layers, 1);
|
||||
ovrResult result = ovr_SubmitFrame(_session, frameIndex, &viewScaleDesc, &layers, 1);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
qDebug() << result;
|
||||
}
|
||||
}
|
||||
_sceneFbo->Increment();
|
||||
#endif
|
||||
|
||||
/*
|
||||
The swapbuffer call here is only required if we want to mirror the content to the screen.
|
||||
|
|
27
plugins/openvr/CMakeLists.txt
Normal file
27
plugins/openvr/CMakeLists.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# Created by Bradley Austin Davis on 2015/11/18
|
||||
# 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
|
||||
#
|
||||
|
||||
# OpenVR is disabled until a) it works with threaded present and
|
||||
# b) it doesn't interfere with Oculus SDK 0.8
|
||||
if (FALSE)
|
||||
#if (WIN32)
|
||||
# we're using static GLEW, so define GLEW_STATIC
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
set(TARGET_NAME openvr)
|
||||
setup_hifi_plugin(OpenGL Script Qml Widgets)
|
||||
link_hifi_libraries(shared gl networking controllers
|
||||
plugins display-plugins input-plugins script-engine
|
||||
render-utils model gpu render model-networking fbx)
|
||||
|
||||
include_hifi_library_headers(octree)
|
||||
|
||||
add_dependency_external_projects(OpenVR)
|
||||
find_package(OpenVR REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES})
|
||||
endif()
|
|
@ -7,24 +7,23 @@
|
|||
//
|
||||
#include "OpenVrDisplayPlugin.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QLoggingCategory>
|
||||
#include <QGLWidget>
|
||||
#include <GLMHelpers.h>
|
||||
#include <QEvent>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <gl/GlWindow.h>
|
||||
|
||||
#include <PerfStat.h>
|
||||
#include <plugins/PluginContainer.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "OpenVrHelpers.h"
|
||||
#include "GLMHelpers.h"
|
||||
|
||||
#include <QLoggingCategory>
|
||||
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||
Q_LOGGING_CATEGORY(displayplugins, "hifi.displayplugins")
|
||||
|
||||
|
@ -41,12 +40,11 @@ vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
|||
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
||||
static mat4 _sensorResetMat;
|
||||
static uvec2 _windowSize;
|
||||
static ivec2 _windowPosition;
|
||||
static uvec2 _renderTargetSize;
|
||||
|
||||
struct PerEyeData {
|
||||
uvec2 _viewportOrigin;
|
||||
uvec2 _viewportSize;
|
||||
//uvec2 _viewportOrigin;
|
||||
//uvec2 _viewportSize;
|
||||
mat4 _projectionMatrix;
|
||||
mat4 _eyeOffset;
|
||||
mat4 _pose;
|
||||
|
@ -89,36 +87,17 @@ void OpenVrDisplayPlugin::activate() {
|
|||
}
|
||||
Q_ASSERT(_hmd);
|
||||
|
||||
_hmd->GetWindowBounds(&_windowPosition.x, &_windowPosition.y, &_windowSize.x, &_windowSize.y);
|
||||
_hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y);
|
||||
// Recommended render target size is per-eye, so double the X size for
|
||||
// left + right eyes
|
||||
_renderTargetSize.x *= 2;
|
||||
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||
PerEyeData& eyeData = _eyesData[eye];
|
||||
_hmd->GetEyeOutputViewport(eye,
|
||||
&eyeData._viewportOrigin.x, &eyeData._viewportOrigin.y,
|
||||
&eyeData._viewportSize.x, &eyeData._viewportSize.y);
|
||||
eyeData._projectionMatrix = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
|
||||
eyeData._eyeOffset = toGlm(_hmd->GetEyeToHeadTransform(eye));
|
||||
});
|
||||
|
||||
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
_compositor = (vr::IVRCompositor*)vr::VR_GetGenericInterface(vr::IVRCompositor_Version, &eError);
|
||||
Q_ASSERT(eError == vr::HmdError_None);
|
||||
_compositor = vr::VRCompositor();
|
||||
Q_ASSERT(_compositor);
|
||||
|
||||
_compositor->SetGraphicsDevice(vr::Compositor_DeviceType_OpenGL, NULL);
|
||||
|
||||
uint32_t unSize = _compositor->GetLastError(NULL, 0);
|
||||
if (unSize > 1) {
|
||||
char* buffer = new char[unSize];
|
||||
_compositor->GetLastError(buffer, unSize);
|
||||
printf("Compositor - %s\n", buffer);
|
||||
delete[] buffer;
|
||||
}
|
||||
Q_ASSERT(unSize <= 1);
|
||||
WindowOpenGLDisplayPlugin::activate();
|
||||
}
|
||||
|
||||
|
@ -132,6 +111,16 @@ void OpenVrDisplayPlugin::deactivate() {
|
|||
WindowOpenGLDisplayPlugin::deactivate();
|
||||
}
|
||||
|
||||
void OpenVrDisplayPlugin::customizeContext() {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, []{
|
||||
glewExperimental = true;
|
||||
GLenum err = glewInit();
|
||||
glGetError();
|
||||
});
|
||||
WindowOpenGLDisplayPlugin::customizeContext();
|
||||
}
|
||||
|
||||
uvec2 OpenVrDisplayPlugin::getRecommendedRenderSize() const {
|
||||
return _renderTargetSize;
|
||||
}
|
||||
|
@ -153,33 +142,41 @@ glm::mat4 OpenVrDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
|
|||
}
|
||||
|
||||
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
||||
return _trackedDevicePoseMat4[0];
|
||||
glm::mat4 result;
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
result = _trackedDevicePoseMat4[0];
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void OpenVrDisplayPlugin::customizeContext() {
|
||||
WindowOpenGLDisplayPlugin::customizeContext();
|
||||
|
||||
void OpenVrDisplayPlugin::submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) {
|
||||
WindowOpenGLDisplayPlugin::submitSceneTexture(frameIndex, sceneTexture, sceneSize);
|
||||
}
|
||||
|
||||
//void OpenVrDisplayPlugin::display(uint32_t frameIndex, uint32_t finalTexture, const glm::uvec2& sceneSize) {
|
||||
// // Flip y-axis since GL UV coords are backwards.
|
||||
// static vr::Compositor_TextureBounds leftBounds{ 0, 1, 0.5f, 0 };
|
||||
// static vr::Compositor_TextureBounds rightBounds{ 0.5f, 1, 1, 0 };
|
||||
// _compositor->Submit(vr::Eye_Left, (void*)finalTexture, &leftBounds);
|
||||
// _compositor->Submit(vr::Eye_Right, (void*)finalTexture, &rightBounds);
|
||||
// glFinish();
|
||||
//}
|
||||
|
||||
//void OpenVrDisplayPlugin::finishFrame() {
|
||||
//// swapBuffers();
|
||||
// doneCurrent();
|
||||
// _compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount);
|
||||
// for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||
// _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
|
||||
// }
|
||||
// openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||
// _eyesData[eye]._pose = _trackedDevicePoseMat4[0];
|
||||
// });
|
||||
//};
|
||||
|
||||
#endif
|
||||
void OpenVrDisplayPlugin::internalPresent() {
|
||||
// Flip y-axis since GL UV coords are backwards.
|
||||
static vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 };
|
||||
static vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 };
|
||||
vr::Texture_t texture{ (void*)_currentSceneTexture, vr::API_OpenGL, vr::ColorSpace_Auto };
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
_compositor->Submit(vr::Eye_Left, &texture, &leftBounds);
|
||||
_compositor->Submit(vr::Eye_Right, &texture, &rightBounds);
|
||||
}
|
||||
glFinish();
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
_compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
|
||||
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
|
||||
}
|
||||
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||
_eyesData[eye]._pose = _trackedDevicePoseMat4[0];
|
||||
});
|
||||
}
|
||||
|
||||
//WindowOpenGLDisplayPlugin::internalPresent();
|
||||
}
|
|
@ -9,10 +9,9 @@
|
|||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <openvr.h>
|
||||
|
||||
#include "../WindowOpenGLDisplayPlugin.h"
|
||||
#include <display-plugins/WindowOpenGLDisplayPlugin.h>
|
||||
|
||||
const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only.
|
||||
|
||||
|
@ -27,6 +26,8 @@ public:
|
|||
virtual void activate() override;
|
||||
virtual void deactivate() override;
|
||||
|
||||
virtual void customizeContext() override;
|
||||
|
||||
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
||||
virtual glm::uvec2 getRecommendedUiSize() const override { return uvec2(1920, 1080); }
|
||||
|
||||
|
@ -36,15 +37,13 @@ public:
|
|||
|
||||
virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override;
|
||||
virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override;
|
||||
virtual void submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) override;
|
||||
|
||||
protected:
|
||||
// virtual void display(uint32_t frameIndex, uint32_t finalTexture, const glm::uvec2& sceneSize) override;
|
||||
virtual void customizeContext() override;
|
||||
virtual void internalPresent() override;
|
||||
|
||||
private:
|
||||
vr::IVRSystem* _hmd { nullptr };
|
||||
static const QString NAME;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -7,14 +7,15 @@
|
|||
//
|
||||
#include "OpenVrHelpers.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
#include "../Logging.h"
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
|
@ -30,13 +31,13 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
|||
if (hmdPresent) {
|
||||
Lock lock(mutex);
|
||||
if (!activeHmd) {
|
||||
qCDebug(displayPlugins) << "openvr: No vr::IVRSystem instance active, building";
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
qCDebug(displayplugins) << "openvr: No vr::IVRSystem instance active, building";
|
||||
vr::EVRInitError eError = vr::VRInitError_None;
|
||||
activeHmd = vr::VR_Init(&eError);
|
||||
qCDebug(displayPlugins) << "openvr display: HMD is " << activeHmd << " error is " << eError;
|
||||
qCDebug(displayplugins) << "openvr display: HMD is " << activeHmd << " error is " << eError;
|
||||
}
|
||||
if (activeHmd) {
|
||||
qCDebug(displayPlugins) << "openvr: incrementing refcount";
|
||||
qCDebug(displayplugins) << "openvr: incrementing refcount";
|
||||
++refCount;
|
||||
}
|
||||
}
|
||||
|
@ -46,10 +47,10 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
|||
void releaseOpenVrSystem() {
|
||||
if (activeHmd) {
|
||||
Lock lock(mutex);
|
||||
qDebug() << "openvr: decrementing refcount";
|
||||
qCDebug(displayplugins) << "openvr: decrementing refcount";
|
||||
--refCount;
|
||||
if (0 == refCount) {
|
||||
qDebug() << "openvr: zero refcount, deallocate VR system";
|
||||
qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system";
|
||||
// Avoid spamming the VR system with activate/deactivate calls at system startup by
|
||||
// putting in a delay before we destory the shutdown the VR subsystem
|
||||
|
||||
|
@ -71,5 +72,3 @@ void releaseOpenVrSystem() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -7,9 +7,6 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <openvr.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
@ -18,5 +15,3 @@
|
|||
vr::IVRSystem* acquireOpenVrSystem();
|
||||
void releaseOpenVrSystem();
|
||||
|
||||
#endif
|
||||
|
60
plugins/openvr/src/OpenVrProvider.cpp
Normal file
60
plugins/openvr/src/OpenVrProvider.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/10/25
|
||||
// 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 <mutex>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QtPlugin>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <plugins/RuntimePlugin.h>
|
||||
|
||||
#include "OpenVrDisplayPlugin.h"
|
||||
#include "ViveControllerManager.h"
|
||||
|
||||
class OpenVrProvider : public QObject, public DisplayProvider, InputProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID DisplayProvider_iid FILE "plugin.json")
|
||||
Q_INTERFACES(DisplayProvider)
|
||||
Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json")
|
||||
Q_INTERFACES(InputProvider)
|
||||
|
||||
public:
|
||||
OpenVrProvider(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~OpenVrProvider() {}
|
||||
|
||||
virtual DisplayPluginList getDisplayPlugins() override {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
DisplayPluginPointer plugin(new OpenVrDisplayPlugin());
|
||||
if (plugin->isSupported()) {
|
||||
_displayPlugins.push_back(plugin);
|
||||
}
|
||||
});
|
||||
return _displayPlugins;
|
||||
}
|
||||
|
||||
virtual InputPluginList getInputPlugins() override {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
InputPluginPointer plugin(new ViveControllerManager());
|
||||
if (plugin->isSupported()) {
|
||||
_inputPlugins.push_back(plugin);
|
||||
}
|
||||
});
|
||||
return _inputPlugins;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
DisplayPluginList _displayPlugins;
|
||||
InputPluginList _inputPlugins;
|
||||
};
|
||||
|
||||
#include "OpenVrProvider.moc"
|
|
@ -17,7 +17,6 @@
|
|||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <display-plugins/openvr/OpenVrHelpers.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <plugins/PluginContainer.h>
|
||||
#include <UserActivityLogger.h>
|
||||
|
@ -26,10 +25,10 @@
|
|||
|
||||
#include <controllers/StandardControls.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "OpenVrHelpers.h"
|
||||
|
||||
extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||
extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
||||
#endif
|
||||
|
||||
vr::IVRSystem* acquireOpenVrSystem();
|
||||
void releaseOpenVrSystem();
|
||||
|
@ -39,7 +38,7 @@ static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
|||
static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||
CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||
CONTROLLER_LENGTH_OFFSET * 2.0f);
|
||||
static const QString CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
|
||||
static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
|
||||
|
||||
static const QString MENU_PARENT = "Avatar";
|
||||
static const QString MENU_NAME = "Vive Controllers";
|
||||
|
@ -49,19 +48,14 @@ static const QString RENDER_CONTROLLERS = "Render Hand Controllers";
|
|||
const QString ViveControllerManager::NAME = "OpenVR";
|
||||
|
||||
bool ViveControllerManager::isSupported() const {
|
||||
#ifdef Q_OS_WIN
|
||||
auto hmd = acquireOpenVrSystem();
|
||||
bool success = hmd != nullptr;
|
||||
releaseOpenVrSystem();
|
||||
return success;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ViveControllerManager::activate() {
|
||||
InputPlugin::activate();
|
||||
#ifdef Q_OS_WIN
|
||||
_container->addMenu(MENU_PATH);
|
||||
_container->addMenuItem(PluginType::INPUT_PLUGIN, MENU_PATH, RENDER_CONTROLLERS,
|
||||
[this] (bool clicked) { this->setRenderControllers(clicked); },
|
||||
|
@ -72,8 +66,11 @@ void ViveControllerManager::activate() {
|
|||
}
|
||||
Q_ASSERT(_hmd);
|
||||
|
||||
auto renderModels = vr::VRRenderModels();
|
||||
|
||||
vr::RenderModel_t model;
|
||||
if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING.toStdString().c_str(), &model)) {
|
||||
/*
|
||||
if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) {
|
||||
qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING);
|
||||
} else {
|
||||
model::Mesh* mesh = new model::Mesh();
|
||||
|
@ -118,7 +115,7 @@ void ViveControllerManager::activate() {
|
|||
_modelLoaded = true;
|
||||
_renderControllers = true;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
// unregister with UserInputMapper
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
|
@ -129,7 +126,6 @@ void ViveControllerManager::activate() {
|
|||
void ViveControllerManager::deactivate() {
|
||||
InputPlugin::deactivate();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
_container->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS);
|
||||
_container->removeMenu(MENU_PATH);
|
||||
|
||||
|
@ -139,7 +135,6 @@ void ViveControllerManager::deactivate() {
|
|||
}
|
||||
|
||||
_inputDevice->_poseStateMap.clear();
|
||||
#endif
|
||||
|
||||
// unregister with UserInputMapper
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
|
@ -225,7 +220,6 @@ void ViveControllerManager::pluginUpdate(float deltaTime, bool jointsCaptured) {
|
|||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
||||
#ifdef Q_OS_WIN
|
||||
_poseStateMap.clear();
|
||||
|
||||
_buttonPressedMap.clear();
|
||||
|
@ -276,7 +270,6 @@ void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCapt
|
|||
}
|
||||
|
||||
_trackedControllers = numTrackedControllers;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::focusOutEvent() {
|
||||
|
@ -286,7 +279,6 @@ void ViveControllerManager::InputDevice::focusOutEvent() {
|
|||
|
||||
// These functions do translation from the Steam IDs to the standard controller IDs
|
||||
void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x, float y, bool left) {
|
||||
#ifdef Q_OS_WIN
|
||||
//FIX ME? It enters here every frame: probably we want to enter only if an event occurs
|
||||
axis += vr::k_EButton_Axis0;
|
||||
using namespace controller;
|
||||
|
@ -296,12 +288,10 @@ void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x,
|
|||
} else if (axis == vr::k_EButton_SteamVR_Trigger) {
|
||||
_axisStateMap[left ? LT : RT] = x;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// These functions do translation from the Steam IDs to the standard controller IDs
|
||||
void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool pressed, bool left) {
|
||||
#ifdef Q_OS_WIN
|
||||
if (!pressed) {
|
||||
return;
|
||||
}
|
||||
|
@ -319,7 +309,6 @@ void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool
|
|||
//FIX ME: not able to ovrewrite the behaviour of this button
|
||||
_buttonPressedMap.insert(left ? controller::LEFT_SECONDARY_THUMB : controller::RIGHT_SECONDARY_THUMB);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::handlePoseEvent(const mat4& mat, bool left) {
|
|
@ -20,7 +20,7 @@
|
|||
#include <model/Geometry.h>
|
||||
#include <gpu/Texture.h>
|
||||
#include <controllers/InputDevice.h>
|
||||
#include "InputPlugin.h"
|
||||
#include <plugins/InputPlugin.h>
|
||||
#include <RenderArgs.h>
|
||||
#include <render/Scene.h>
|
||||
|
1
plugins/openvr/src/plugin.json
Normal file
1
plugins/openvr/src/plugin.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
Loading…
Reference in a new issue