From 5a42991e0ccd075100c2da985f7d67925fd076c5 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Oct 2015 12:30:34 -0700 Subject: [PATCH 1/6] first pass at cleaning up MyAvatars use of PalmData --- interface/src/Application.cpp | 165 ++++++++++-------- interface/src/Application.h | 15 +- interface/src/avatar/Avatar.cpp | 32 ---- interface/src/avatar/Avatar.h | 6 +- interface/src/avatar/Hand.cpp | 18 +- interface/src/avatar/MyAvatar.cpp | 76 +++----- interface/src/avatar/MyAvatar.h | 4 +- interface/src/avatar/SkeletonModel.cpp | 46 +++-- interface/src/avatar/SkeletonModel.h | 2 +- .../ControllerScriptingInterface.cpp | 45 ----- .../scripting/ControllerScriptingInterface.h | 5 - interface/src/ui/ApplicationCompositor.cpp | 15 +- libraries/avatars/src/HandData.cpp | 33 ++-- libraries/avatars/src/HandData.h | 73 +++----- 14 files changed, 213 insertions(+), 322 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 92680ed3e0..910cbb19e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2741,13 +2741,13 @@ void Application::update(float deltaTime) { 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, LEFT_HAND_INDEX, userInputMapper->getActionState(controller::Action::LEFT_HAND_CLICK)); - setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX, userInputMapper->getActionState(controller::Action::RIGHT_HAND_CLICK)); + 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)); if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) { emulateMouse(hand, userInputMapper->getActionState(controller::Action::LEFT_HAND_CLICK), - userInputMapper->getActionState(controller::Action::SHIFT), LEFT_HAND_INDEX); + userInputMapper->getActionState(controller::Action::SHIFT), HandData::LeftHand); emulateMouse(hand, userInputMapper->getActionState(controller::Action::RIGHT_HAND_CLICK), - userInputMapper->getActionState(controller::Action::SHIFT), RIGHT_HAND_INDEX); + userInputMapper->getActionState(controller::Action::SHIFT), HandData::RightHand); } updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... @@ -4805,86 +4805,101 @@ mat4 Application::getHMDSensorPose() const { return mat4(); } -void Application::setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, int index, float triggerValue) { - PalmData* palm; - bool foundHand = false; - for (size_t j = 0; j < hand->getNumPalms(); j++) { - if (hand->getPalms()[j].getSixenseID() == index) { - palm = &(hand->getPalms()[j]); - foundHand = true; - break; +void Application::setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, HandData::Hand whichHand, float triggerValue) { + + // NOTE: the Hand::modifyPalms() 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->modifyPalms([&](std::vector& palms) { + auto myAvatar = DependencyManager::get()->getMyAvatar(); + PalmData* palm; + bool foundHand = false; + + // FIXME - this little chuck of code is a hot mess. It's basically searching the palms + // for the one that matches the "sixenseID" that is the "index" parameter. If it + // doesn't find it, then it creates a new palm and sets that palm's ID this really + // can and should be inside the HandData class + for (size_t j = 0; j < palms.size(); j++) { + if (palms[j].whichHand() == whichHand) { + palm = &(palms[j]); + foundHand = true; + break; + } + } + if (!foundHand) { + PalmData newPalm(hand); + palms.push_back(newPalm); + palm = &(palms[palms.size() - 1]); // FIXME - lame + palm->setHand(whichHand); } - } - if (!foundHand) { - PalmData newPalm(hand); - hand->getPalms().push_back(newPalm); - palm = &(hand->getPalms()[hand->getNumPalms() - 1]); - palm->setSixenseID(index); - } - palm->setActive(pose.isValid()); + palm->setActive(pose.isValid()); - // transform from sensor space, to world space, to avatar model space. - glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation()); - glm::mat4 sensorToWorldMat = getMyAvatar()->getSensorToWorldMatrix(); - glm::mat4 modelMat = createMatFromQuatAndPos(getMyAvatar()->getOrientation(), getMyAvatar()->getPosition()); - glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat; + // transform from sensor space, to world space, to avatar model space. + glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation()); + glm::mat4 sensorToWorldMat = myAvatar->getSensorToWorldMatrix(); + glm::mat4 modelMat = createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()); + glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat; - glm::vec3 position = extractTranslation(objectPose); - glm::quat rotation = glm::quat_cast(objectPose); + glm::vec3 position = extractTranslation(objectPose); + glm::quat rotation = glm::quat_cast(objectPose); - // Compute current velocity from position change - glm::vec3 rawVelocity; - if (deltaTime > 0.0f) { - rawVelocity = (position - palm->getRawPosition()) / deltaTime; - } else { - rawVelocity = glm::vec3(0.0f); - } - palm->setRawVelocity(rawVelocity); // meters/sec + // Compute current velocity from position change + glm::vec3 rawVelocity; + if (deltaTime > 0.0f) { + rawVelocity = (position - palm->getRawPosition()) / deltaTime; + } else { + rawVelocity = glm::vec3(0.0f); + } + palm->setRawVelocity(rawVelocity); // meters/sec - // Angular Velocity of Palm - glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); - glm::vec3 angularVelocity(0.0f); - float rotationAngle = glm::angle(deltaRotation); - if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { - angularVelocity = glm::normalize(glm::axis(deltaRotation)); - angularVelocity *= (rotationAngle / deltaTime); - palm->setRawAngularVelocity(angularVelocity); - } else { - palm->setRawAngularVelocity(glm::vec3(0.0f)); - } + // Angular Velocity of Palm + glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); + glm::vec3 angularVelocity(0.0f); + float rotationAngle = glm::angle(deltaRotation); + if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { + angularVelocity = glm::normalize(glm::axis(deltaRotation)); + angularVelocity *= (rotationAngle / deltaTime); + palm->setRawAngularVelocity(angularVelocity); + } else { + palm->setRawAngularVelocity(glm::vec3(0.0f)); + } - 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); + 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); + // 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); + }); } -void Application::emulateMouse(Hand* hand, float click, float shift, int index) { +void Application::emulateMouse(Hand* hand, float click, float shift, HandData::Hand whichHand) { + auto palms = hand->getCopyOfPalms(); + // Locate the palm, if it exists and is active PalmData* palm; bool foundHand = false; - for (size_t j = 0; j < hand->getNumPalms(); j++) { - if (hand->getPalms()[j].getSixenseID() == index) { - palm = &(hand->getPalms()[j]); + for (size_t j = 0; j < palms.size(); j++) { + if (palms[j].whichHand() == whichHand) { + palm = &(palms[j]); foundHand = true; break; } @@ -4896,12 +4911,14 @@ void Application::emulateMouse(Hand* hand, float click, float shift, int index) // Process the mouse events QPoint pos; - unsigned int deviceID = index == 0 ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT; + + // FIXME - this mouse emulation stuff needs to be reworked for new controller input plugins + unsigned int deviceID = whichHand == HandData::LeftHand ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT; + int index = (int)whichHand; // FIXME - hack attack if (isHMDMode()) { pos = getApplicationCompositor().getPalmClickLocation(palm); - } - else { + } else { // Get directon relative to avatar orientation glm::vec3 direction = glm::inverse(getMyAvatar()->getOrientation()) * palm->getFingerDirection(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 75cc418e94..301eb3b262 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -352,8 +352,8 @@ private: void update(float deltaTime); - void setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, int index, float triggerValue); - void emulateMouse(Hand* hand, float click, float shift, int index); + void setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, HandData::Hand whichHand, float triggerValue); + void emulateMouse(Hand* hand, float click, float shift, HandData::Hand whichHand); // Various helper functions called during update() void updateLOD(); @@ -522,10 +522,13 @@ private: ApplicationCompositor _compositor; OverlayConductor _overlayConductor; - int _oldHandMouseX[2]; - int _oldHandMouseY[2]; - bool _oldHandLeftClick[2]; - bool _oldHandRightClick[2]; + + // FIXME - Hand Controller to mouse emulation helpers. This is crufty and should be moved + // into the input plugins or something. + int _oldHandMouseX[(int)HandData::NUMBER_OF_HANDS]; + int _oldHandMouseY[(int)HandData::NUMBER_OF_HANDS]; + bool _oldHandLeftClick[(int)HandData::NUMBER_OF_HANDS]; + bool _oldHandRightClick[(int)HandData::NUMBER_OF_HANDS]; DialogsManagerScriptingInterface* _dialogsManagerScriptingInterface = new DialogsManagerScriptingInterface(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9f4e7ee3cf..8c29ce1a41 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1177,22 +1177,6 @@ glm::vec3 Avatar::getLeftPalmPosition() { return leftHandPosition; } -glm::vec3 Avatar::getLeftPalmVelocity() { - const PalmData* palm = getHand()->getPalm(LEFT_HAND_INDEX); - if (palm != NULL) { - return palm->getVelocity(); - } - return glm::vec3(0.0f); -} - -glm::vec3 Avatar::getLeftPalmAngularVelocity() { - const PalmData* palm = getHand()->getPalm(LEFT_HAND_INDEX); - if (palm != NULL) { - return palm->getRawAngularVelocity(); - } - return glm::vec3(0.0f); -} - glm::quat Avatar::getLeftPalmRotation() { glm::quat leftRotation; getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation); @@ -1208,22 +1192,6 @@ glm::vec3 Avatar::getRightPalmPosition() { return rightHandPosition; } -glm::vec3 Avatar::getRightPalmVelocity() { - const PalmData* palm = getHand()->getPalm(RIGHT_HAND_INDEX); - if (palm != NULL) { - return palm->getVelocity(); - } - return glm::vec3(0.0f); -} - -glm::vec3 Avatar::getRightPalmAngularVelocity() { - const PalmData* palm = getHand()->getPalm(RIGHT_HAND_INDEX); - if (palm != NULL) { - return palm->getRawAngularVelocity(); - } - return glm::vec3(0.0f); -} - glm::quat Avatar::getRightPalmRotation() { glm::quat rightRotation; getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 6a1f216089..44b5d91015 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -160,13 +160,11 @@ public: AvatarMotionState* getMotionState() { return _motionState; } public slots: + + // FIXME - these should be migrated to use Pose data instead glm::vec3 getLeftPalmPosition(); - glm::vec3 getLeftPalmVelocity(); - glm::vec3 getLeftPalmAngularVelocity(); glm::quat getLeftPalmRotation(); glm::vec3 getRightPalmPosition(); - glm::vec3 getRightPalmVelocity(); - glm::vec3 getRightPalmAngularVelocity(); glm::quat getRightPalmRotation(); protected: diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 0eeb7222b6..dfac5e393f 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -31,13 +31,7 @@ Hand::Hand(Avatar* owningAvatar) : } void Hand::simulate(float deltaTime, bool isMine) { - if (isMine) { - // Iterate hand controllers, take actions as needed - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; - palm.setLastControllerButtons(palm.getControllerButtons()); - } - } + // nothing to do here } void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { @@ -53,10 +47,12 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { const glm::vec3 grayColor(0.5f); const float SPHERE_RADIUS = 0.03f * avatarScale; + auto palms = getCopyOfPalms(); + gpu::Batch& batch = *renderArgs->_batch; if (isMine) { - for (size_t i = 0; i < getNumPalms(); i++) { - PalmData& palm = getPalms()[i]; + for (size_t i = 0; i < palms.size(); i++) { + PalmData& palm = palms[i]; if (!palm.isActive()) { continue; } @@ -82,8 +78,8 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { const float AXIS_LENGTH = 10.0f * SPHERE_RADIUS; // Draw the coordinate frames of the hand targets - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; + for (size_t i = 0; i < palms.size(); ++i) { + PalmData& palm = palms[i]; if (palm.isActive()) { glm::vec3 root = palm.getPosition(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6e08ca24cf..5483219318 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -554,74 +554,76 @@ void MyAvatar::updateFromTrackers(float deltaTime) { // first active controller. If you have both controllers held up or just the left, that // will be correct. But if you lift the right controller, then it will be reported // as "left"... you also see this in the avatars hands. -const PalmData* MyAvatar::getActivePalm(int palmIndex) const { - const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); - int numberOfPalms = handData->getNumPalms(); +PalmData MyAvatar::getActivePalmData(int palmIndex) const { + auto palms = getHandData()->getCopyOfPalms(); + + int numberOfPalms = palms.size(); int numberOfActivePalms = 0; for (int i = 0; i < numberOfPalms; i++) { - auto palm = handData->getPalms()[i]; + auto palm = palms[i]; if (palm.isActive()) { // if we've reached the requested "active" palm, then we will return it if (numberOfActivePalms == palmIndex) { - return &handData->getPalms()[i]; + return palm; } numberOfActivePalms++; } } - return NULL; + PalmData noData(nullptr); + return noData; } glm::vec3 MyAvatar::getLeftHandPosition() const { const int LEFT_HAND = 0; - auto palmData = getActivePalm(LEFT_HAND); - return palmData ? palmData->getPosition() : glm::vec3(0.0f); + auto palmData = getActivePalmData(LEFT_HAND); + return palmData.isValid() ? palmData.getPosition() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandPosition() const { const int RIGHT_HAND = 1; - auto palmData = getActivePalm(RIGHT_HAND); - return palmData ? palmData->getPosition() : glm::vec3(0.0f); + auto palmData = getActivePalmData(RIGHT_HAND); + return palmData.isValid() ? palmData.getPosition() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getLeftHandTipPosition() const { const int LEFT_HAND = 0; - auto palmData = getActivePalm(LEFT_HAND); - return palmData ? palmData->getTipPosition() : glm::vec3(0.0f); + auto palmData = getActivePalmData(LEFT_HAND); + return palmData.isValid() ? palmData.getTipPosition() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandTipPosition() const { const int RIGHT_HAND = 1; - auto palmData = getActivePalm(RIGHT_HAND); - return palmData ? palmData->getTipPosition() : glm::vec3(0.0f); + auto palmData = getActivePalmData(RIGHT_HAND); + return palmData.isValid() ? palmData.getTipPosition() : glm::vec3(0.0f); } controller::Pose MyAvatar::getLeftHandPose() const { const int LEFT_HAND = 0; - auto palmData = getActivePalm(LEFT_HAND); - return palmData ? controller::Pose(palmData->getPosition(), palmData->getRotation(), - palmData->getVelocity(), palmData->getRawAngularVelocityAsQuat()) : controller::Pose(); + auto palmData = getActivePalmData(LEFT_HAND); + return palmData.isValid() ? controller::Pose(palmData.getPosition(), palmData.getRotation(), + palmData.getVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } controller::Pose MyAvatar::getRightHandPose() const { const int RIGHT_HAND = 1; - auto palmData = getActivePalm(RIGHT_HAND); - return palmData ? controller::Pose(palmData->getPosition(), palmData->getRotation(), - palmData->getVelocity(), palmData->getRawAngularVelocityAsQuat()) : controller::Pose(); + auto palmData = getActivePalmData(RIGHT_HAND); + return palmData.isValid() ? controller::Pose(palmData.getPosition(), palmData.getRotation(), + palmData.getVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } controller::Pose MyAvatar::getLeftHandTipPose() const { const int LEFT_HAND = 0; - auto palmData = getActivePalm(LEFT_HAND); - return palmData ? controller::Pose(palmData->getTipPosition(), palmData->getRotation(), - palmData->getTipVelocity(), palmData->getRawAngularVelocityAsQuat()) : controller::Pose(); + auto palmData = getActivePalmData(LEFT_HAND); + return palmData.isValid() ? controller::Pose(palmData.getTipPosition(), palmData.getRotation(), + palmData.getTipVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } controller::Pose MyAvatar::getRightHandTipPose() const { const int RIGHT_HAND = 1; - auto palmData = getActivePalm(RIGHT_HAND); - return palmData ? controller::Pose(palmData->getTipPosition(), palmData->getRotation(), - palmData->getTipVelocity(), palmData->getRawAngularVelocityAsQuat()) : controller::Pose(); + auto palmData = getActivePalmData(RIGHT_HAND); + return palmData.isValid() ? controller::Pose(palmData.getTipPosition(), palmData.getRotation(), + palmData.getTipVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } // virtual @@ -1967,28 +1969,6 @@ void MyAvatar::updateMotionBehaviorFromMenu() { _characterController.setEnabled(menu->isOptionChecked(MenuOption::EnableCharacterController)); } -//Renders sixense laser pointers for UI selection with controllers -void MyAvatar::renderLaserPointers(gpu::Batch& batch) { - const float PALM_TIP_ROD_RADIUS = 0.002f; - - //If the Oculus is enabled, we will draw a blue cursor ray - - for (size_t i = 0; i < getHand()->getNumPalms(); ++i) { - PalmData& palm = getHand()->getPalms()[i]; - if (palm.isActive()) { - glm::vec3 tip = getLaserPointerTipPosition(&palm); - glm::vec3 root = palm.getPosition(); - - //Scale the root vector with the avatar scale - scaleVectorRelativeToPosition(root); - Transform transform = Transform(); - transform.setTranslation(glm::vec3()); - batch.setModelTransform(transform); - Avatar::renderJointConnectingCone(batch, root, tip, PALM_TIP_ROD_RADIUS, PALM_TIP_ROD_RADIUS, glm::vec4(0, 1, 1, 1)); - } - } -} - //Gets the tip position for the laser pointer glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) { glm::vec3 direction = glm::normalize(palm->getTipPosition() - palm->getPosition()); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0a3d7dedf4..b6cce7165a 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -294,7 +294,6 @@ private: const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f, bool allowDuplicates = false, bool useSaved = true) override; - void renderLaserPointers(gpu::Batch& batch); const RecorderPointer getRecorder() const { return _recorder; } const PlayerPointer getPlayer() const { return _player; } @@ -310,8 +309,7 @@ private: void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity); - const PalmData* getActivePalm(int palmIndex) const; - + PalmData getActivePalmData(int palmIndex) const; // derive avatar body position and orientation from the current HMD Sensor location. // results are in sensor space diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 28c7941c52..f821c79d59 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -97,17 +97,6 @@ void SkeletonModel::initJointStates(QVector states) { emit skeletonLoaded(); } -static const PalmData* getPalmWithIndex(Hand* hand, int index) { - const PalmData* palm = nullptr; - for (size_t j = 0; j < hand->getNumPalms(); j++) { - if (hand->getPalms()[j].getSixenseID() == index) { - palm = &(hand->getPalms()[j]); - break; - } - } - return palm; -} - const float PALM_PRIORITY = DEFAULT_PRIORITY; // Called within Model::simulate call, below. void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { @@ -169,22 +158,22 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::HandParameters handParams; - const PalmData* leftPalm = getPalmWithIndex(myAvatar->getHand(), LEFT_HAND_INDEX); - if (leftPalm && leftPalm->isActive()) { + auto leftPalm = myAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand); + if (leftPalm.isValid() && leftPalm.isActive()) { handParams.isLeftEnabled = true; - handParams.leftPosition = leftPalm->getRawPosition(); - handParams.leftOrientation = leftPalm->getRawRotation(); - handParams.leftTrigger = leftPalm->getTrigger(); + handParams.leftPosition = leftPalm.getRawPosition(); + handParams.leftOrientation = leftPalm.getRawRotation(); + handParams.leftTrigger = leftPalm.getTrigger(); } else { handParams.isLeftEnabled = false; } - const PalmData* rightPalm = getPalmWithIndex(myAvatar->getHand(), RIGHT_HAND_INDEX); - if (rightPalm && rightPalm->isActive()) { + auto rightPalm = myAvatar->getHand()->getCopyOfPalmData(HandData::RightHand); + if (rightPalm.isValid() && rightPalm.isActive()) { handParams.isRightEnabled = true; - handParams.rightPosition = rightPalm->getRawPosition(); - handParams.rightOrientation = rightPalm->getRawRotation(); - handParams.rightTrigger = rightPalm->getTrigger(); + handParams.rightPosition = rightPalm.getRawPosition(); + handParams.rightOrientation = rightPalm.getRawRotation(); + handParams.rightTrigger = rightPalm.getTrigger(); } else { handParams.isRightEnabled = false; } @@ -250,10 +239,15 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { // find the left and rightmost active palms int leftPalmIndex, rightPalmIndex; Hand* hand = _owningAvatar->getHand(); - hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); + + // FIXME - it's possible that the left/right hand indices could change between this call + // and the call to hand->getCopyOfPalms(); This logic should be reworked to only operate on + // the copy of the palms data + hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); // Don't Relax toward hand positions when in animGraph mode. if (!_rig->getEnableAnimGraph()) { + auto palms = hand->getCopyOfPalms(); const float HAND_RESTORATION_RATE = 0.25f; if (leftPalmIndex == -1 && rightPalmIndex == -1) { // palms are not yet set, use mouse @@ -268,17 +262,17 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { } else if (leftPalmIndex == rightPalmIndex) { // right hand only - applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[leftPalmIndex]); + applyPalmData(geometry.rightHandJointIndex, palms[leftPalmIndex]); restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { if (leftPalmIndex != -1) { - applyPalmData(geometry.leftHandJointIndex, hand->getPalms()[leftPalmIndex]); + applyPalmData(geometry.leftHandJointIndex, palms[leftPalmIndex]); } else { restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } if (rightPalmIndex != -1) { - applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]); + applyPalmData(geometry.rightHandJointIndex, palms[rightPalmIndex]); } else { restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } @@ -329,7 +323,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) PALM_PRIORITY); } -void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { +void SkeletonModel::applyPalmData(int jointIndex, const PalmData& palm) { if (jointIndex == -1 || jointIndex >= _rig->getJointStateCount()) { return; } diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index d655d6e01f..dc08168a8c 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -118,7 +118,7 @@ protected: /// \param position position of joint in model-frame void applyHandPosition(int jointIndex, const glm::vec3& position); - void applyPalmData(int jointIndex, PalmData& palm); + void applyPalmData(int jointIndex, const PalmData& palm); private: void renderJointConstraints(gpu::Batch& batch, int jointIndex); diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 31f823de8b..547f16ea8b 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -35,51 +35,6 @@ void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) { } } -const PalmData* ControllerScriptingInterface::getPrimaryPalm() const { - int leftPalmIndex, rightPalmIndex; - - const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); - handData->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); - - if (rightPalmIndex != -1) { - return &handData->getPalms()[rightPalmIndex]; - } - - return NULL; -} - -int ControllerScriptingInterface::getNumberOfActivePalms() const { - const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); - int numberOfPalms = handData->getNumPalms(); - int numberOfActivePalms = 0; - for (int i = 0; i < numberOfPalms; i++) { - if (getPalm(i)->isActive()) { - numberOfActivePalms++; - } - } - return numberOfActivePalms; -} - -const PalmData* ControllerScriptingInterface::getPalm(int palmIndex) const { - const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); - return &handData->getPalms()[palmIndex]; -} - -const PalmData* ControllerScriptingInterface::getActivePalm(int palmIndex) const { - const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); - int numberOfPalms = handData->getNumPalms(); - int numberOfActivePalms = 0; - for (int i = 0; i < numberOfPalms; i++) { - if (getPalm(i)->isActive()) { - if (numberOfActivePalms == palmIndex) { - return &handData->getPalms()[i]; - } - numberOfActivePalms++; - } - } - return NULL; -} - bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const { return isKeyCaptured(KeyEvent(*event)); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 3133f93804..4c69551dd2 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -123,11 +123,6 @@ signals: private: QString sanatizeName(const QString& name); /// makes a name clean for inclusing in JavaScript - const PalmData* getPrimaryPalm() const; - const PalmData* getPalm(int palmIndex) const; - int getNumberOfActivePalms() const; - const PalmData* getActivePalm(int palmIndex) const; - QMultiMap _capturedKeys; QSet _capturedJoysticks; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index ca5c60dc04..2f442a3284 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -320,8 +320,9 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int // Only render the hand pointers if the EnableHandMouseInput is enabled if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { - PalmData& palm = myAvatar->getHand()->getPalms()[i]; + auto palms = myAvatar->getHand()->getCopyOfPalms(); + for (int i = 0; i < (int)palms.size(); i++) { + const auto& palm = palms[i]; if (palm.isActive()) { glm::vec2 polar = getPolarCoordinates(palm); // Convert to quaternion @@ -446,6 +447,7 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) { } +// FIXME - this is old code that likely needs to be removed and/or reworked to support the new input control model void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); @@ -455,23 +457,24 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { static bool stateWhenPressed[NUMBER_OF_RETICLES] = { false, false, false }; const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); + auto palms = handData->getCopyOfPalms(); for (unsigned int palmIndex = 2; palmIndex < 4; palmIndex++) { const int index = palmIndex - 1; const PalmData* palmData = NULL; - if (palmIndex >= handData->getPalms().size()) { + if (palmIndex >= palms.size()) { return; } - if (handData->getPalms()[palmIndex].isActive()) { - palmData = &handData->getPalms()[palmIndex]; + if (palms[palmIndex].isActive()) { + palmData = &palms[palmIndex]; } else { continue; } - int controllerButtons = palmData->getControllerButtons(); + int controllerButtons = 0; //Check for if we should toggle or drag the magnification window if (controllerButtons & BUTTON_3) { diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 1a9b6775d3..4e08f5190f 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -21,6 +21,8 @@ HandData::HandData(AvatarData* owningAvatar) : _owningAvatarData(owningAvatar) { + // FIXME - this is likely the source of the fact that with Hydras and other input plugins with hand controllers + // we end up with 4 palms... because we end up adding palms once we know the SixenseIDs // Start with two palms addNewPalm(); addNewPalm(); @@ -31,32 +33,35 @@ glm::vec3 HandData::worldToLocalVector(const glm::vec3& worldVector) const { } PalmData& HandData::addNewPalm() { + QWriteLocker locker(&_palmsLock); _palms.push_back(PalmData(this)); return _palms.back(); } -const PalmData* HandData::getPalm(int sixSenseID) const { +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 right SixSenseID - for (unsigned int i = 0; i < _palms.size(); i++) { - const PalmData* palm = &(_palms[i]); - if (palm->getSixenseID() == sixSenseID) { - return palm->isActive() ? palm : NULL; + // so we have to search for the correct hand + for (const auto& palm : _palms) { + if (palm.whichHand() == hand && palm.isActive()) { + return palm; } } - return NULL; + return PalmData(nullptr); // invalid hand } void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const { + QReadLocker locker(&_palmsLock); leftPalmIndex = -1; rightPalmIndex = -1; for (size_t i = 0; i < _palms.size(); i++) { const PalmData& palm = _palms[i]; if (palm.isActive()) { - if (palm.getSixenseID() == LEFT_HAND_INDEX) { + if (palm.whichHand() == LeftHand) { leftPalmIndex = i; } - if (palm.getSixenseID() == RIGHT_HAND_INDEX) { + if (palm.whichHand() == RightHand) { rightPalmIndex = i; } } @@ -69,14 +74,9 @@ _rawPosition(0.0f), _rawVelocity(0.0f), _rawAngularVelocity(0.0f), _totalPenetration(0.0f), -_controllerButtons(0), _isActive(false), -_sixenseID(SIXENSEID_INVALID), _numFramesWithoutData(0), -_owningHandData(owningHandData), -_isCollidingWithVoxel(false), -_isCollidingWithPalm(false), -_collisionlessPaddleExpiry(0) { +_owningHandData(owningHandData) { } void PalmData::addToPosition(const glm::vec3& delta) { @@ -85,7 +85,8 @@ void PalmData::addToPosition(const glm::vec3& delta) { bool HandData::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, const PalmData*& collidingPalm) const { - + QReadLocker locker(&_palmsLock); + for (size_t i = 0; i < _palms.size(); ++i) { const PalmData& palm = _palms[i]; if (!palm.isActive()) { diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 855da63870..ca2aa9836a 100644 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -12,26 +12,30 @@ #ifndef hifi_HandData_h #define hifi_HandData_h +#include #include #include #include #include +#include + #include #include class AvatarData; class PalmData; -const int LEFT_HAND_INDEX = 0; -const int RIGHT_HAND_INDEX = 1; -const int NUM_HANDS = 2; - -const int SIXENSEID_INVALID = -1; - class HandData { public: + enum Hand { + UnknownHand, + RightHand, + LeftHand, + NUMBER_OF_HANDS + }; + HandData(AvatarData* owningAvatar); virtual ~HandData() {} @@ -46,11 +50,10 @@ public: glm::vec3 worldToLocalVector(const glm::vec3& worldVector) const; - std::vector& getPalms() { return _palms; } - const std::vector& getPalms() const { return _palms; } - const PalmData* getPalm(int sixSenseID) const; - size_t getNumPalms() const { return _palms.size(); } + PalmData getCopyOfPalmData(Hand hand) const; + PalmData& addNewPalm(); + std::vector getCopyOfPalms() const { QReadLocker locker(&_palmsLock); return _palms; } /// Finds the indices of the left and right palms according to their locations, or -1 if either or /// both is not found. @@ -67,10 +70,15 @@ public: glm::quat getBaseOrientation() const; + /// Allows a lamda function write access to the palms for this Hand + void modifyPalms(std::function& palms)> callback) + { QWriteLocker locker(&_palmsLock); callback(_palms);} + friend class AvatarData; protected: AvatarData* _owningAvatarData; std::vector _palms; + mutable QReadWriteLock _palmsLock{ QReadWriteLock::Recursive }; glm::vec3 getBasePosition() const; float getBaseScale() const; @@ -90,10 +98,12 @@ public: const glm::vec3& getRawPosition() const { return _rawPosition; } bool isActive() const { return _isActive; } - int getSixenseID() const { return _sixenseID; } + bool isValid() const { return _owningHandData; } void setActive(bool active) { _isActive = active; } - void setSixenseID(int id) { _sixenseID = id; } + + 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; } @@ -123,31 +133,11 @@ public: void resetFramesWithoutData() { _numFramesWithoutData = 0; } int getFramesWithoutData() const { return _numFramesWithoutData; } - // Controller buttons - void setControllerButtons(unsigned int controllerButtons) { _controllerButtons = controllerButtons; } - void setLastControllerButtons(unsigned int controllerButtons) { _lastControllerButtons = controllerButtons; } - - unsigned int getControllerButtons() const { return _controllerButtons; } - unsigned int getLastControllerButtons() const { return _lastControllerButtons; } - + // 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; } - void setJoystick(float joystickX, float joystickY) { _joystickX = joystickX; _joystickY = joystickY; } - float getJoystickX() const { return _joystickX; } - float getJoystickY() const { return _joystickY; } - bool getIsCollidingWithVoxel() const { return _isCollidingWithVoxel; } - void setIsCollidingWithVoxel(bool isCollidingWithVoxel) { _isCollidingWithVoxel = isCollidingWithVoxel; } - - bool getIsCollidingWithPalm() const { return _isCollidingWithPalm; } - void setIsCollidingWithPalm(bool isCollidingWithPalm) { _isCollidingWithPalm = isCollidingWithPalm; } - - bool hasPaddle() const { return _collisionlessPaddleExpiry < usecTimestampNow(); } - void updateCollisionlessPaddleExpiry() { _collisionlessPaddleExpiry = usecTimestampNow() + USECS_PER_SECOND; } - - /// Store position where the palm holds the ball. - void getBallHoldPosition(glm::vec3& position) const; - // return world-frame: glm::vec3 getFingerDirection() const; glm::vec3 getNormal() const; @@ -163,21 +153,14 @@ private: glm::vec3 _tipPosition; glm::vec3 _tipVelocity; - glm::vec3 _totalPenetration; // accumulator for per-frame penetrations + glm::vec3 _totalPenetration; /// accumulator for per-frame penetrations - unsigned int _controllerButtons; - unsigned int _lastControllerButtons; float _trigger; - float _joystickX, _joystickY; - bool _isActive; // This has current valid data - int _sixenseID; // Sixense controller ID for this palm - int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost. + bool _isActive; /// This has current valid data + HandData::Hand _hand = HandData::UnknownHand; + int _numFramesWithoutData; /// after too many frames without data, this tracked object assumed lost. HandData* _owningHandData; - - bool _isCollidingWithVoxel; /// Whether the finger of this palm is inside a leaf voxel - bool _isCollidingWithPalm; - quint64 _collisionlessPaddleExpiry; /// Timestamp after which paddle starts colliding }; #endif // hifi_HandData_h From 133d48ebee8c24cfd1fba989037da20b361573e7 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Oct 2015 15:53:48 -0700 Subject: [PATCH 2/6] CR feedback --- interface/src/Application.cpp | 53 +++++++++--------------------- libraries/avatars/src/HandData.cpp | 19 +++++------ libraries/avatars/src/HandData.h | 28 +++++++++++----- 3 files changed, 44 insertions(+), 56 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 910cbb19e2..29f4bd6ece 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4811,30 +4811,9 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de // 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->modifyPalms([&](std::vector& palms) { + hand->modifyPalm(whichHand, [&](PalmData& palm) { auto myAvatar = DependencyManager::get()->getMyAvatar(); - PalmData* palm; - bool foundHand = false; - - // FIXME - this little chuck of code is a hot mess. It's basically searching the palms - // for the one that matches the "sixenseID" that is the "index" parameter. If it - // doesn't find it, then it creates a new palm and sets that palm's ID this really - // can and should be inside the HandData class - for (size_t j = 0; j < palms.size(); j++) { - if (palms[j].whichHand() == whichHand) { - palm = &(palms[j]); - foundHand = true; - break; - } - } - if (!foundHand) { - PalmData newPalm(hand); - palms.push_back(newPalm); - palm = &(palms[palms.size() - 1]); // FIXME - lame - palm->setHand(whichHand); - } - - palm->setActive(pose.isValid()); + palm.setActive(pose.isValid()); // transform from sensor space, to world space, to avatar model space. glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation()); @@ -4848,46 +4827,46 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de // Compute current velocity from position change glm::vec3 rawVelocity; if (deltaTime > 0.0f) { - rawVelocity = (position - palm->getRawPosition()) / deltaTime; + rawVelocity = (position - palm.getRawPosition()) / deltaTime; } else { rawVelocity = glm::vec3(0.0f); } - palm->setRawVelocity(rawVelocity); // meters/sec + palm.setRawVelocity(rawVelocity); // meters/sec // Angular Velocity of Palm - glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); + glm::quat deltaRotation = rotation * glm::inverse(palm.getRawRotation()); glm::vec3 angularVelocity(0.0f); float rotationAngle = glm::angle(deltaRotation); if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { angularVelocity = glm::normalize(glm::axis(deltaRotation)); angularVelocity *= (rotationAngle / deltaTime); - palm->setRawAngularVelocity(angularVelocity); + palm.setRawAngularVelocity(angularVelocity); } else { - palm->setRawAngularVelocity(glm::vec3(0.0f)); + palm.setRawAngularVelocity(glm::vec3(0.0f)); } 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); + position = palm.getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); + rotation = safeMix(palm.getRawRotation(), rotation, 1.0f - velocityFilter); } - palm->setRawPosition(position); - palm->setRawRotation(rotation); + 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(); + glm::vec3 oldTipPosition = palm.getTipRawPosition(); if (deltaTime > 0.0f) { - palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); + palm.setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); } else { - palm->setTipVelocity(glm::vec3(0.0f)); + palm.setTipVelocity(glm::vec3(0.0f)); } - palm->setTipPosition(newTipPosition); - palm->setTrigger(triggerValue); + palm.setTipPosition(newTipPosition); + palm.setTrigger(triggerValue); }); } diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 4e08f5190f..0237f8ecd9 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -21,20 +21,17 @@ HandData::HandData(AvatarData* owningAvatar) : _owningAvatarData(owningAvatar) { - // FIXME - this is likely the source of the fact that with Hydras and other input plugins with hand controllers - // we end up with 4 palms... because we end up adding palms once we know the SixenseIDs - // Start with two palms - addNewPalm(); - addNewPalm(); + addNewPalm(LeftHand); + addNewPalm(RightHand); } glm::vec3 HandData::worldToLocalVector(const glm::vec3& worldVector) const { return glm::inverse(getBaseOrientation()) * worldVector / getBaseScale(); } -PalmData& HandData::addNewPalm() { +PalmData& HandData::addNewPalm(Hand whichHand) { QWriteLocker locker(&_palmsLock); - _palms.push_back(PalmData(this)); + _palms.push_back(PalmData(this, whichHand)); return _palms.back(); } @@ -48,7 +45,8 @@ PalmData HandData::getCopyOfPalmData(Hand hand) const { return palm; } } - return PalmData(nullptr); // invalid hand + PalmData noData; + return noData; // invalid hand } void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const { @@ -68,7 +66,7 @@ void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) } } -PalmData::PalmData(HandData* owningHandData) : +PalmData::PalmData(HandData* owningHandData, HandData::Hand hand) : _rawRotation(0.0f, 0.0f, 0.0f, 1.0f), _rawPosition(0.0f), _rawVelocity(0.0f), @@ -76,7 +74,8 @@ _rawAngularVelocity(0.0f), _totalPenetration(0.0f), _isActive(false), _numFramesWithoutData(0), -_owningHandData(owningHandData) { +_owningHandData(owningHandData), +_hand(hand) { } void PalmData::addToPosition(const glm::vec3& delta) { diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index ca2aa9836a..10292daccc 100644 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -30,9 +30,9 @@ class PalmData; class HandData { public: enum Hand { - UnknownHand, - RightHand, LeftHand, + RightHand, + UnknownHand, NUMBER_OF_HANDS }; @@ -52,7 +52,6 @@ public: PalmData getCopyOfPalmData(Hand hand) const; - PalmData& addNewPalm(); std::vector getCopyOfPalms() const { QReadLocker locker(&_palmsLock); return _palms; } /// Finds the indices of the left and right palms according to their locations, or -1 if either or @@ -70,9 +69,17 @@ public: glm::quat getBaseOrientation() const; - /// Allows a lamda function write access to the palms for this Hand - void modifyPalms(std::function& palms)> callback) - { QWriteLocker locker(&_palmsLock); callback(_palms);} + /// 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) { + QReadLocker locker(&_palmsLock); + for (auto& palm : _palms) { + if (palm.whichHand() == whichHand && palm.isValid()) { + callback(palm); + return; + } + } + } friend class AvatarData; protected: @@ -82,7 +89,10 @@ protected: 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&); @@ -92,7 +102,7 @@ private: class PalmData { public: - PalmData(HandData* owningHandData); + 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); } @@ -158,7 +168,7 @@ private: float _trigger; bool _isActive; /// This has current valid data - HandData::Hand _hand = HandData::UnknownHand; + HandData::Hand _hand; int _numFramesWithoutData; /// after too many frames without data, this tracked object assumed lost. HandData* _owningHandData; }; From eb1936412954d0eabf2152f9fc759b5a2c9405c0 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Oct 2015 15:56:27 -0700 Subject: [PATCH 3/6] CR feedback --- interface/src/avatar/MyAvatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5483219318..1b1a2a18e0 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -569,8 +569,8 @@ PalmData MyAvatar::getActivePalmData(int palmIndex) const { numberOfActivePalms++; } } - PalmData noData(nullptr); - return noData; + ; + return PalmData(); } From 19743c1f39c17743634d3b7894a57a882f8d3b55 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Oct 2015 16:16:03 -0700 Subject: [PATCH 4/6] gak, build busters and more CR feedback --- interface/src/Application.cpp | 4 +-- interface/src/avatar/MyAvatar.cpp | 50 +++++------------------------- libraries/avatars/src/HandData.cpp | 3 +- libraries/avatars/src/HandData.h | 24 +++++++------- 4 files changed, 24 insertions(+), 57 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 29f4bd6ece..5f5b8e68c5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4807,7 +4807,7 @@ mat4 Application::getHMDSensorPose() const { void Application::setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, HandData::Hand whichHand, float triggerValue) { - // NOTE: the Hand::modifyPalms() will allow the lambda to modify the palm data while ensuring some other user isn't + // 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. @@ -4866,7 +4866,7 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de palm.setTipVelocity(glm::vec3(0.0f)); } palm.setTipPosition(newTipPosition); - palm.setTrigger(triggerValue); + palm.setTrigger(triggerValue); // FIXME - we want to get rid of this idea of PalmData having a trigger }); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1b1a2a18e0..18a7f4eb52 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -548,80 +548,46 @@ void MyAvatar::updateFromTrackers(float deltaTime) { } -// FIXME - this is super duper dumb... but this is how master works. When you have -// hydras plugged in, you'll get 4 "palms" but only the number of controllers lifted -// of the base station are considered active. So when you ask for "left" you get the -// first active controller. If you have both controllers held up or just the left, that -// will be correct. But if you lift the right controller, then it will be reported -// as "left"... you also see this in the avatars hands. -PalmData MyAvatar::getActivePalmData(int palmIndex) const { - auto palms = getHandData()->getCopyOfPalms(); - - int numberOfPalms = palms.size(); - int numberOfActivePalms = 0; - for (int i = 0; i < numberOfPalms; i++) { - auto palm = palms[i]; - if (palm.isActive()) { - // if we've reached the requested "active" palm, then we will return it - if (numberOfActivePalms == palmIndex) { - return palm; - } - numberOfActivePalms++; - } - } - ; - return PalmData(); -} - - glm::vec3 MyAvatar::getLeftHandPosition() const { - const int LEFT_HAND = 0; - auto palmData = getActivePalmData(LEFT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); return palmData.isValid() ? palmData.getPosition() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandPosition() const { - const int RIGHT_HAND = 1; - auto palmData = getActivePalmData(RIGHT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); return palmData.isValid() ? palmData.getPosition() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getLeftHandTipPosition() const { - const int LEFT_HAND = 0; - auto palmData = getActivePalmData(LEFT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); return palmData.isValid() ? palmData.getTipPosition() : glm::vec3(0.0f); } glm::vec3 MyAvatar::getRightHandTipPosition() const { - const int RIGHT_HAND = 1; - auto palmData = getActivePalmData(RIGHT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); return palmData.isValid() ? palmData.getTipPosition() : glm::vec3(0.0f); } controller::Pose MyAvatar::getLeftHandPose() const { - const int LEFT_HAND = 0; - auto palmData = getActivePalmData(LEFT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); return palmData.isValid() ? controller::Pose(palmData.getPosition(), palmData.getRotation(), palmData.getVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } controller::Pose MyAvatar::getRightHandPose() const { - const int RIGHT_HAND = 1; - auto palmData = getActivePalmData(RIGHT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); return palmData.isValid() ? controller::Pose(palmData.getPosition(), palmData.getRotation(), palmData.getVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } controller::Pose MyAvatar::getLeftHandTipPose() const { - const int LEFT_HAND = 0; - auto palmData = getActivePalmData(LEFT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::LeftHand); return palmData.isValid() ? controller::Pose(palmData.getTipPosition(), palmData.getRotation(), palmData.getTipVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } controller::Pose MyAvatar::getRightHandTipPose() const { - const int RIGHT_HAND = 1; - auto palmData = getActivePalmData(RIGHT_HAND); + auto palmData = getHandData()->getCopyOfPalmData(HandData::RightHand); return palmData.isValid() ? controller::Pose(palmData.getTipPosition(), palmData.getRotation(), palmData.getTipVelocity(), palmData.getRawAngularVelocityAsQuat()) : controller::Pose(); } diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 0237f8ecd9..413a5ea955 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -45,8 +45,7 @@ PalmData HandData::getCopyOfPalmData(Hand hand) const { return palm; } } - PalmData noData; - return noData; // invalid hand + return PalmData(); // invalid hand } void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const { diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 10292daccc..b475248d9e 100644 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -71,15 +71,7 @@ public: /// 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) { - QReadLocker locker(&_palmsLock); - for (auto& palm : _palms) { - if (palm.whichHand() == whichHand && palm.isValid()) { - callback(palm); - return; - } - } - } + template void modifyPalm(Hand whichHand, PalmModifierFunction callback); friend class AvatarData; protected: @@ -115,7 +107,7 @@ public: HandData::Hand whichHand() const { return _hand; } void setHand(HandData::Hand hand) { _hand = hand; } - void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; }; + 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; } @@ -168,9 +160,19 @@ private: float _trigger; bool _isActive; /// This has current valid data - HandData::Hand _hand; 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 d86f1b50a7c8a68c1d261879520eb0d915dc19ca Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Oct 2015 16:37:43 -0700 Subject: [PATCH 5/6] more cleanup --- interface/src/avatar/Hand.cpp | 6 ++---- interface/src/ui/ApplicationCompositor.cpp | 3 +-- libraries/avatars/src/HandData.cpp | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index dfac5e393f..15a3163998 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -51,8 +51,7 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { gpu::Batch& batch = *renderArgs->_batch; if (isMine) { - for (size_t i = 0; i < palms.size(); i++) { - PalmData& palm = palms[i]; + for (const auto& palm : palms) { if (!palm.isActive()) { continue; } @@ -78,8 +77,7 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { const float AXIS_LENGTH = 10.0f * SPHERE_RADIUS; // Draw the coordinate frames of the hand targets - for (size_t i = 0; i < palms.size(); ++i) { - PalmData& palm = palms[i]; + for (const auto& palm : palms) { if (palm.isActive()) { glm::vec3 root = palm.getPosition(); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 2f442a3284..2a2a45b67b 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -321,8 +321,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); auto palms = myAvatar->getHand()->getCopyOfPalms(); - for (int i = 0; i < (int)palms.size(); i++) { - const auto& palm = palms[i]; + for (const auto& palm : palms) { if (palm.isActive()) { glm::vec2 polar = getPolarCoordinates(palm); // Convert to quaternion diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 413a5ea955..fc6d18932a 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -85,8 +85,7 @@ bool HandData::findSpherePenetration(const glm::vec3& penetratorCenter, float pe const PalmData*& collidingPalm) const { QReadLocker locker(&_palmsLock); - for (size_t i = 0; i < _palms.size(); ++i) { - const PalmData& palm = _palms[i]; + for (const auto& palm : _palms) { if (!palm.isActive()) { continue; } From 65eae3543329ac8b2585f7a24fac18cc40752c2e Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Oct 2015 17:09:43 -0700 Subject: [PATCH 6/6] a little more cleanup --- interface/src/avatar/SkeletonModel.cpp | 31 +++++++++----------------- libraries/avatars/src/HandData.cpp | 17 -------------- libraries/avatars/src/HandData.h | 4 ---- 3 files changed, 10 insertions(+), 42 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index f821c79d59..e39bfe246b 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -236,20 +236,15 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); - // find the left and rightmost active palms - int leftPalmIndex, rightPalmIndex; - Hand* hand = _owningAvatar->getHand(); - - // FIXME - it's possible that the left/right hand indices could change between this call - // and the call to hand->getCopyOfPalms(); This logic should be reworked to only operate on - // the copy of the palms data - hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); - // Don't Relax toward hand positions when in animGraph mode. if (!_rig->getEnableAnimGraph()) { - auto palms = hand->getCopyOfPalms(); + + Hand* hand = _owningAvatar->getHand(); + auto leftPalm = hand->getCopyOfPalmData(HandData::LeftHand); + auto rightPalm = hand->getCopyOfPalmData(HandData::RightHand); + const float HAND_RESTORATION_RATE = 0.25f; - if (leftPalmIndex == -1 && rightPalmIndex == -1) { + if (!leftPalm.isActive() && !rightPalm.isActive()) { // palms are not yet set, use mouse if (_owningAvatar->getHandState() == HAND_STATE_NULL) { restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); @@ -259,20 +254,14 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { applyHandPosition(geometry.rightHandJointIndex, handPosition); } restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); - - } else if (leftPalmIndex == rightPalmIndex) { - // right hand only - applyPalmData(geometry.rightHandJointIndex, palms[leftPalmIndex]); - restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); - } else { - if (leftPalmIndex != -1) { - applyPalmData(geometry.leftHandJointIndex, palms[leftPalmIndex]); + if (leftPalm.isActive()) { + applyPalmData(geometry.leftHandJointIndex, leftPalm); } else { restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } - if (rightPalmIndex != -1) { - applyPalmData(geometry.rightHandJointIndex, palms[rightPalmIndex]); + if (rightPalm.isActive()) { + applyPalmData(geometry.rightHandJointIndex, rightPalm); } else { restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index fc6d18932a..5d783a671e 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -48,23 +48,6 @@ PalmData HandData::getCopyOfPalmData(Hand hand) const { return PalmData(); // invalid hand } -void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const { - QReadLocker locker(&_palmsLock); - leftPalmIndex = -1; - rightPalmIndex = -1; - for (size_t i = 0; i < _palms.size(); i++) { - const PalmData& palm = _palms[i]; - if (palm.isActive()) { - if (palm.whichHand() == LeftHand) { - leftPalmIndex = i; - } - if (palm.whichHand() == RightHand) { - rightPalmIndex = i; - } - } - } -} - PalmData::PalmData(HandData* owningHandData, HandData::Hand hand) : _rawRotation(0.0f, 0.0f, 0.0f, 1.0f), _rawPosition(0.0f), diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index b475248d9e..d782f240ee 100644 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -54,10 +54,6 @@ public: std::vector getCopyOfPalms() const { QReadLocker locker(&_palmsLock); return _palms; } - /// Finds the indices of the left and right palms according to their locations, or -1 if either or - /// both is not found. - void getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const; - /// 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