From 807d31743c5b6786306d2e43c52654e0b587ed96 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Mar 2016 19:33:31 -0800 Subject: [PATCH 1/4] Removed Hand, HandData & PalmData Instead, we just store two controller::Poses in MyAvatar. Existing behavior and scripting APIs have been preserved. The hand controller debug drawing is slightly different, but still works. --- interface/src/Application.cpp | 52 +----- interface/src/Application.h | 4 +- interface/src/Menu.cpp | 3 +- interface/src/avatar/Avatar.cpp | 12 -- interface/src/avatar/Avatar.h | 3 +- interface/src/avatar/AvatarActionHold.cpp | 79 ++++---- interface/src/avatar/Hand.cpp | 101 ---------- interface/src/avatar/Hand.h | 36 ---- interface/src/avatar/MyAvatar.cpp | 110 +++++++---- interface/src/avatar/MyAvatar.h | 9 + interface/src/avatar/SkeletonModel.cpp | 28 +-- interface/src/avatar/SkeletonModel.h | 1 - .../ControllerScriptingInterface.cpp | 1 - libraries/avatars/src/AvatarData.cpp | 7 - libraries/avatars/src/AvatarData.h | 4 +- libraries/avatars/src/HandData.cpp | 110 ----------- libraries/avatars/src/HandData.h | 174 ------------------ 17 files changed, 149 insertions(+), 585 deletions(-) delete mode 100644 interface/src/avatar/Hand.cpp delete mode 100644 interface/src/avatar/Hand.h delete mode 100644 libraries/avatars/src/HandData.cpp delete mode 100644 libraries/avatars/src/HandData.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4ae63f817a..728691a0e1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3216,11 +3216,10 @@ void Application::update(float deltaTime) { myAvatar->setDriveKeys(ZOOM, userInputMapper->getActionState(controller::Action::TRANSLATE_CAMERA_Z)); } - controller::Pose leftHand = userInputMapper->getPoseState(controller::Action::LEFT_HAND); - controller::Pose rightHand = userInputMapper->getPoseState(controller::Action::RIGHT_HAND); - Hand* hand = DependencyManager::get()->getMyAvatar()->getHand(); - setPalmData(hand, leftHand, deltaTime, HandData::LeftHand, userInputMapper->getActionState(controller::Action::LEFT_HAND_CLICK)); - setPalmData(hand, rightHand, deltaTime, HandData::RightHand, userInputMapper->getActionState(controller::Action::RIGHT_HAND_CLICK)); + controller::Pose leftHandPose = userInputMapper->getPoseState(controller::Action::LEFT_HAND); + controller::Pose rightHandPose = userInputMapper->getPoseState(controller::Action::RIGHT_HAND); + myAvatar->setHandControllerPoses(leftHandPose, rightHandPose); + updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... updateDialogs(deltaTime); // update various stats dialogs if present @@ -4979,49 +4978,6 @@ mat4 Application::getHMDSensorPose() const { return mat4(); } -void Application::setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, HandData::Hand whichHand, float triggerValue) { - - // NOTE: the Hand::modifyPalm() will allow the lambda to modify the palm data while ensuring some other user isn't - // reading or writing to the Palms. This is definitely not the best way of handling this, and I'd like to see more - // of this palm manipulation in the Hand class itself. But unfortunately the Hand and Palm don't knbow about - // controller::Pose. More work is needed to clean this up. - hand->modifyPalm(whichHand, [&](PalmData& palm) { - palm.setActive(pose.isValid()); - - // controller pose is in Avatar frame. - glm::vec3 position = pose.getTranslation(); - glm::quat rotation = pose.getRotation(); - glm::vec3 rawVelocity = pose.getVelocity(); - glm::vec3 angularVelocity = pose.getAngularVelocity(); - - palm.setRawVelocity(rawVelocity); - palm.setRawAngularVelocity(angularVelocity); - - if (controller::InputDevice::getLowVelocityFilter()) { - // Use a velocity sensitive filter to damp small motions and preserve large ones with - // no latency. - float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); - position = palm.getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); - rotation = safeMix(palm.getRawRotation(), rotation, 1.0f - velocityFilter); - } - palm.setRawPosition(position); - palm.setRawRotation(rotation); - - // Store the one fingertip in the palm structure so we can track velocity - const float FINGER_LENGTH = 0.3f; // meters - const glm::vec3 FINGER_VECTOR(0.0f, FINGER_LENGTH, 0.0f); - const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; - glm::vec3 oldTipPosition = palm.getTipRawPosition(); - if (deltaTime > 0.0f) { - palm.setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); - } else { - palm.setTipVelocity(glm::vec3(0.0f)); - } - palm.setTipPosition(newTipPosition); - palm.setTrigger(triggerValue); // FIXME - we want to get rid of this idea of PalmData having a trigger - }); -} - void Application::crashApplication() { qCDebug(interfaceapp) << "Intentionally crashed Interface"; QObject* object = nullptr; diff --git a/interface/src/Application.h b/interface/src/Application.h index c93b7431f3..14b90877df 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -299,7 +299,7 @@ private slots: void loadSettings(); void saveSettings(); - + bool acceptSnapshot(const QString& urlString); bool askToSetAvatarUrl(const QString& url); bool askToLoadScript(const QString& scriptFilenameOrURL); @@ -327,8 +327,6 @@ private: void update(float deltaTime); - void setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, HandData::Hand whichHand, float triggerValue); - // Various helper functions called during update() void updateLOD(); void updateThreads(float deltaTime); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 15fae25646..ab1b7238df 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -479,7 +479,8 @@ Menu::Menu() { // Developer > Hands >>> MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands"); - addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false); + addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false, + avatar, SLOT(setEnableDebugDrawHandControllers(bool))); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true, qApp, SLOT(setLowVelocityFilter(bool))); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 292e4c637e..ca242a2ca2 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -35,7 +35,6 @@ #include "Avatar.h" #include "AvatarManager.h" #include "AvatarMotionState.h" -#include "Hand.h" #include "Head.h" #include "Menu.h" #include "Physics.h" @@ -101,7 +100,6 @@ Avatar::Avatar(RigPointer rig) : // give the pointer to our head to inherited _headData variable from AvatarData _headData = static_cast(new Head(this)); - _handData = static_cast(new Hand(this)); } Avatar::~Avatar() { @@ -190,11 +188,6 @@ void Avatar::simulate(float deltaTime) { float boundingRadius = getBoundingRadius(); bool inView = qApp->getViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius); - { - PerformanceTimer perfTimer("hand"); - getHand()->simulate(deltaTime, false); - } - if (_shouldAnimate && !_shouldSkipRender && inView) { { PerformanceTimer perfTimer("skeleton"); @@ -578,11 +571,6 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, floa if (_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable()) { getHead()->render(renderArgs, 1.0f, renderFrustum); } - - if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE && - Menu::getInstance()->isOptionChecked(MenuOption::DisplayHandTargets)) { - getHand()->renderHandTargets(renderArgs, false); - } } getHead()->renderLookAts(renderArgs); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index f9e21febd5..7020de377f 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -22,7 +22,6 @@ #include -#include "Hand.h" #include "Head.h" #include "SkeletonModel.h" #include "world.h" @@ -91,7 +90,7 @@ public: float getUniformScale() const { return getScale().y; } const Head* getHead() const { return static_cast(_headData); } Head* getHead() { return static_cast(_headData); } - Hand* getHand() { return static_cast(_handData); } + glm::quat getWorldAlignedOrientation() const; AABox getBounds() const; diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index b62cae1d58..0ce0b5a190 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -104,48 +104,57 @@ std::shared_ptr AvatarActionHold::getTarget(float deltaTimeStep, glm::qu withReadLock([&]{ bool isRightHand = (_hand == "right"); + glm::vec3 palmPosition; glm::quat palmRotation; - PalmData palmData = holdingAvatar->getHand()->getCopyOfPalmData(isRightHand ? HandData::RightHand : HandData::LeftHand); - - if (palmData.isValid()) { - // TODO: adjust according to _relativePosition and _relativeRotation? - linearVelocity = palmData.getVelocity(); - angularVelocity = palmData.getAngularVelocity(); - } - - if (_ignoreIK && holdingAvatar->isMyAvatar() && palmData.isValid()) { - // We cannot ignore other avatars IK and this is not the point of this option - // This is meant to make the grabbing behavior more reactive. - palmPosition = palmData.getPosition(); - palmRotation = palmData.getRotation(); - } else if (holdingAvatar->isMyAvatar()) { - glm::vec3 avatarRigidBodyPosition; - glm::quat avatarRigidBodyRotation; - getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); - - // the offset and rotation between the avatar's rigid body and the palm were determined earlier - // in prepareForPhysicsSimulation. At this point, the avatar's rigid body has been moved by bullet - // and the data in the Avatar class is stale. This means that the result of get*PalmPosition will - // be stale. Instead, determine the current palm position with the current avatar's rigid body - // location and the saved offsets. - - // this line is more correct but breaks for the current way avatar data is updated. - // palmPosition = avatarRigidBodyPosition + avatarRigidBodyRotation * _palmOffsetFromRigidBody; - // instead, use this for now: - palmPosition = avatarRigidBodyPosition + _palmOffsetFromRigidBody; - - // the item jitters the least by getting the rotation based on the opinion of Avatar.h rather - // than that of the rigid body. leaving this next line here for future reference: - // palmRotation = avatarRigidBodyRotation * _palmRotationFromRigidBody; + if (holdingAvatar->isMyAvatar()) { + // fetch the hand controller pose + controller::Pose pose; if (isRightHand) { - palmRotation = holdingAvatar->getRightPalmRotation(); + pose = avatarManager->getMyAvatar()->getRightHandControllerPose(); } else { - palmRotation = holdingAvatar->getLeftPalmRotation(); + pose = avatarManager->getMyAvatar()->getLeftHandControllerPose(); } - } else { + + if (pose.isValid()) { + linearVelocity = pose.getVelocity(); + angularVelocity = pose.getAngularVelocity(); + } + + if (_ignoreIK && pose.isValid()) { + // We cannot ignore other avatars IK and this is not the point of this option + // This is meant to make the grabbing behavior more reactive. + palmPosition = pose.getTranslation(); + palmRotation = pose.getRotation(); + } else { + glm::vec3 avatarRigidBodyPosition; + glm::quat avatarRigidBodyRotation; + getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); + + // the offset and rotation between the avatar's rigid body and the palm were determined earlier + // in prepareForPhysicsSimulation. At this point, the avatar's rigid body has been moved by bullet + // and the data in the Avatar class is stale. This means that the result of get*PalmPosition will + // be stale. Instead, determine the current palm position with the current avatar's rigid body + // location and the saved offsets. + + // this line is more correct but breaks for the current way avatar data is updated. + // palmPosition = avatarRigidBodyPosition + avatarRigidBodyRotation * _palmOffsetFromRigidBody; + // instead, use this for now: + palmPosition = avatarRigidBodyPosition + _palmOffsetFromRigidBody; + + // the item jitters the least by getting the rotation based on the opinion of Avatar.h rather + // than that of the rigid body. leaving this next line here for future reference: + // palmRotation = avatarRigidBodyRotation * _palmRotationFromRigidBody; + + if (isRightHand) { + palmRotation = holdingAvatar->getRightPalmRotation(); + } else { + palmRotation = holdingAvatar->getLeftPalmRotation(); + } + } + } else { // regular avatar if (isRightHand) { palmPosition = holdingAvatar->getRightPalmPosition(); palmRotation = holdingAvatar->getRightPalmRotation(); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp deleted file mode 100644 index 5371fe5736..0000000000 --- a/interface/src/avatar/Hand.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// Hand.cpp -// interface/src/avatar -// -// Copyright 2013 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 "Hand.h" - -#include - -#include -#include - -#include "Avatar.h" -#include "AvatarManager.h" -#include "MyAvatar.h" -#include "Util.h" -#include "world.h" - -using namespace std; - -Hand::Hand(Avatar* owningAvatar) : - HandData((AvatarData*)owningAvatar), - _owningAvatar(owningAvatar) -{ -} - -void Hand::simulate(float deltaTime, bool isMine) { - // nothing to do here -} - -void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { - float avatarScale = 1.0f; - if (_owningAvatar) { - avatarScale = _owningAvatar->getUniformScale(); - } - - const float alpha = 1.0f; - const glm::vec3 redColor(1.0f, 0.0f, 0.0f); // Color the hand targets red to be different than skin - const glm::vec3 greenColor(0.0f, 1.0f, 0.0f); // Color the hand targets red to be different than skin - const glm::vec3 blueColor(0.0f, 0.0f, 1.0f); // Color the hand targets red to be different than skin - const glm::vec3 grayColor(0.5f); - const float SPHERE_RADIUS = 0.03f * avatarScale; - - auto palms = getCopyOfPalms(); - - gpu::Batch& batch = *renderArgs->_batch; - if (isMine) { - for (const auto& palm : palms) { - if (!palm.isActive()) { - continue; - } - // draw a gray sphere at the target position of the "Hand" joint - glm::vec3 position = palm.getPosition(); - Transform transform = Transform(); - transform.setTranslation(position); - transform.setRotation(palm.getRotation()); - transform.postScale(SPHERE_RADIUS); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphereInstance(batch, grayColor); - - // draw a green sphere at the old "finger tip" - transform = Transform(); - position = palm.getTipPosition(); - transform.setTranslation(position); - transform.setRotation(palm.getRotation()); - transform.postScale(SPHERE_RADIUS); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphereInstance(batch, greenColor); - } - } - - const float AXIS_RADIUS = 0.1f * SPHERE_RADIUS; - const float AXIS_LENGTH = 10.0f * SPHERE_RADIUS; - - // Draw the coordinate frames of the hand targets - for (const auto& palm : palms) { - if (palm.isActive()) { - glm::vec3 root = palm.getPosition(); - - const glm::vec3 yAxis(0.0f, 1.0f, 0.0f); - glm::quat palmRotation = palm.getRotation(); - Transform transform = Transform(); - transform.setTranslation(glm::vec3()); - batch.setModelTransform(transform); - glm::vec3 tip = root + palmRotation * glm::vec3(AXIS_LENGTH, 0.0f, 0.0f); - Avatar::renderJointConnectingCone(batch, root, tip, AXIS_RADIUS, AXIS_RADIUS, glm::vec4(redColor.r, redColor.g, redColor.b, alpha)); - - tip = root + palmRotation * glm::vec3(0.0f, AXIS_LENGTH, 0.0f); - Avatar::renderJointConnectingCone(batch, root, tip, AXIS_RADIUS, AXIS_RADIUS, glm::vec4(greenColor.r, greenColor.g, greenColor.b, alpha)); - - tip = root + palmRotation * glm::vec3(0.0f, 0.0f, AXIS_LENGTH); - Avatar::renderJointConnectingCone(batch, root, tip, AXIS_RADIUS, AXIS_RADIUS, glm::vec4(blueColor.r, blueColor.g, blueColor.b, alpha)); - } - } -} - diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h deleted file mode 100644 index 2ece3e9f9e..0000000000 --- a/interface/src/avatar/Hand.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Hand.h -// interface/src/avatar -// -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Hand_h -#define hifi_Hand_h - -#include - -class Avatar; -class RenderArgs; - -class Hand : public HandData { -public: - Hand(Avatar* owningAvatar); - - void simulate(float deltaTime, bool isMine); - void renderHandTargets(RenderArgs* renderArgs, bool isMine); - -private: - // disallow copies of the Hand, copy of owning Avatar is disallowed too - Hand(const Hand&); - Hand& operator= (const Hand&); - - int _controllerButtons; /// Button states read from hand-held controllers - - Avatar* _owningAvatar; -}; - -#endif // hifi_Hand_h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 26e0ce56dd..016e2a464c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -341,12 +341,6 @@ void MyAvatar::simulate(float deltaTime) { updatePosition(deltaTime); } - { - PerformanceTimer perfTimer("hand"); - // update avatar skeleton and simulate hand and head - getHand()->simulate(deltaTime, true); - } - { PerformanceTimer perfTimer("skeleton"); _skeletonModel.simulate(deltaTime); @@ -520,47 +514,49 @@ void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 MyAvatar::getLeftHandPosition() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); - return palmData.isValid() ? palmData.getPosition() : glm::vec3(0.0f); + auto pose = getLeftHandControllerPose(); + return pose.isValid() ? pose.getTranslation() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandPosition() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); - return palmData.isValid() ? palmData.getPosition() : glm::vec3(0.0f); + auto pose = getRightHandControllerPose(); + return pose.isValid() ? pose.getTranslation() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getLeftHandTipPosition() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); - return palmData.isValid() ? palmData.getTipPosition() : glm::vec3(0.0f); + const float TIP_LENGTH = 0.3f; + auto pose = getLeftHandControllerPose(); + return pose.isValid() ? pose.getTranslation() * pose.getRotation() + glm::vec3(0.0f, TIP_LENGTH, 0.0f) : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandTipPosition() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); - return palmData.isValid() ? palmData.getTipPosition() : glm::vec3(0.0f); + const float TIP_LENGTH = 0.3f; + auto pose = getRightHandControllerPose(); + return pose.isValid() ? pose.getTranslation() * pose.getRotation() + glm::vec3(0.0f, TIP_LENGTH, 0.0f) : glm::vec3(0.0f); } controller::Pose MyAvatar::getLeftHandPose() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); - return palmData.isValid() ? controller::Pose(palmData.getPosition(), palmData.getRotation(), - palmData.getVelocity(), palmData.getRawAngularVelocity()) : controller::Pose(); + return getLeftHandControllerPose(); } controller::Pose MyAvatar::getRightHandPose() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); - return palmData.isValid() ? controller::Pose(palmData.getPosition(), palmData.getRotation(), - palmData.getVelocity(), palmData.getRawAngularVelocity()) : controller::Pose(); + return getRightHandControllerPose(); } controller::Pose MyAvatar::getLeftHandTipPose() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); - return palmData.isValid() ? controller::Pose(palmData.getTipPosition(), palmData.getRotation(), - palmData.getTipVelocity(), palmData.getRawAngularVelocity()) : controller::Pose(); + auto pose = getLeftHandControllerPose(); + glm::vec3 tipTrans = getLeftHandTipPosition(); + pose.velocity += glm::cross(pose.getAngularVelocity(), pose.getTranslation() - tipTrans); + pose.translation = tipTrans; + return pose; } controller::Pose MyAvatar::getRightHandTipPose() const { - auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); - return palmData.isValid() ? controller::Pose(palmData.getTipPosition(), palmData.getRotation(), - palmData.getTipVelocity(), palmData.getRawAngularVelocity()) : controller::Pose(); + auto pose = getRightHandControllerPose(); + glm::vec3 tipTrans = getRightHandTipPosition(); + pose.velocity += glm::cross(pose.getAngularVelocity(), pose.getTranslation() - tipTrans); + pose.translation = tipTrans; + return pose; } // virtual @@ -698,6 +694,14 @@ void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) { } } +void MyAvatar::setEnableDebugDrawHandControllers(bool isEnabled) { + _enableDebugDrawHandControllers = isEnabled; + if (!isEnabled) { + DebugDraw::getInstance().removeMyAvatarMarker("leftHandController"); + DebugDraw::getInstance().removeMyAvatarMarker("rightHandController"); + } +} + void MyAvatar::setEnableMeshVisible(bool isEnabled) { render::ScenePointer scene = qApp->getMain3DScene(); _skeletonModel.setVisibleInScene(isEnabled, scene); @@ -1080,6 +1084,38 @@ void MyAvatar::rebuildCollisionShape() { _characterController.setLocalBoundingBox(corner, diagonal); } +static controller::Pose applyLowVelocityFilter(const controller::Pose& oldPose, const controller::Pose& newPose) { + controller::Pose finalPose = newPose; + if (newPose.isValid()) { + // Use a velocity sensitive filter to damp small motions and preserve large ones with + // no latency. + float velocityFilter = glm::clamp(1.0f - glm::length(oldPose.getVelocity()), 0.0f, 1.0f); + finalPose.translation = oldPose.getTranslation() * velocityFilter + newPose.getTranslation() * (1.0f - velocityFilter); + finalPose.rotation = safeMix(oldPose.getRotation(), newPose.getRotation(), 1.0f - velocityFilter); + } + return finalPose; +} + +void MyAvatar::setHandControllerPoses(const controller::Pose& left, const controller::Pose& right) { + if (controller::InputDevice::getLowVelocityFilter()) { + auto oldLeftPose = getLeftHandControllerPose(); + auto oldRightPose = getRightHandControllerPose(); + _leftHandControllerPoseCache.set(applyLowVelocityFilter(oldLeftPose, left)); + _rightHandControllerPoseCache.set(applyLowVelocityFilter(oldRightPose, right)); + } else { + _leftHandControllerPoseCache.set(left); + _rightHandControllerPoseCache.set(right); + } +} + +controller::Pose MyAvatar::getLeftHandControllerPose() const { + return _leftHandControllerPoseCache.get(); +} + +controller::Pose MyAvatar::getRightHandControllerPose() const { + return _rightHandControllerPoseCache.get(); +} + void MyAvatar::prepareForPhysicsSimulation() { relayDriveKeysToCharacterController(); @@ -1215,11 +1251,6 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl } else { getHead()->renderLookAts(renderArgs); } - - if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE && - Menu::getInstance()->isOptionChecked(MenuOption::DisplayHandTargets)) { - getHand()->renderHandTargets(renderArgs, true); - } } void MyAvatar::setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visible) { @@ -1328,6 +1359,23 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { } } + if (_enableDebugDrawHandControllers) { + auto leftHandPose = getLeftHandControllerPose(); + auto rightHandPose = getRightHandControllerPose(); + + if (leftHandPose.isValid()) { + DebugDraw::getInstance().addMyAvatarMarker("leftHandController", leftHandPose.getRotation(), leftHandPose.getTranslation(), glm::vec4(1)); + } else { + DebugDraw::getInstance().removeMyAvatarMarker("leftHandController"); + } + + if (rightHandPose.isValid()) { + DebugDraw::getInstance().addMyAvatarMarker("rightHandController", rightHandPose.getRotation(), rightHandPose.getTranslation(), glm::vec4(1)); + } else { + DebugDraw::getInstance().removeMyAvatarMarker("rightHandController"); + } + } + DebugDraw::getInstance().updateMyAvatarPos(getPosition()); DebugDraw::getInstance().updateMyAvatarRot(getOrientation()); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fd5c2920a9..0092280762 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -249,6 +249,10 @@ public: virtual void rebuildCollisionShape() override; + void setHandControllerPoses(const controller::Pose& left, const controller::Pose& right); + controller::Pose MyAvatar::getLeftHandControllerPose() const; + controller::Pose MyAvatar::getRightHandControllerPose() const; + public slots: void increaseSize(); void decreaseSize(); @@ -271,6 +275,7 @@ public slots: void setEnableDebugDrawDefaultPose(bool isEnabled); void setEnableDebugDrawAnimPose(bool isEnabled); void setEnableDebugDrawPosition(bool isEnabled); + void setEnableDebugDrawHandControllers(bool isEnabled); bool getEnableMeshVisible() const { return _skeletonModel.isVisible(); } void setEnableMeshVisible(bool isEnabled); void setUseAnimPreAndPostRotations(bool isEnabled); @@ -434,6 +439,7 @@ private: bool _enableDebugDrawDefaultPose { false }; bool _enableDebugDrawAnimPose { false }; + bool _enableDebugDrawHandControllers { false }; AudioListenerMode _audioListenerMode; glm::vec3 _customListenPosition; @@ -444,6 +450,9 @@ private: bool _hoverReferenceCameraFacingIsCaptured { false }; glm::vec3 _hoverReferenceCameraFacing { 0.0f, 0.0f, -1.0f }; // hmd sensor space + ThreadSafeValueCache _leftHandControllerPoseCache { controller::Pose() }; + ThreadSafeValueCache _rightHandControllerPoseCache { controller::Pose() }; + float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f }; float AUDIO_ENERGY_CONSTANT { 0.000001f }; float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f }; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 711ed17231..d659d79dd9 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -16,7 +16,6 @@ #include "Application.h" #include "Avatar.h" -#include "Hand.h" #include "Menu.h" #include "SkeletonModel.h" #include "Util.h" @@ -127,20 +126,20 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::HandParameters handParams; - auto leftPalm = myAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand); - if (leftPalm.isValid() && leftPalm.isActive()) { + auto leftPose = myAvatar->getLeftHandControllerPose(); + if (leftPose.isValid()) { handParams.isLeftEnabled = true; - handParams.leftPosition = Quaternions::Y_180 * leftPalm.getRawPosition(); - handParams.leftOrientation = Quaternions::Y_180 * leftPalm.getRawRotation(); + handParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation(); + handParams.leftOrientation = Quaternions::Y_180 * leftPose.getRotation(); } else { handParams.isLeftEnabled = false; } - auto rightPalm = myAvatar->getHand()->getCopyOfPalmData(HandData::RightHand); - if (rightPalm.isValid() && rightPalm.isActive()) { + auto rightPose = myAvatar->getRightHandControllerPose(); + if (rightPose.isValid()) { handParams.isRightEnabled = true; - handParams.rightPosition = Quaternions::Y_180 * rightPalm.getRawPosition(); - handParams.rightOrientation = Quaternions::Y_180 * rightPalm.getRawRotation(); + handParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation(); + handParams.rightOrientation = Quaternions::Y_180 * rightPose.getRotation(); } else { handParams.isRightEnabled = false; } @@ -247,17 +246,6 @@ bool operator<(const IndexValue& firstIndex, const IndexValue& secondIndex) { return firstIndex.value < secondIndex.value; } -void SkeletonModel::applyPalmData(int jointIndex, const PalmData& palm) { - if (jointIndex == -1 || jointIndex >= _rig->getJointStateCount()) { - return; - } - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - int parentJointIndex = geometry.joints.at(jointIndex).parentIndex; - if (parentJointIndex == -1) { - return; - } -} - bool SkeletonModel::getLeftGrabPosition(glm::vec3& position) const { int knuckleIndex = _rig->indexOfJoint("LeftHandMiddle1"); int handIndex = _rig->indexOfJoint("LeftHand"); diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index b57d54020d..6c6a7472f7 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -111,7 +111,6 @@ protected: void computeBoundingShape(); - void applyPalmData(int jointIndex, const PalmData& palm); private: bool getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 9ca1e2c6c6..f6e5b6364f 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d14df7b05a..067ab0603b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -57,7 +57,6 @@ AvatarData::AvatarData() : _hasNewJointRotations(true), _hasNewJointTranslations(true), _headData(NULL), - _handData(NULL), _faceModelURL("http://invalid.com"), _displayNameTargetAlpha(1.0f), _displayNameAlpha(1.0f), @@ -74,7 +73,6 @@ AvatarData::AvatarData() : AvatarData::~AvatarData() { delete _headData; - delete _handData; } // We cannot have a file-level variable (const or otherwise) in the header if it uses PathUtils, because that references Application, which will not yet initialized. @@ -418,11 +416,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { _headData = new HeadData(this); } - // lazily allocate memory for HandData in case we're not an Avatar instance - if (!_handData) { - _handData = new HandData(this); - } - const unsigned char* startPosition = reinterpret_cast(buffer.data()); const unsigned char* sourceBuffer = startPosition; quint64 now = usecTimestampNow(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index cf6cf80162..6ffcaed0da 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -52,9 +52,9 @@ typedef unsigned long long quint64; #include #include #include +#include #include "AABox.h" -#include "HandData.h" #include "HeadData.h" #include "PathUtils.h" @@ -290,7 +290,6 @@ public: KeyState keyState() const { return _keyState; } const HeadData* getHeadData() const { return _headData; } - const HandData* getHandData() const { return _handData; } bool hasIdentityChangedAfterParsing(const QByteArray& data); QByteArray identityByteArray(); @@ -383,7 +382,6 @@ protected: bool _hasNewJointTranslations; // set in AvatarData, cleared in Avatar HeadData* _headData; - HandData* _handData; QUrl _faceModelURL; // These need to be empty so that on first time setting them they will not short circuit QUrl _skeletonModelURL; // These need to be empty so that on first time setting them they will not short circuit diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp deleted file mode 100644 index 7ba23b01ad..0000000000 --- a/libraries/avatars/src/HandData.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// -// HandData.cpp -// libraries/avatars/src -// -// Created by Stephen Birarda on 5/20/13. -// Copyright 2013 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 "AvatarData.h" -#include "HandData.h" - - -HandData::HandData(AvatarData* owningAvatar) : - _owningAvatarData(owningAvatar) -{ - addNewPalm(LeftHand); - addNewPalm(RightHand); -} - -glm::vec3 HandData::worldToLocalVector(const glm::vec3& worldVector) const { - return glm::inverse(getBaseOrientation()) * worldVector / getBaseScale(); -} - -PalmData& HandData::addNewPalm(Hand whichHand) { - QWriteLocker locker(&_palmsLock); - _palms.push_back(PalmData(this, whichHand)); - return _palms.back(); -} - -PalmData HandData::getCopyOfPalmData(Hand hand) const { - QReadLocker locker(&_palmsLock); - - // the palms are not necessarily added in left-right order, - // so we have to search for the correct hand - for (const auto& palm : _palms) { - if (palm.whichHand() == hand && palm.isActive()) { - return palm; - } - } - return PalmData(); // invalid hand -} - -PalmData::PalmData(HandData* owningHandData, HandData::Hand hand) : -_rawRotation(0.0f, 0.0f, 0.0f, 1.0f), -_rawPosition(0.0f), -_rawVelocity(0.0f), -_rawAngularVelocity(0.0f), -_totalPenetration(0.0f), -_isActive(false), -_numFramesWithoutData(0), -_owningHandData(owningHandData), -_hand(hand) { -} - -void PalmData::addToPosition(const glm::vec3& delta) { - _rawPosition += _owningHandData->worldToLocalVector(delta); -} - -bool HandData::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, - const PalmData*& collidingPalm) const { - QReadLocker locker(&_palmsLock); - - for (const auto& palm : _palms) { - if (!palm.isActive()) { - continue; - } - glm::vec3 palmPosition = palm.getPosition(); - const float PALM_RADIUS = 0.05f; // in world (not voxel) coordinates - if (findSphereSpherePenetration(penetratorCenter, penetratorRadius, palmPosition, PALM_RADIUS, penetration)) { - collidingPalm = &palm; - return true; - } - } - return false; -} - -glm::quat HandData::getBaseOrientation() const { - return _owningAvatarData->getOrientation(); -} - -glm::vec3 HandData::getBasePosition() const { - return _owningAvatarData->getPosition(); -} - -float HandData::getBaseScale() const { - return _owningAvatarData->getTargetScale(); -} - -glm::vec3 PalmData::getFingerDirection() const { - // finger points along yAxis in hand-frame - const glm::vec3 LOCAL_FINGER_DIRECTION(0.0f, 1.0f, 0.0f); - return glm::normalize(_owningHandData->localToWorldDirection(_rawRotation * LOCAL_FINGER_DIRECTION)); -} - -glm::vec3 PalmData::getNormal() const { - // palm normal points along zAxis in hand-frame - const glm::vec3 LOCAL_PALM_DIRECTION(0.0f, 0.0f, 1.0f); - return glm::normalize(_owningHandData->localToWorldDirection(_rawRotation * LOCAL_PALM_DIRECTION)); -} - - - diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h deleted file mode 100644 index 63af43e399..0000000000 --- a/libraries/avatars/src/HandData.h +++ /dev/null @@ -1,174 +0,0 @@ -// -// HandData.h -// libraries/avatars/src -// -// Created by Eric Johnston on 6/26/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_HandData_h -#define hifi_HandData_h - -#include -#include -#include - -#include -#include - -#include - -#include -#include - -class AvatarData; -class PalmData; - -class HandData { -public: - enum Hand { - LeftHand, - RightHand, - UnknownHand, - NUMBER_OF_HANDS - }; - - HandData(AvatarData* owningAvatar); - virtual ~HandData() {} - - // position conversion - glm::vec3 localToWorldPosition(const glm::vec3& localPosition) { - return getBasePosition() + getBaseOrientation() * localPosition * getBaseScale(); - } - - glm::vec3 localToWorldDirection(const glm::vec3& localVector) { - return getBaseOrientation() * localVector * getBaseScale(); - } - - glm::vec3 worldToLocalVector(const glm::vec3& worldVector) const; - - PalmData getCopyOfPalmData(Hand hand) const; - - std::vector getCopyOfPalms() const { QReadLocker locker(&_palmsLock); return _palms; } - - /// Checks for penetration between the described sphere and the hand. - /// \param penetratorCenter the center of the penetration test sphere - /// \param penetratorRadius the radius of the penetration test sphere - /// \param penetration[out] the vector in which to store the penetration - /// \param collidingPalm[out] a const PalmData* to the palm that was collided with - /// \return whether or not the sphere penetrated - bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, - const PalmData*& collidingPalm) const; - - glm::quat getBaseOrientation() const; - - /// Allows a lamda function write access to the specific palm for this Hand, this might - /// modify the _palms vector - template void modifyPalm(Hand whichHand, PalmModifierFunction callback); - - friend class AvatarData; -protected: - AvatarData* _owningAvatarData; - std::vector _palms; - mutable QReadWriteLock _palmsLock{ QReadWriteLock::Recursive }; - - glm::vec3 getBasePosition() const; - float getBaseScale() const; - - PalmData& addNewPalm(Hand whichHand); - PalmData& getPalmData(Hand hand); - -private: - // privatize copy ctor and assignment operator so copies of this object cannot be made - HandData(const HandData&); - HandData& operator= (const HandData&); -}; - - -class PalmData { -public: - PalmData(HandData* owningHandData = nullptr, HandData::Hand hand = HandData::UnknownHand); - glm::vec3 getPosition() const { return _owningHandData->localToWorldPosition(_rawPosition); } - glm::vec3 getVelocity() const { return _owningHandData->localToWorldDirection(_rawVelocity); } - glm::vec3 getAngularVelocity() const { return _owningHandData->localToWorldDirection(_rawAngularVelocity); } - - const glm::vec3& getRawPosition() const { return _rawPosition; } - bool isActive() const { return _isActive; } - bool isValid() const { return _owningHandData; } - - void setActive(bool active) { _isActive = active; } - - HandData::Hand whichHand() const { return _hand; } - void setHand(HandData::Hand hand) { _hand = hand; } - - void setRawRotation(const glm::quat& rawRotation) { _rawRotation = rawRotation; }; - glm::quat getRawRotation() const { return _rawRotation; } - glm::quat getRotation() const { return _owningHandData->getBaseOrientation() * _rawRotation; } - void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } - void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } - const glm::vec3& getRawVelocity() const { return _rawVelocity; } - - void setRawAngularVelocity(const glm::vec3& angularVelocity) { _rawAngularVelocity = angularVelocity; } - const glm::vec3& getRawAngularVelocity() const { return _rawAngularVelocity; } - - void addToPosition(const glm::vec3& delta); - - void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; } - void resolvePenetrations() { addToPosition(-_totalPenetration); _totalPenetration = glm::vec3(0.0f); } - - void setTipPosition(const glm::vec3& position) { _tipPosition = position; } - const glm::vec3 getTipPosition() const { return _owningHandData->localToWorldPosition(_tipPosition); } - const glm::vec3& getTipRawPosition() const { return _tipPosition; } - - void setTipVelocity(const glm::vec3& velocity) { _tipVelocity = velocity; } - const glm::vec3 getTipVelocity() const { return _owningHandData->localToWorldDirection(_tipVelocity); } - const glm::vec3& getTipRawVelocity() const { return _tipVelocity; } - - void incrementFramesWithoutData() { _numFramesWithoutData++; } - void resetFramesWithoutData() { _numFramesWithoutData = 0; } - int getFramesWithoutData() const { return _numFramesWithoutData; } - - // FIXME - these are used in SkeletonModel::updateRig() the skeleton/rig should probably get this information - // from an action and/or the UserInputMapper instead of piping it through here. - void setTrigger(float trigger) { _trigger = trigger; } - float getTrigger() const { return _trigger; } - - // return world-frame: - glm::vec3 getFingerDirection() const; - glm::vec3 getNormal() const; - -private: - // unless marked otherwise, these are all in the model-frame - glm::quat _rawRotation; - glm::vec3 _rawPosition; - glm::vec3 _rawVelocity; - glm::vec3 _rawAngularVelocity; - glm::quat _rawDeltaRotation; - glm::quat _lastRotation; - - glm::vec3 _tipPosition; - glm::vec3 _tipVelocity; - glm::vec3 _totalPenetration; /// accumulator for per-frame penetrations - - float _trigger; - - bool _isActive; /// This has current valid data - int _numFramesWithoutData; /// after too many frames without data, this tracked object assumed lost. - HandData* _owningHandData; - HandData::Hand _hand; -}; - -template void HandData::modifyPalm(Hand whichHand, PalmModifierFunction callback) { - QReadLocker locker(&_palmsLock); - for (auto& palm : _palms) { - if (palm.whichHand() == whichHand && palm.isValid()) { - callback(palm); - return; - } - } -} - -#endif // hifi_HandData_h From ab19d3e5a2a4ec261377c42a53efa768a803b386 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Mar 2016 20:44:35 -0800 Subject: [PATCH 2/4] Moved animation after physics, hand poses are in world frame. There are still some debug hacks enabled so I can test in the vive room. --- interface/src/Application.cpp | 7 +- interface/src/avatar/AvatarActionHold.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 68 ++++++++++++-------- interface/src/avatar/MyAvatar.h | 13 ++-- interface/src/avatar/SkeletonModel.cpp | 4 +- libraries/render-utils/src/AnimDebugDraw.cpp | 7 +- plugins/hifiSixense/src/SixenseManager.cpp | 6 ++ 7 files changed, 68 insertions(+), 41 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 728691a0e1..42430b3a4c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3218,13 +3218,12 @@ void Application::update(float deltaTime) { controller::Pose leftHandPose = userInputMapper->getPoseState(controller::Action::LEFT_HAND); controller::Pose rightHandPose = userInputMapper->getPoseState(controller::Action::RIGHT_HAND); - myAvatar->setHandControllerPoses(leftHandPose, rightHandPose); + auto myAvatarMatrix = createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()); + myAvatar->setHandControllerPosesInWorldFrame(leftHandPose.transform(myAvatarMatrix), rightHandPose.transform(myAvatarMatrix)); updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... updateDialogs(deltaTime); // update various stats dialogs if present - _avatarUpdate->synchronousProcess(); - if (_physicsEnabled) { PerformanceTimer perfTimer("physics"); AvatarManager* avatarManager = DependencyManager::get().data(); @@ -3296,6 +3295,8 @@ void Application::update(float deltaTime) { } } + _avatarUpdate->synchronousProcess(); + { PerformanceTimer perfTimer("overlays"); _overlays.update(deltaTime); diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 0ce0b5a190..5087f7955d 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -113,9 +113,9 @@ std::shared_ptr AvatarActionHold::getTarget(float deltaTimeStep, glm::qu // fetch the hand controller pose controller::Pose pose; if (isRightHand) { - pose = avatarManager->getMyAvatar()->getRightHandControllerPose(); + pose = avatarManager->getMyAvatar()->getRightHandControllerPoseInWorldFrame(); } else { - pose = avatarManager->getMyAvatar()->getLeftHandControllerPose(); + pose = avatarManager->getMyAvatar()->getLeftHandControllerPoseInWorldFrame(); } if (pose.isValid()) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 016e2a464c..c018a76168 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -512,39 +512,38 @@ void MyAvatar::updateFromTrackers(float deltaTime) { -MAX_LEAN, MAX_LEAN)); } - glm::vec3 MyAvatar::getLeftHandPosition() const { - auto pose = getLeftHandControllerPose(); + auto pose = getLeftHandControllerPoseInAvatarFrame(); return pose.isValid() ? pose.getTranslation() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandPosition() const { - auto pose = getRightHandControllerPose(); + auto pose = getRightHandControllerPoseInAvatarFrame(); return pose.isValid() ? pose.getTranslation() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getLeftHandTipPosition() const { const float TIP_LENGTH = 0.3f; - auto pose = getLeftHandControllerPose(); + auto pose = getLeftHandControllerPoseInAvatarFrame(); return pose.isValid() ? pose.getTranslation() * pose.getRotation() + glm::vec3(0.0f, TIP_LENGTH, 0.0f) : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandTipPosition() const { const float TIP_LENGTH = 0.3f; - auto pose = getRightHandControllerPose(); + auto pose = getRightHandControllerPoseInAvatarFrame(); return pose.isValid() ? pose.getTranslation() * pose.getRotation() + glm::vec3(0.0f, TIP_LENGTH, 0.0f) : glm::vec3(0.0f); } controller::Pose MyAvatar::getLeftHandPose() const { - return getLeftHandControllerPose(); + return getLeftHandControllerPoseInAvatarFrame(); } controller::Pose MyAvatar::getRightHandPose() const { - return getRightHandControllerPose(); + return getRightHandControllerPoseInAvatarFrame(); } controller::Pose MyAvatar::getLeftHandTipPose() const { - auto pose = getLeftHandControllerPose(); + auto pose = getLeftHandControllerPoseInAvatarFrame(); glm::vec3 tipTrans = getLeftHandTipPosition(); pose.velocity += glm::cross(pose.getAngularVelocity(), pose.getTranslation() - tipTrans); pose.translation = tipTrans; @@ -552,7 +551,7 @@ controller::Pose MyAvatar::getLeftHandTipPose() const { } controller::Pose MyAvatar::getRightHandTipPose() const { - auto pose = getRightHandControllerPose(); + auto pose = getRightHandControllerPoseInAvatarFrame(); glm::vec3 tipTrans = getRightHandTipPosition(); pose.velocity += glm::cross(pose.getAngularVelocity(), pose.getTranslation() - tipTrans); pose.translation = tipTrans; @@ -697,8 +696,8 @@ void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) { void MyAvatar::setEnableDebugDrawHandControllers(bool isEnabled) { _enableDebugDrawHandControllers = isEnabled; if (!isEnabled) { - DebugDraw::getInstance().removeMyAvatarMarker("leftHandController"); - DebugDraw::getInstance().removeMyAvatarMarker("rightHandController"); + DebugDraw::getInstance().removeMarker("leftHandController"); + DebugDraw::getInstance().removeMarker("rightHandController"); } } @@ -1096,24 +1095,34 @@ static controller::Pose applyLowVelocityFilter(const controller::Pose& oldPose, return finalPose; } -void MyAvatar::setHandControllerPoses(const controller::Pose& left, const controller::Pose& right) { +void MyAvatar::setHandControllerPosesInWorldFrame(const controller::Pose& left, const controller::Pose& right) { if (controller::InputDevice::getLowVelocityFilter()) { - auto oldLeftPose = getLeftHandControllerPose(); - auto oldRightPose = getRightHandControllerPose(); - _leftHandControllerPoseCache.set(applyLowVelocityFilter(oldLeftPose, left)); - _rightHandControllerPoseCache.set(applyLowVelocityFilter(oldRightPose, right)); + auto oldLeftPose = getLeftHandControllerPoseInWorldFrame(); + auto oldRightPose = getRightHandControllerPoseInWorldFrame(); + _leftHandControllerPoseInWorldFrameCache.set(applyLowVelocityFilter(oldLeftPose, left)); + _rightHandControllerPoseInWorldFrameCache.set(applyLowVelocityFilter(oldRightPose, right)); } else { - _leftHandControllerPoseCache.set(left); - _rightHandControllerPoseCache.set(right); + _leftHandControllerPoseInWorldFrameCache.set(left); + _rightHandControllerPoseInWorldFrameCache.set(right); } } -controller::Pose MyAvatar::getLeftHandControllerPose() const { - return _leftHandControllerPoseCache.get(); +controller::Pose MyAvatar::getLeftHandControllerPoseInWorldFrame() const { + return _leftHandControllerPoseInWorldFrameCache.get(); } -controller::Pose MyAvatar::getRightHandControllerPose() const { - return _rightHandControllerPoseCache.get(); +controller::Pose MyAvatar::getRightHandControllerPoseInWorldFrame() const { + return _rightHandControllerPoseInWorldFrameCache.get(); +} + +controller::Pose MyAvatar::getLeftHandControllerPoseInAvatarFrame() const { + glm::mat4 invAvatarMatrix = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); + return getLeftHandControllerPoseInWorldFrame().transform(invAvatarMatrix); +} + +controller::Pose MyAvatar::getRightHandControllerPoseInAvatarFrame() const { + glm::mat4 invAvatarMatrix = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); + return getRightHandControllerPoseInWorldFrame().transform(invAvatarMatrix); } void MyAvatar::prepareForPhysicsSimulation() { @@ -1360,20 +1369,23 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { } if (_enableDebugDrawHandControllers) { - auto leftHandPose = getLeftHandControllerPose(); - auto rightHandPose = getRightHandControllerPose(); + auto leftHandPose = getLeftHandControllerPoseInWorldFrame(); + auto rightHandPose = getRightHandControllerPoseInWorldFrame(); if (leftHandPose.isValid()) { - DebugDraw::getInstance().addMyAvatarMarker("leftHandController", leftHandPose.getRotation(), leftHandPose.getTranslation(), glm::vec4(1)); + DebugDraw::getInstance().addMarker("leftHandController", leftHandPose.getRotation(), leftHandPose.getTranslation(), glm::vec4(1)); } else { - DebugDraw::getInstance().removeMyAvatarMarker("leftHandController"); + DebugDraw::getInstance().removeMarker("leftHandController"); } if (rightHandPose.isValid()) { - DebugDraw::getInstance().addMyAvatarMarker("rightHandController", rightHandPose.getRotation(), rightHandPose.getTranslation(), glm::vec4(1)); + DebugDraw::getInstance().addMarker("rightHandController", rightHandPose.getRotation(), rightHandPose.getTranslation(), glm::vec4(1)); } else { - DebugDraw::getInstance().removeMyAvatarMarker("rightHandController"); + DebugDraw::getInstance().removeMarker("rightHandController"); } + + // AJT: REMOVE + DebugDraw::getInstance().addMyAvatarMarker("REFERENCE", glm::quat(), glm::vec3(0.0f, 0.7f, -0.5f), glm::vec4(1)); } DebugDraw::getInstance().updateMyAvatarPos(getPosition()); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0092280762..2301e37a5b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -249,9 +249,11 @@ public: virtual void rebuildCollisionShape() override; - void setHandControllerPoses(const controller::Pose& left, const controller::Pose& right); - controller::Pose MyAvatar::getLeftHandControllerPose() const; - controller::Pose MyAvatar::getRightHandControllerPose() const; + void setHandControllerPosesInWorldFrame(const controller::Pose& left, const controller::Pose& right); + controller::Pose getLeftHandControllerPoseInWorldFrame() const; + controller::Pose getRightHandControllerPoseInWorldFrame() const; + controller::Pose getLeftHandControllerPoseInAvatarFrame() const; + controller::Pose getRightHandControllerPoseInAvatarFrame() const; public slots: void increaseSize(); @@ -450,8 +452,9 @@ private: bool _hoverReferenceCameraFacingIsCaptured { false }; glm::vec3 _hoverReferenceCameraFacing { 0.0f, 0.0f, -1.0f }; // hmd sensor space - ThreadSafeValueCache _leftHandControllerPoseCache { controller::Pose() }; - ThreadSafeValueCache _rightHandControllerPoseCache { controller::Pose() }; + // These are stored in WORLD frame + ThreadSafeValueCache _leftHandControllerPoseInWorldFrameCache { controller::Pose() }; + ThreadSafeValueCache _rightHandControllerPoseInWorldFrameCache { controller::Pose() }; float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f }; float AUDIO_ENERGY_CONSTANT { 0.000001f }; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index d659d79dd9..46a091cf35 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -126,7 +126,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::HandParameters handParams; - auto leftPose = myAvatar->getLeftHandControllerPose(); + auto leftPose = myAvatar->getLeftHandControllerPoseInAvatarFrame(); if (leftPose.isValid()) { handParams.isLeftEnabled = true; handParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation(); @@ -135,7 +135,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { handParams.isLeftEnabled = false; } - auto rightPose = myAvatar->getRightHandControllerPose(); + auto rightPose = myAvatar->getRightHandControllerPoseInAvatarFrame(); if (rightPose.isValid()) { handParams.isRightEnabled = true; handParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation(); diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index c9abf71fad..44bf533739 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -392,13 +392,18 @@ void AnimDebugDraw::update() { assert(numVerts == (v - verts)); + // This render item bound shit is broken. + // Fuck that, use the big ass bound instead. + /* render::Item::Bound theBound; for (int i = 0; i < numVerts; i++) { theBound += verts[i].pos; } + */ data._isVisible = (numVerts > 0); - data._bound = theBound; + + //data._bound = theBound; data._indexBuffer->resize(sizeof(uint16_t) * numVerts); uint16_t* indices = (uint16_t*)data._indexBuffer->editData(); for (int i = 0; i < numVerts; i++) { diff --git a/plugins/hifiSixense/src/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp index 9fdce3add4..67192edebd 100644 --- a/plugins/hifiSixense/src/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -481,6 +481,12 @@ void SixenseManager::InputDevice::handlePoseEvent(float deltaTime, const control // transform pose into avatar frame. auto nextPose = controller::Pose(pos, rot, velocity, angularVelocity).transform(controllerToAvatar); + if (!left) { + // AJT: HACK TO DEBUG IK + nextPose.translation = glm::vec3(0.25f, 0.7f, -0.5f); + nextPose.rotation = glm::quat(); + } + if (prevPose.isValid() && (deltaTime > std::numeric_limits::epsilon())) { nextPose.velocity = (nextPose.getTranslation() - prevPose.getTranslation()) / deltaTime; From 5eeb4ca594aae5de25b81f1e90987a059c9d7399 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Mar 2016 09:28:25 -0800 Subject: [PATCH 3/4] Fix one frame lag controller lag/jitter Move userInputMapper->update() after inputPlugin->pluginUpdate(). --- interface/src/Application.cpp | 3 ++- interface/src/avatar/MyAvatar.cpp | 3 --- libraries/shared/src/GLMHelpers.cpp | 8 ++++++++ libraries/shared/src/GLMHelpers.h | 2 ++ plugins/hifiSixense/src/SixenseManager.cpp | 6 ------ 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 42430b3a4c..2e4cb1db0f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3179,7 +3179,6 @@ void Application::update(float deltaTime) { auto myAvatar = getMyAvatar(); auto userInputMapper = DependencyManager::get(); - userInputMapper->update(deltaTime); controller::InputCalibrationData calibrationData = { myAvatar->getSensorToWorldMatrix(), @@ -3197,6 +3196,8 @@ void Application::update(float deltaTime) { } } + userInputMapper->update(deltaTime); + _controllerScriptingInterface->updateInputControllers(); // Transfer the user inputs to the driveKeys diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c018a76168..8be8b601a4 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1383,9 +1383,6 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { } else { DebugDraw::getInstance().removeMarker("rightHandController"); } - - // AJT: REMOVE - DebugDraw::getInstance().addMyAvatarMarker("REFERENCE", glm::quat(), glm::vec3(0.0f, 0.7f, -0.5f), glm::vec4(1)); } DebugDraw::getInstance().updateMyAvatarPos(getPosition()); diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index b2294f9ef3..d21d88d212 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -471,3 +471,11 @@ bool isNaN(glm::quat value) { return isNaN(value.w) || isNaN(value.x) || isNaN(value.y) || isNaN(value.z); } +glm::mat4 orthoInverse(const glm::mat4& m) { + glm::mat4 r = m; + r[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + r = glm::transpose(r); + r[3] = -(r * m[3]); + r[3][3] = 1.0f; + return r; +} diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 4a37d68240..469ca1fc81 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -232,4 +232,6 @@ glm::vec2 getFacingDir2D(const glm::mat4& m); bool isNaN(glm::vec3 value); bool isNaN(glm::quat value); +glm::mat4 orthoInverse(const glm::mat4& m); + #endif // hifi_GLMHelpers_h diff --git a/plugins/hifiSixense/src/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp index 67192edebd..9fdce3add4 100644 --- a/plugins/hifiSixense/src/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -481,12 +481,6 @@ void SixenseManager::InputDevice::handlePoseEvent(float deltaTime, const control // transform pose into avatar frame. auto nextPose = controller::Pose(pos, rot, velocity, angularVelocity).transform(controllerToAvatar); - if (!left) { - // AJT: HACK TO DEBUG IK - nextPose.translation = glm::vec3(0.25f, 0.7f, -0.5f); - nextPose.rotation = glm::quat(); - } - if (prevPose.isValid() && (deltaTime > std::numeric_limits::epsilon())) { nextPose.velocity = (nextPose.getTranslation() - prevPose.getTranslation()) / deltaTime; From 0ce004c8a7db7d555755544b1cd7ab824cbf990f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 11 Mar 2016 13:35:27 -0800 Subject: [PATCH 4/4] Removed passive-aggressive comment, (it was a late night) --- libraries/render-utils/src/AnimDebugDraw.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 44bf533739..a0f7d7eca1 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -392,18 +392,20 @@ void AnimDebugDraw::update() { assert(numVerts == (v - verts)); - // This render item bound shit is broken. - // Fuck that, use the big ass bound instead. + // The RenderItem culling is not working correctly + // Workaround this issue by using the default constructed + // item._bound which is a 16 km cube. /* render::Item::Bound theBound; for (int i = 0; i < numVerts; i++) { theBound += verts[i].pos; } + data._bound = theBound; */ data._isVisible = (numVerts > 0); - //data._bound = theBound; + data._indexBuffer->resize(sizeof(uint16_t) * numVerts); uint16_t* indices = (uint16_t*)data._indexBuffer->editData(); for (int i = 0; i < numVerts; i++) {