diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index 8d13882d48..a98745b404 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -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 "" diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index f9d0ef5a71..9ef95b17da 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -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 "" diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 138240f5d6..07894b46d1 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -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 }); } diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 186b2ee828..ff72e95313 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -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 @@ -
- Animation Start Automatically - - - -
Textures
diff --git a/examples/particle_explorer/main.js b/examples/particle_explorer/main.js index 32ec12b640..a2a112d8e5 100644 --- a/examples/particle_explorer/main.js +++ b/examples/particle_explorer/main.js @@ -74,7 +74,9 @@ var keysToIgnore = [ 'shapeType', 'isEmitting', 'sittingPoints', - 'originalTextures' + 'originalTextures', + 'parentJointIndex', + 'parentID' ]; var individualKeys = []; diff --git a/examples/toybox/bow/bow.js b/examples/toybox/bow/bow.js index 90199fb70f..f0128acc77 100644 --- a/examples/toybox/bow/bow.js +++ b/examples/toybox/bow/bow.js @@ -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; diff --git a/examples/toybox/bow/createBow.js b/examples/toybox/bow/createBow.js index 9a9ed98c20..4f0cddfc0d 100644 --- a/examples/toybox/bow/createBow.js +++ b/examples/toybox/bow/createBow.js @@ -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) } diff --git a/examples/toybox/bubblewand/createWand.js b/examples/toybox/bubblewand/createWand.js index 6b4f9717ec..efd86b046f 100644 --- a/examples/toybox/bubblewand/createWand.js +++ b/examples/toybox/bubblewand/createWand.js @@ -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) } } }) -}); \ No newline at end of file +}); + +function scriptEnding() { + Entities.deleteEntity(wand); +} +Script.scriptEnding.connect(scriptEnding); diff --git a/examples/toybox/flashlight/flashlight.js b/examples/toybox/flashlight/flashlight.js index 8911c0ecd8..251ca71b7a 100644 --- a/examples/toybox/flashlight/flashlight.js +++ b/examples/toybox/flashlight/flashlight.js @@ -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') { diff --git a/examples/toybox/pistol/createPistol.js b/examples/toybox/pistol/createPistol.js index d804150cbe..693c53b9b4 100644 --- a/examples/toybox/pistol/createPistol.js +++ b/examples/toybox/pistol/createPistol.js @@ -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 } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6637331b64..34821e6737 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -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(); diff --git a/interface/src/avatar/MyCharacterController.cpp b/interface/src/avatar/MyCharacterController.cpp index e8f686da6f..23d601e58e 100644 --- a/interface/src/avatar/MyCharacterController.cpp +++ b/interface/src/avatar/MyCharacterController.cpp @@ -11,255 +11,25 @@ #include "MyCharacterController.h" -#include -#include -#include -#include - -#include -#include -#include +#include #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 -} diff --git a/interface/src/avatar/MyCharacterController.h b/interface/src/avatar/MyCharacterController.h index 82aa958309..39f0f99917 100644 --- a/interface/src/avatar/MyCharacterController.h +++ b/interface/src/avatar/MyCharacterController.h @@ -13,12 +13,8 @@ #ifndef hifi_MyCharacterController_h #define hifi_MyCharacterController_h -#include -#include - -#include #include -#include +//#include 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 diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index 6c34612e8c..08368597d0 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -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 }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 80710e9b96..880e4a16b3 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -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(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 88ccddc125..72211056d9 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -74,7 +74,7 @@ protected: ProgramPtr _program; ShapeWrapperPtr _plane; - Mutex _mutex; + mutable Mutex _mutex; SimpleMovingAverage _usecsPerFrame { 10 }; QMap _sceneTextureToFrameIndexMap; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 43c6373147..edbfb6158c 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -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); + } + } } diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index f9d8c07443..ef89128e30 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -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; diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index 8c40b0c036..8e85d8bc99 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -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); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index d040f785da..2e785519da 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -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); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b0b0e7c76a..d96814ff04 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -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; } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index cbd54f7168..2b8121c2f6 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -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(); } diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 0e21d4a40c..b81554511d 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -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() diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 6db35572b5..4b79572a07 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -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 }; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 5dd0248224..3b08c218a2 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -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(); 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: diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 348a7a4590..b6bf4b24c0 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -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; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 93fbe7acdc..81aae796c1 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -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; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index cd7b9a113c..ba48c4ccf1 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -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 diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 8da9541387..44d4269e0e 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -11,8 +11,55 @@ #include "CharacterController.h" +#include + +#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 +} diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index e9e6f1328e..6edbabdab8 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -17,11 +17,14 @@ #include #include +#include + 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 diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3306659c80..a075b0a91d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -82,7 +82,7 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { } Q_DECLARE_METATYPE(controller::InputController*) -static int inputControllerPointerId = qRegisterMetaType(); +//static int inputControllerPointerId = qRegisterMetaType(); QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) { return engine->newQObject(in); diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 7c057c7152..d6811c3529 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -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; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 711be6aa5e..1a26c6958b 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -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) diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index e6eae2cf02..c8fb0ba080 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -23,12 +23,16 @@ // ovr_CreateMirrorTextureGL, etc template struct RiftFramebufferWrapper : public FramebufferWrapper { - 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 { } protected: + virtual void destroyColor() { + } + virtual void initDepth() override final { } }; @@ -53,12 +60,6 @@ struct SwapFramebufferWrapper : public RiftFramebufferWrapperCurrentIndex; @@ -66,13 +67,17 @@ struct SwapFramebufferWrapper : public RiftFramebufferWrapper { 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. diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt new file mode 100644 index 0000000000..c3c4771276 --- /dev/null +++ b/plugins/openvr/CMakeLists.txt @@ -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() diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp similarity index 65% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp rename to plugins/openvr/src/OpenVrDisplayPlugin.cpp index 68a711a847..58f7536856 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -7,24 +7,23 @@ // #include "OpenVrDisplayPlugin.h" -#if defined(Q_OS_WIN) - #include #include +#include #include -#include #include #include +#include +#include + #include #include #include #include "OpenVrHelpers.h" -#include "GLMHelpers.h" -#include 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(); +} diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h similarity index 86% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h rename to plugins/openvr/src/OpenVrDisplayPlugin.h index d07add7ea5..8186e59936 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -9,10 +9,9 @@ #include -#if defined(Q_OS_WIN) #include -#include "../WindowOpenGLDisplayPlugin.h" +#include 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 - diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp similarity index 80% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp rename to plugins/openvr/src/OpenVrHelpers.cpp index f8e810beaf..7020fcb40d 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -7,14 +7,15 @@ // #include "OpenVrHelpers.h" -#if defined(Q_OS_WIN) - -#include - #include #include -#include "../Logging.h" +#include +#include +#include + + +Q_DECLARE_LOGGING_CATEGORY(displayplugins) using Mutex = std::mutex; using Lock = std::unique_lock; @@ -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 diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h b/plugins/openvr/src/OpenVrHelpers.h similarity index 89% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h rename to plugins/openvr/src/OpenVrHelpers.h index 3e445d90ba..513e1702d2 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h +++ b/plugins/openvr/src/OpenVrHelpers.h @@ -7,9 +7,6 @@ // #pragma once -#include - -#if defined(Q_OS_WIN) #include #include #include @@ -18,5 +15,3 @@ vr::IVRSystem* acquireOpenVrSystem(); void releaseOpenVrSystem(); -#endif - diff --git a/plugins/openvr/src/OpenVrProvider.cpp b/plugins/openvr/src/OpenVrProvider.cpp new file mode 100644 index 0000000000..66227a9543 --- /dev/null +++ b/plugins/openvr/src/OpenVrProvider.cpp @@ -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 + +#include +#include +#include + +#include + +#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" diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp similarity index 97% rename from libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp rename to plugins/openvr/src/ViveControllerManager.cpp index 5315152cea..39056cd46f 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -26,10 +25,10 @@ #include -#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(); @@ -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(); @@ -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) { diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h similarity index 98% rename from libraries/input-plugins/src/input-plugins/ViveControllerManager.h rename to plugins/openvr/src/ViveControllerManager.h index 02bdecb10a..077aec7fc3 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -20,7 +20,7 @@ #include #include #include -#include "InputPlugin.h" +#include #include #include diff --git a/plugins/openvr/src/plugin.json b/plugins/openvr/src/plugin.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/openvr/src/plugin.json @@ -0,0 +1 @@ +{}