diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index deefd10ab0..f9eaf89ea4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2752,6 +2752,9 @@ void Application::displayOverlay() { drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 0.0f, 0, frameTimer, WHITE_TEXT); } + // give external parties a change to hook in + emit renderingOverlay(); + _overlays.render2D(); glPopMatrix(); @@ -3060,6 +3063,8 @@ void Application::resetSensors() { OculusManager::reset(); } + _prioVR.reset(); + QCursor::setPos(_mouseX, _mouseY); _myAvatar->reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 77f8024b6c..985859f4d0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -195,6 +195,7 @@ public: Visage* getVisage() { return &_visage; } FaceTracker* getActiveFaceTracker(); SixenseManager* getSixenseManager() { return &_sixenseManager; } + PrioVR* getPrioVR() { return &_prioVR; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } QUndoStack* getUndoStack() { return &_undoStack; } @@ -268,6 +269,9 @@ signals: /// Fired when we're rendering in-world interface elements; allows external parties to hook in. void renderingInWorldInterface(); + /// Fired when we're rendering the overlay. + void renderingOverlay(); + /// Fired when the import window is closed void importDone(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e6d6634653..8358fecd9d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -244,23 +244,28 @@ void MyAvatar::simulate(float deltaTime) { void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; - FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker(); - if (tracker) { - estimatedPosition = tracker->getHeadTranslation(); - estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation())); - - // Rotate the body if the head is turned beyond the screen - if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) { - const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f; - const float TRACKER_MIN_YAW_TURN = 15.0f; - const float TRACKER_MAX_YAW_TURN = 50.0f; - if ( (fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) && - (fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) { - if (estimatedRotation.y > 0.0f) { - _bodyYawDelta += (estimatedRotation.y - TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; - } else { - _bodyYawDelta += (estimatedRotation.y + TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; - } + if (Application::getInstance()->getPrioVR()->isActive()) { + estimatedRotation = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getHeadRotation())); + + } else { + FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker(); + if (tracker) { + estimatedPosition = tracker->getHeadTranslation(); + estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation())); + } + } + + // Rotate the body if the head is turned beyond the screen + if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) { + const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f; + const float TRACKER_MIN_YAW_TURN = 15.0f; + const float TRACKER_MAX_YAW_TURN = 50.0f; + if ( (fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) && + (fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) { + if (estimatedRotation.y > 0.0f) { + _bodyYawDelta += (estimatedRotation.y - TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; + } else { + _bodyYawDelta += (estimatedRotation.y + TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; } } } @@ -278,6 +283,14 @@ void MyAvatar::updateFromTrackers(float deltaTime) { head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView); head->setDeltaRoll(estimatedRotation.z); + // the priovr can give us exact lean + if (Application::getInstance()->getPrioVR()->isActive()) { + glm::vec3 eulers = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getTorsoRotation())); + head->setLeanSideways(eulers.z); + head->setLeanForward(eulers.x); + return; + } + // Update torso lean distance based on accelerometer data const float TORSO_LENGTH = 0.5f; glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 96510dad25..7a515d63dc 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -33,14 +33,28 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { return; // only simulate for own avatar } + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + PrioVR* prioVR = Application::getInstance()->getPrioVR(); + if (prioVR->isActive()) { + for (int i = 0; i < prioVR->getJointRotations().size(); i++) { + int humanIKJointIndex = prioVR->getHumanIKJointIndices().at(i); + if (humanIKJointIndex == -1) { + continue; + } + int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex); + if (jointIndex != -1) { + setJointRotation(jointIndex, _rotation * prioVR->getJointRotations().at(i), true); + } + } + return; + } + // find the left and rightmost active Leap palms int leftPalmIndex, rightPalmIndex; Hand* hand = _owningAvatar->getHand(); hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); - const float HAND_RESTORATION_RATE = 0.25f; - - const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const float HAND_RESTORATION_RATE = 0.25f; if (leftPalmIndex == -1) { // no Leap data; set hands from mouse if (_owningAvatar->getHandState() == HAND_STATE_NULL) { diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index 5fe6b56b11..adda3b5cb2 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -13,7 +13,9 @@ #include +#include "Application.h" #include "PrioVR.h" +#include "ui/TextRenderer.h" const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A, 0x0000000C, 0x0000000D, 0x0000000E, 0x00000004, 0x00000005, 0x00000010, 0x00000011 }; @@ -49,7 +51,6 @@ PrioVR::PrioVR() { for (int i = 0; i < LIST_LENGTH; i++) { _humanIKJointIndices.append(jointsDiscovered[i] ? indexOfHumanIKJoint(JOINT_NAMES[i]) : -1); } - yei_tareSensors(_skeletalDevice); #endif } @@ -61,6 +62,16 @@ PrioVR::~PrioVR() { #endif } +glm::quat PrioVR::getHeadRotation() const { + const int HEAD_ROTATION_INDEX = 0; + return _jointRotations.size() > HEAD_ROTATION_INDEX ? _jointRotations.at(HEAD_ROTATION_INDEX) : glm::quat(); +} + +glm::quat PrioVR::getTorsoRotation() const { + const int TORSO_ROTATION_INDEX = 1; + return _jointRotations.size() > TORSO_ROTATION_INDEX ? _jointRotations.at(TORSO_ROTATION_INDEX) : glm::quat(); +} + void PrioVR::update() { #ifdef HAVE_PRIOVR if (!_skeletalDevice) { @@ -71,3 +82,30 @@ void PrioVR::update() { _jointRotations.size() * sizeof(glm::quat), ×tamp); #endif } + +void PrioVR::reset() { +#ifdef HAVE_PRIOVR + if (!_skeletalDevice) { + return; + } + connect(Application::getInstance(), SIGNAL(renderingOverlay()), SLOT(renderCalibrationCountdown())); + _calibrationCountdownStarted = QDateTime::currentDateTime(); +#endif +} + +void PrioVR::renderCalibrationCountdown() { +#ifdef HAVE_PRIOVR + const int COUNTDOWN_SECONDS = 3; + int secondsRemaining = COUNTDOWN_SECONDS - _calibrationCountdownStarted.secsTo(QDateTime::currentDateTime()); + if (secondsRemaining == 0) { + yei_tareSensors(_skeletalDevice); + Application::getInstance()->disconnect(this); + return; + } + static TextRenderer textRenderer(MONO_FONT_FAMILY, 18, QFont::Bold, false, TextRenderer::OUTLINE_EFFECT, 2); + QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "..."; + textRenderer.draw((Application::getInstance()->getGLWidget()->width() - textRenderer.computeWidth(text.constData())) / 2, + Application::getInstance()->getGLWidget()->height() / 2, + text); +#endif +} diff --git a/interface/src/devices/PrioVR.h b/interface/src/devices/PrioVR.h index 8bb21f4357..9cd7bda5d4 100644 --- a/interface/src/devices/PrioVR.h +++ b/interface/src/devices/PrioVR.h @@ -12,6 +12,7 @@ #ifndef hifi_PrioVR_h #define hifi_PrioVR_h +#include #include #include @@ -32,10 +33,20 @@ public: PrioVR(); virtual ~PrioVR(); + bool isActive() const { return !_jointRotations.isEmpty(); } + + glm::quat getHeadRotation() const; + glm::quat getTorsoRotation() const; + const QVector& getHumanIKJointIndices() const { return _humanIKJointIndices; } const QVector& getJointRotations() const { return _jointRotations; } void update(); + void reset(); + +private slots: + + void renderCalibrationCountdown(); private: #ifdef HAVE_PRIOVR @@ -44,6 +55,8 @@ private: QVector _humanIKJointIndices; QVector _jointRotations; + + QDateTime _calibrationCountdownStarted; }; #endif // hifi_PrioVR_h