From 5a42991e0ccd075100c2da985f7d67925fd076c5 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Oct 2015 12:30:34 -0700 Subject: [PATCH] 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