From cd2665fc55e2dc7a39856e90ae643258e3c92555 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 24 Apr 2017 18:10:50 -0400 Subject: [PATCH 01/32] standardize Audio bg thread joins --- interface/src/Application.cpp | 11 +-- libraries/audio-client/src/AudioClient.cpp | 89 +++++++++++++--------- libraries/audio-client/src/AudioClient.h | 38 +++------ 3 files changed, 69 insertions(+), 69 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fbf28a8d99..c94b1bbd2f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1683,7 +1683,6 @@ void Application::updateHeartbeat() const { void Application::aboutToQuit() { emit beforeAboutToQuit(); - DependencyManager::get()->beforeAboutToQuit(); foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { if (inputPlugin->isActive()) { @@ -1784,14 +1783,12 @@ void Application::cleanupBeforeQuit() { _snapshotSoundInjector->stop(); } - // stop audio after QML, as there are unexplained audio crashes originating in qtwebengine - - // stop the AudioClient, synchronously - QMetaObject::invokeMethod(DependencyManager::get().data(), - "stop", Qt::BlockingQueuedConnection); - + // FIXME: something else is holding a reference to AudioClient, + // so it must be explicitly synchronously stopped here + QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::BlockingQueuedConnection); // destroy Audio so it and its threads have a chance to go down safely + // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine DependencyManager::destroy(); DependencyManager::destroy(); diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 4a2de0a64b..6107fef516 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -76,42 +76,58 @@ using Mutex = std::mutex; using Lock = std::unique_lock; static Mutex _deviceMutex; -// background thread that continuously polls for device changes -class CheckDevicesThread : public QThread { +class BackgroundThread : public QThread { public: - const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; + BackgroundThread(AudioClient* client) : QThread((QObject*)client), _client(client) {} + virtual void join() = 0; +protected: + AudioClient* _client; +}; - CheckDevicesThread(AudioClient* audioClient) - : _audioClient(audioClient) { - } +// background thread continuously polling device changes +class CheckDevicesThread : public BackgroundThread { +public: + CheckDevicesThread(AudioClient* client) : BackgroundThread(client) {} - void beforeAboutToQuit() { - Lock lock(_checkDevicesMutex); + void join() override { _quit = true; + std::unique_lock lock(mutex); + cv.wait(lock, [&]{ return !running; }); } +protected: void run() override { - while (true) { - { - Lock lock(_checkDevicesMutex); - if (_quit) { - break; - } - _audioClient->checkDevices(); - } + while (!_quit) { + _client->checkDevices(); + + const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; QThread::msleep(DEVICE_CHECK_INTERVAL_MSECS); } + std::lock_guard lock(mutex); + running = false; + cv.notify_one(); } private: - AudioClient* _audioClient { nullptr }; - Mutex _checkDevicesMutex; - bool _quit { false }; + std::atomic _quit { false }; + bool running { true }; + std::mutex mutex; + std::condition_variable cv; }; -void AudioInjectorsThread::prepare() { - _audio->prepareLocalAudioInjectors(); -} +// background thread buffering local injectors +class LocalInjectorsThread : public BackgroundThread { + Q_OBJECT +public: + LocalInjectorsThread(AudioClient* client) : BackgroundThread(client) {} + + void join() override { return; } + +private slots: + void prepare() { _client->prepareLocalAudioInjectors(); } +}; + +#include "AudioClient.moc" static void channelUpmix(int16_t* source, int16_t* dest, int numSamples, int numExtraChannels) { for (int i = 0; i < numSamples/2; i++) { @@ -179,7 +195,6 @@ AudioClient::AudioClient() : _inputToNetworkResampler(NULL), _networkToOutputResampler(NULL), _localToOutputResampler(NULL), - _localAudioThread(this), _audioLimiter(AudioConstants::SAMPLE_RATE, OUTPUT_CHANNEL_COUNT), _outgoingAvatarAudioSequenceNumber(0), _audioOutputIODevice(_localInjectorsStream, _receivedAudioStream, this), @@ -210,13 +225,14 @@ AudioClient::AudioClient() : // start a thread to detect any device changes _checkDevicesThread = new CheckDevicesThread(this); - _checkDevicesThread->setObjectName("CheckDevices Thread"); + _checkDevicesThread->setObjectName("AudioClient CheckDevices Thread"); _checkDevicesThread->setPriority(QThread::LowPriority); _checkDevicesThread->start(); // start a thread to process local injectors - _localAudioThread.setObjectName("LocalAudio Thread"); - _localAudioThread.start(); + _localInjectorsThread = new LocalInjectorsThread(this); + _localInjectorsThread->setObjectName("AudioClient LocalInjectors Thread"); + _localInjectorsThread->start(); configureReverb(); @@ -231,18 +247,23 @@ AudioClient::AudioClient() : } AudioClient::~AudioClient() { - delete _checkDevicesThread; - stop(); if (_codec && _encoder) { _codec->releaseEncoder(_encoder); _encoder = nullptr; } } -void AudioClient::beforeAboutToQuit() { - static_cast(_checkDevicesThread)->beforeAboutToQuit(); -} +void AudioClient::customDeleter() { + stop(); // synchronously + static_cast(_checkDevicesThread)->join(); + delete _checkDevicesThread; + + static_cast(_localInjectorsThread)->join(); + delete _localInjectorsThread; + + deleteLater(); // asynchronously +} void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) { qCDebug(audioclient) << __FUNCTION__ << "sendingNode:" << *node << "currentCodec:" << currentCodec << "recievedCodec:" << recievedCodec; @@ -1527,8 +1548,8 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice _outputScratchBuffer = new int16_t[_outputPeriod]; // size local output mix buffer based on resampled network frame size - _networkPeriod = _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO); - _localOutputMixBuffer = new float[_networkPeriod]; + int networkPeriod = _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO); + _localOutputMixBuffer = new float[networkPeriod]; int localPeriod = _outputPeriod * 2; _localInjectorsStream.resizeForFrameSize(localPeriod); @@ -1691,7 +1712,7 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { } // prepare injectors for the next callback - QMetaObject::invokeMethod(&_audio->_localAudioThread, "prepare", Qt::QueuedConnection); + QMetaObject::invokeMethod(_audio->_localInjectorsThread, "prepare", Qt::QueuedConnection); int samplesPopped = std::max(networkSamplesPopped, injectorSamplesPopped); int framesPopped = samplesPopped / AudioConstants::STEREO; diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 139749e8e8..6e69915f0a 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -71,19 +71,6 @@ class QIODevice; class Transform; class NLPacket; -class AudioInjectorsThread : public QThread { - Q_OBJECT - -public: - AudioInjectorsThread(AudioClient* audio) : _audio(audio) {} - -public slots : - void prepare(); - -private: - AudioClient* _audio; -}; - class AudioClient : public AbstractAudioInterface, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -186,8 +173,6 @@ public slots: void audioMixerKilled(); void toggleMute(); - void beforeAboutToQuit(); - virtual void setIsStereoInput(bool stereo) override; void toggleAudioNoiseReduction() { _isNoiseGateEnabled = !_isNoiseGateEnabled; } @@ -244,9 +229,7 @@ protected: AudioClient(); ~AudioClient(); - virtual void customDeleter() override { - deleteLater(); - } + virtual void customDeleter() override; private: void outputFormatChanged(); @@ -339,19 +322,17 @@ private: // for network audio (used by network audio thread) int16_t _networkScratchBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_AMBISONIC]; - // for local audio (used by audio injectors thread) - int _networkPeriod { 0 }; - float _localMixBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO]; - int16_t _localScratchBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_AMBISONIC]; - float* _localOutputMixBuffer { NULL }; - AudioInjectorsThread _localAudioThread; - RecursiveMutex _localAudioMutex; - // for output audio (used by this thread) int _outputPeriod { 0 }; float* _outputMixBuffer { NULL }; int16_t* _outputScratchBuffer { NULL }; + // for local audio (used by audio injectors thread) + float _localMixBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO]; + int16_t _localScratchBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_AMBISONIC]; + float* _localOutputMixBuffer { NULL }; + RecursiveMutex _localAudioMutex; + AudioLimiter _audioLimiter; // Adds Reverb @@ -394,12 +375,13 @@ private: QString _selectedCodecName; Encoder* _encoder { nullptr }; // for outbound mic stream - QThread* _checkDevicesThread { nullptr }; - RateCounter<> _silentOutbound; RateCounter<> _audioOutbound; RateCounter<> _silentInbound; RateCounter<> _audioInbound; + + QThread* _checkDevicesThread { nullptr }; + QThread* _localInjectorsThread { nullptr }; }; From 4a26785eda43c42879d5758c5e1110d6005cf46e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 24 Apr 2017 18:21:27 -0400 Subject: [PATCH 02/32] cleanup Audio bg threads in cleanupBeforeQuit --- interface/src/Application.cpp | 3 ++- libraries/audio-client/src/AudioClient.cpp | 21 +++++++++++++++------ libraries/audio-client/src/AudioClient.h | 1 + 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c94b1bbd2f..ff6f85c8b2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1785,7 +1785,8 @@ void Application::cleanupBeforeQuit() { // FIXME: something else is holding a reference to AudioClient, // so it must be explicitly synchronously stopped here - QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::BlockingQueuedConnection); + QMetaObject::invokeMethod(DependencyManager::get().data(), + "cleanupBeforeQuit", Qt::BlockingQueuedConnection); // destroy Audio so it and its threads have a chance to go down safely // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 6107fef516..fbb578f560 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -254,15 +254,24 @@ AudioClient::~AudioClient() { } void AudioClient::customDeleter() { - stop(); // synchronously + deleteLater(); +} - static_cast(_checkDevicesThread)->join(); - delete _checkDevicesThread; +void AudioClient::cleanupBeforeQuit() { + // FIXME: this should be put in customDeleter, but there is still a reference to this when it is called, + // so this must be explicitly, synchronously stopped - static_cast(_localInjectorsThread)->join(); - delete _localInjectorsThread; + stop(); - deleteLater(); // asynchronously + if (_checkDevicesThread) { + static_cast(_checkDevicesThread)->join(); + delete _checkDevicesThread; + } + + if (_localInjectorsThread) { + static_cast(_localInjectorsThread)->join(); + delete _localInjectorsThread; + } } void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) { diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 6e69915f0a..f3038b4d62 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -158,6 +158,7 @@ public: public slots: void start(); void stop(); + void cleanupBeforeQuit(); void handleAudioEnvironmentDataPacket(QSharedPointer message); void handleAudioDataPacket(QSharedPointer message); From c27dd446ebfdfd2654f0993fe970b1ff437988ce Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 25 Apr 2017 14:59:30 -0400 Subject: [PATCH 03/32] rename to standard --- libraries/audio-client/src/AudioClient.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index fbb578f560..9e1195e460 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -90,29 +90,29 @@ public: CheckDevicesThread(AudioClient* client) : BackgroundThread(client) {} void join() override { - _quit = true; - std::unique_lock lock(mutex); - cv.wait(lock, [&]{ return !running; }); + _shouldQuit = true; + std::unique_lock lock(_joinMutex); + _joinCondition.wait(lock, [&]{ return !_isRunning; }); } protected: void run() override { - while (!_quit) { + while (!_shouldQuit) { _client->checkDevices(); const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; QThread::msleep(DEVICE_CHECK_INTERVAL_MSECS); } - std::lock_guard lock(mutex); - running = false; - cv.notify_one(); + std::lock_guard lock(_joinCondition); + _isRunning = false; + _joinCondition.notify_one(); } private: - std::atomic _quit { false }; - bool running { true }; - std::mutex mutex; - std::condition_variable cv; + std::atomic _shouldQuit { false }; + bool _isRunning { true }; + std::mutex _joinMutex; + std::condition_variable _joinCondition; }; // background thread buffering local injectors From e9c5b8600367be234126f979088fd60ffe7789a5 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 25 Apr 2017 16:02:43 -0400 Subject: [PATCH 04/32] use mutex, not cv --- libraries/audio-client/src/AudioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 9e1195e460..2c78fbceca 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -103,7 +103,7 @@ protected: const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; QThread::msleep(DEVICE_CHECK_INTERVAL_MSECS); } - std::lock_guard lock(_joinCondition); + std::lock_guard lock(_joinMutex); _isRunning = false; _joinCondition.notify_one(); } From 15cad1fee914264de3e7a084f499efd813dbfe3e Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 2 May 2017 21:33:58 +0100 Subject: [PATCH 05/32] saving work --- plugins/openvr/src/ViveControllerManager.cpp | 72 +++++++++++++++++++- plugins/openvr/src/ViveControllerManager.h | 16 ++++- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 86b37135d2..293885f8ee 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -10,6 +10,7 @@ // #include "ViveControllerManager.h" +#include #include #include @@ -41,9 +42,16 @@ static const char* MENU_PARENT = "Avatar"; static const char* MENU_NAME = "Vive Controllers"; static const char* MENU_PATH = "Avatar" ">" "Vive Controllers"; static const char* RENDER_CONTROLLERS = "Render Hand Controllers"; +const quint64 CALIBRATION_TIMELAPSE = 3000000; const char* ViveControllerManager::NAME { "OpenVR" }; +bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { + controller::Pose firstPose = firstPuck.second; + controller::Pose secondPose = secondPuck.second; + return (firstPose.translation.y < secondPose.translation.y); +} + bool ViveControllerManager::isSupported() const { return openVrSupported(); } @@ -125,6 +133,7 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu void ViveControllerManager::InputDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { _poseStateMap.clear(); _buttonPressedMap.clear(); + _validTrackedObjects.clear(); // While the keyboard is open, we defer strictly to the keyboard values if (isOpenVrKeyboardShown()) { @@ -164,10 +173,10 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle numTrackedControllers++; } _trackedControllers = numTrackedControllers; + calibrate(inputCalibrationData); } void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) { - uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex; if (_system->IsTrackedDeviceConnected(deviceIndex) && @@ -185,12 +194,71 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde // transform into avatar frame glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; _poseStateMap[poseIndex] = pose.transform(controllerToAvatar); + _validTrackedObjects.push_back(std::make_pair(poseIndex, _poseStateMap[poseIndex])); } else { controller::Pose invalidPose; _poseStateMap[poseIndex] = invalidPose; } } +void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { + quint64 currentTime = usecTimestampNow(); + + auto leftTrigger = _buttonPressedMap.find(controller::LT); + auto rightTrigger = _buttonPressedMap.find(controller::RT); + if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { + if (!_calibrated) { + auto puckCount = _validTrackedObjects.size(); + if (puckCount == 2) { + qDebug() << "-------------< configure feet <-------------"; + _config = Config::Feet; + } else if (puckCount == 3) { + qDebug() << "-------------> configure feet and hips <-------------"; + _config = Config::FeetAndHips; + } else if (puckCount >= 4) { + _config = Config::FeetHipsAndChest; + } else { + qDebug() << "Could not configure # pucks " << puckCount; + return; + } + + std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); + auto firstFoot = _validTrackedObjects[0]; + auto secondFoot = _validTrackedObjects[1]; + controller::Pose firstFootPose = firstFoot.second; + controller::Pose secondFootPose = secondFoot.second; + if (firstFootPose.translation.x > secondFootPose.translation.x) { + _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; + _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; + } else { + _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; + _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; + + } + + if (_config == Config::Feet) { + // done + } else if (_config == Config::FeetAndHips) { + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + } else if (_config == Config::FeetHipsAndChest) { + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[2].first; + } + + computePucksOffset(inputCalibration); + _calibrated = true; + + } else { + qDebug() << "---- de-calibrated ---"; + + } + + } +} + +void ViveControllerManager::InputDevice::computePucksOffset(const controller::InputCalibrationData& inputCalibration) { + +} void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) { if (_system->IsTrackedDeviceConnected(deviceIndex) && @@ -353,7 +421,7 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef float hapticTime = strength * MAX_HAPTIC_TIME; if (hapticTime < duration * 1000.0f) { _system->TriggerHapticPulse(deviceIndex, 0, hapticTime); - } + } float remainingHapticTime = duration - (hapticTime / 1000.0f + deltaTime * 1000.0f); // in milliseconds if (leftHand) { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index dc1883d5e4..5d844b6499 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -14,9 +14,11 @@ #include #include +#include +#include +#include #include - #include #include #include @@ -58,7 +60,8 @@ private: bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; void hapticsHelper(float deltaTime, bool leftHand); - + void calibrate(const controller::InputCalibrationData& inputCalibration); + void computePucksOffset(const controller::InputCalibrationData& inputCalibration); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); @@ -90,10 +93,14 @@ private: float _timer { 0.0f }; glm::vec2 _stick { 0.0f, 0.0f }; }; - + enum class Config { Feet, FeetAndHips, FeetHipsAndChest, NoConfig }; + Config _config { Config::NoConfig }; FilteredStick _filteredLeftStick; FilteredStick _filteredRightStick; + std::vector> _validTrackedObjects; + std::map _pucksOffset; + std::map _jointToPuckMap; // perform an action when the InputDevice mutex is acquired. using Locker = std::unique_lock; template @@ -101,10 +108,13 @@ private: int _trackedControllers { 0 }; vr::IVRSystem*& _system; + quint64 _calibrateAfterTimelapse { 0.f }; float _leftHapticStrength { 0.0f }; float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; float _rightHapticDuration { 0.0f }; + bool _calibrate { false }; + bool _calibrated { false }; mutable std::recursive_mutex _lock; friend class ViveControllerManager; From 8e2b25eacc80c8da62f80cb52dff03c0ecd309b2 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 3 May 2017 00:25:41 +0100 Subject: [PATCH 06/32] working on computing offsets --- plugins/openvr/src/ViveControllerManager.cpp | 34 +++++++++++++++----- plugins/openvr/src/ViveControllerManager.h | 3 +- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 293885f8ee..73cb26410c 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -46,6 +47,16 @@ const quint64 CALIBRATION_TIMELAPSE = 3000000; const char* ViveControllerManager::NAME { "OpenVR" }; +/*glm::mat4 computeDefualtHead(glm::mat4 centerOfEye, glm::mat4 jointHead) { + headOffset = glm::muliply(glm::inverse(centerOfEye), jointHead); + return glm:: + }*/ + +glm::mat4 computeOffset(glm::mat4 defaultRefrence, glm::mat4 defaultJointMat, controller::Pose puckPose) { + qDebug() << "-------------> computing offset <-------------"; + glm::mat4 puckMat = create + return mat4(); +} bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { controller::Pose firstPose = firstPuck.second; controller::Pose secondPose = secondPuck.second; @@ -203,11 +214,17 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { quint64 currentTime = usecTimestampNow(); - + auto leftTrigger = _buttonPressedMap.find(controller::LT); auto rightTrigger = _buttonPressedMap.find(controller::RT); if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { if (!_calibrated) { + glm::mat4 controllerToAvatar = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; + glm::mat4 currentHead = inputCalibration.hmdSensorMat * controllerToAvatar; + glm::quat canceledRollAndPitch = cancelOutRollAndPitch(glmExtractRotation(currentHead)); + glm::vec3 currentHeadPosition = extractTranslation(currentHead); + currentHead = createMatFromQuatAndPos(canceledRollAndPitch, currentHeadPosition); + glm::mat4 defaultRefrenceXform = currentHead * glm::inverse(inputCalibration.defaultHeadMat); auto puckCount = _validTrackedObjects.size(); if (puckCount == 2) { qDebug() << "-------------< configure feet <-------------"; @@ -229,23 +246,27 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr controller::Pose secondFootPose = secondFoot.second; if (firstFootPose.translation.x > secondFootPose.translation.x) { _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, firstFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, secondFootPose); } else { _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, secondFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; - + _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, firstFootPose); } if (_config == Config::Feet) { // done } else if (_config == Config::FeetAndHips) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); } else if (_config == Config::FeetHipsAndChest) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[2].first; - } - - computePucksOffset(inputCalibration); + _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); + } _calibrated = true; } else { @@ -256,9 +277,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr } } -void ViveControllerManager::InputDevice::computePucksOffset(const controller::InputCalibrationData& inputCalibration) { - -} void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) { if (_system->IsTrackedDeviceConnected(deviceIndex) && diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 5d844b6499..966f1e879b 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -61,7 +61,6 @@ private: bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; void hapticsHelper(float deltaTime, bool leftHand); void calibrate(const controller::InputCalibrationData& inputCalibration); - void computePucksOffset(const controller::InputCalibrationData& inputCalibration); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); @@ -99,7 +98,7 @@ private: FilteredStick _filteredRightStick; std::vector> _validTrackedObjects; - std::map _pucksOffset; + std::map _pucksOffset; std::map _jointToPuckMap; // perform an action when the InputDevice mutex is acquired. using Locker = std::unique_lock; From fb502a7fede162834a1c7e495b805efb6f1a02ac Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 3 May 2017 00:37:35 +0100 Subject: [PATCH 07/32] add offset function --- plugins/openvr/src/ViveControllerManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 73cb26410c..29d036fd31 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -54,8 +54,9 @@ const char* ViveControllerManager::NAME { "OpenVR" }; glm::mat4 computeOffset(glm::mat4 defaultRefrence, glm::mat4 defaultJointMat, controller::Pose puckPose) { qDebug() << "-------------> computing offset <-------------"; - glm::mat4 puckMat = create - return mat4(); + glm::mat4 poseMat = createMatFromQuatAndPos(puckPose.rotation, puckPose.translation); + glm::mat4 refrenceJointMat = defaultRefrence * defaultJointMat; + return glm::inverse(poseMat) * refrenceJointMat; } bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { controller::Pose firstPose = firstPuck.second; @@ -221,10 +222,11 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if (!_calibrated) { glm::mat4 controllerToAvatar = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; glm::mat4 currentHead = inputCalibration.hmdSensorMat * controllerToAvatar; + glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; glm::quat canceledRollAndPitch = cancelOutRollAndPitch(glmExtractRotation(currentHead)); glm::vec3 currentHeadPosition = extractTranslation(currentHead); currentHead = createMatFromQuatAndPos(canceledRollAndPitch, currentHeadPosition); - glm::mat4 defaultRefrenceXform = currentHead * glm::inverse(inputCalibration.defaultHeadMat); + glm::mat4 defaultRefrenceXform = currentHead * defaultHeadOffset; auto puckCount = _validTrackedObjects.size(); if (puckCount == 2) { qDebug() << "-------------< configure feet <-------------"; From 31f6038e457586d6ceaafb94b8e6eff55d8b45c7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 3 May 2017 20:08:42 +0100 Subject: [PATCH 08/32] limbs tracking pucks --- interface/resources/controllers/vive.json | 6 ++- plugins/openvr/src/ViveControllerManager.cpp | 57 ++++++++++++++++---- plugins/openvr/src/ViveControllerManager.h | 2 + 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/interface/resources/controllers/vive.json b/interface/resources/controllers/vive.json index 4fbdb37abf..5bdffadbbf 100644 --- a/interface/resources/controllers/vive.json +++ b/interface/resources/controllers/vive.json @@ -35,6 +35,10 @@ { "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" }, { "from": "Vive.LeftHand", "to": "Standard.LeftHand", "when": [ "Application.InHMD" ] }, - { "from": "Vive.RightHand", "to": "Standard.RightHand", "when": [ "Application.InHMD" ] } + { "from": "Vive.RightHand", "to": "Standard.RightHand", "when": [ "Application.InHMD" ] }, + { "from": "Vive.LeftFoot", "to" : "Standard.LeftFoot", "when": [ "Application.InHMD"] }, + { "from": "Vive.RightFoot", "to" : "Standard.RightFoot", "when": [ "Application.InHMD"] }, + { "from": "Vive.Hips", "to" : "Standard.Hips", "when": [ "Application.InHMD"] }, + { "from": "Vive.Spine2", "to" : "Standard.Spine2", "when": [ "Application.InHMD"] } ] } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 29d036fd31..1a1f6b0977 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -53,7 +53,7 @@ const char* ViveControllerManager::NAME { "OpenVR" }; }*/ glm::mat4 computeOffset(glm::mat4 defaultRefrence, glm::mat4 defaultJointMat, controller::Pose puckPose) { - qDebug() << "-------------> computing offset <-------------"; + ///qDebug() << "-------------> computing offset <-------------"; glm::mat4 poseMat = createMatFromQuatAndPos(puckPose.rotation, puckPose.translation); glm::mat4 refrenceJointMat = defaultRefrence * defaultJointMat; return glm::inverse(poseMat) * refrenceJointMat; @@ -134,6 +134,7 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu userInputMapper->removeDevice(_inputDevice->_deviceID); _registeredWithInputMapper = false; _inputDevice->_poseStateMap.clear(); + //qDebug() << " ----------->>!!!!!!! clear pose state map !!!!!!!<<----------------"; } if (!_registeredWithInputMapper && _inputDevice->_trackedControllers > 0) { @@ -186,6 +187,7 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle } _trackedControllers = numTrackedControllers; calibrate(inputCalibrationData); + updateCalibratedLimbs(); } void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) { @@ -220,21 +222,28 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr auto rightTrigger = _buttonPressedMap.find(controller::RT); if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { if (!_calibrated) { + // conver the hmd head from sensor space to avatar space glm::mat4 controllerToAvatar = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; - glm::mat4 currentHead = inputCalibration.hmdSensorMat * controllerToAvatar; + glm::mat4 hmdHeadInAvatarSpace = inputCalibration.hmdSensorMat * controllerToAvatar; + + // cancel the roll and pitch for the hmd head + glm::quat canceledRollAndPitch = cancelOutRollAndPitch(glmExtractRotation(hmdHeadInAvatarSpace)); + glm::vec3 hmdHeadPosition = extractTranslation(hmdHeadInAvatarSpace); + glm::mat4 hmdHeadMat = createMatFromQuatAndPos(canceledRollAndPitch, hmdHeadPosition); + + //calculate the offset from the centerEye to the head hoint glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; - glm::quat canceledRollAndPitch = cancelOutRollAndPitch(glmExtractRotation(currentHead)); - glm::vec3 currentHeadPosition = extractTranslation(currentHead); - currentHead = createMatFromQuatAndPos(canceledRollAndPitch, currentHeadPosition); - glm::mat4 defaultRefrenceXform = currentHead * defaultHeadOffset; + + glm::mat4 defaultRefrenceXform = hmdHeadMat * defaultHeadOffset; auto puckCount = _validTrackedObjects.size(); if (puckCount == 2) { - qDebug() << "-------------< configure feet <-------------"; + //qDebug() << "-------------< configure feet <-------------"; _config = Config::Feet; } else if (puckCount == 3) { - qDebug() << "-------------> configure feet and hips <-------------"; + //qDebug() << "-------------> configure feet and hips <-------------"; _config = Config::FeetAndHips; } else if (puckCount >= 4) { + //qDebug() << "-------------> configure feet, hips and chest <---------------"; _config = Config::FeetHipsAndChest; } else { qDebug() << "Could not configure # pucks " << puckCount; @@ -242,17 +251,19 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr } std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); + auto firstFoot = _validTrackedObjects[0]; auto secondFoot = _validTrackedObjects[1]; controller::Pose firstFootPose = firstFoot.second; controller::Pose secondFootPose = secondFoot.second; - if (firstFootPose.translation.x > secondFootPose.translation.x) { + if (firstFootPose.translation.x < secondFootPose.translation.x) { _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, firstFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, secondFootPose); } else { _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; + qDebug() << " --------> Printing out the offset pose <------------"; _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, secondFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, firstFootPose); @@ -266,7 +277,7 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr } else if (_config == Config::FeetHipsAndChest) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); - _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[2].first; + _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); } _calibrated = true; @@ -279,6 +290,28 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr } } +void ViveControllerManager::InputDevice::updateCalibratedLimbs() { + _poseStateMap[controller::LEFT_FOOT] = addOffsetToPuckPose(controller::LEFT_FOOT); + _poseStateMap[controller::RIGHT_FOOT] = addOffsetToPuckPose(controller::RIGHT_FOOT); + _poseStateMap[controller::HIPS] = addOffsetToPuckPose(controller::HIPS); + _poseStateMap[controller::SPINE2] = addOffsetToPuckPose(controller::SPINE2); +} + +controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(int joint) { + auto puck = _jointToPuckMap.find(joint); + if (puck != _jointToPuckMap.end()) { + uint32_t puckIndex = puck->second; + controller::Pose puckPose = _poseStateMap[puckIndex]; + glm::mat4 puckOffset = _pucksOffset[puckIndex]; + puckPose.postTransform(puckOffset); + //qDebug() << "-----------> adding offset to puck <-------------- " << puckPose.valid; + return puckPose; + + } + //qDebug() << "---------> joint is not mapped to any thing <--------------"; + return controller::Pose(); +} + void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) { if (_system->IsTrackedDeviceConnected(deviceIndex) && @@ -492,6 +525,10 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI // 3d location of controller makePair(LEFT_HAND, "LeftHand"), makePair(RIGHT_HAND, "RightHand"), + makePair(LEFT_FOOT, "LeftFoot"), + makePair(RIGHT_FOOT, "RightFoot"), + makePair(HIPS, "Hips"), + makePair(SPINE2, "Spine2"), // 16 tracked poses makePair(TRACKED_OBJECT_00, "TrackedObject00"), diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 966f1e879b..43dd982f80 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -61,6 +61,8 @@ private: bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; void hapticsHelper(float deltaTime, bool leftHand); void calibrate(const controller::InputCalibrationData& inputCalibration); + controller::Pose addOffsetToPuckPose(int joint); + void updateCalibratedLimbs(); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); From 20c8356bb2b1e7e292f8783a5d5014774edeb43a Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 5 May 2017 22:55:53 +0100 Subject: [PATCH 09/32] debugging rotation fix --- plugins/openvr/src/ViveControllerManager.cpp | 72 ++++++++++++++++---- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 1a1f6b0977..8d480a8e6d 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -1,6 +1,4 @@ -// -// ViveControllerManager.cpp -// input-plugins/src/input-plugins + // // Created by Sam Gondelman on 6/29/15. // Copyright 2013 High Fidelity, Inc. @@ -23,6 +21,9 @@ #include #include #include +#include +#include +#include #include @@ -52,11 +53,11 @@ const char* ViveControllerManager::NAME { "OpenVR" }; return glm:: }*/ -glm::mat4 computeOffset(glm::mat4 defaultRefrence, glm::mat4 defaultJointMat, controller::Pose puckPose) { +glm::mat4 computeOffset(glm::mat4 defaultToRefrenceMat, glm::mat4 defaultJointMat, controller::Pose puckPose) { ///qDebug() << "-------------> computing offset <-------------"; glm::mat4 poseMat = createMatFromQuatAndPos(puckPose.rotation, puckPose.translation); - glm::mat4 refrenceJointMat = defaultRefrence * defaultJointMat; - return glm::inverse(poseMat) * refrenceJointMat; + glm::mat4 refrenceJointMat = defaultToRefrenceMat * defaultJointMat; + return ( glm::inverse(poseMat) * refrenceJointMat); } bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { controller::Pose firstPose = firstPuck.second; @@ -64,6 +65,12 @@ bool sortPucksYPosition(std::pair firstPuck, std::pa return (firstPose.translation.y < secondPose.translation.y); } +void printPose(controller::Pose pose) { + qDebug() << "-------------> printing out controller::Pose <--------------"; + qDebug() << QString::fromStdString(glm::to_string(pose.translation)); + qDebug() << QString::fromStdString(glm::to_string(pose.rotation)); +} + bool ViveControllerManager::isSupported() const { return openVrSupported(); } @@ -223,18 +230,40 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { if (!_calibrated) { // conver the hmd head from sensor space to avatar space - glm::mat4 controllerToAvatar = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; - glm::mat4 hmdHeadInAvatarSpace = inputCalibration.hmdSensorMat * controllerToAvatar; + qDebug() << " -------------------> begin:::InputDevice::calibrate <--------------------"; + glm::mat4 worldToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; + glm::mat4 hmdHeadInAvatarSpace = worldToAvatarMat * inputCalibration.hmdSensorMat; // cancel the roll and pitch for the hmd head glm::quat canceledRollAndPitch = cancelOutRollAndPitch(glmExtractRotation(hmdHeadInAvatarSpace)); glm::vec3 hmdHeadPosition = extractTranslation(hmdHeadInAvatarSpace); glm::mat4 hmdHeadMat = createMatFromQuatAndPos(canceledRollAndPitch, hmdHeadPosition); + glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + glm::mat4 defaultRefrenceXform = hmdHeadMat * defaultHeadOffset; + + glm::quat tmpHmdHeadRotation = glmExtractRotation(hmdHeadMat); + /*qDebug() << "----------- hmd head position < ------"; + qDebug() << QString::fromStdString(glm::to_string(hmdHeadPosition)); + qDebug() << "<--------------- hmd head roatation <---------"; + qDebug() << QString::fromStdString(glm::to_string(canceledRollAndPitch));*/ //calculate the offset from the centerEye to the head hoint - glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + //glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + glm::vec3 tmpHeadOffsetPosition = extractTranslation(defaultHeadOffset); + glm::quat tmpHeadOffsetRotation = glmExtractRotation(defaultHeadOffset); + + /*qDebug() << "----------------> head offset position <------------------"; + qDebug() << QString::fromStdString(glm::to_string(tmpHeadOffsetPosition)); + qDebug() << "---------------> head offset rotation <-----------------"; + qDebug() << QString::fromStdString(glm::to_string(tmpHeadOffsetRotation));*/ + + glm::vec3 defaultRefrencePosition = extractTranslation(defaultRefrenceXform); + glm::quat defaultRefrenceRotation = glmExtractRotation(defaultRefrenceXform); + qDebug() << "----------------> defaultToReference position <------------------"; + qDebug() << QString::fromStdString(glm::to_string(defaultRefrencePosition)); + qDebug() << "---------------> defaultToReference rotation <-----------------"; + qDebug() << QString::fromStdString(glm::to_string(defaultRefrenceRotation)); - glm::mat4 defaultRefrenceXform = hmdHeadMat * defaultHeadOffset; auto puckCount = _validTrackedObjects.size(); if (puckCount == 2) { //qDebug() << "-------------< configure feet <-------------"; @@ -246,7 +275,7 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr //qDebug() << "-------------> configure feet, hips and chest <---------------"; _config = Config::FeetHipsAndChest; } else { - qDebug() << "Could not configure # pucks " << puckCount; + //qDebug() << "Could not configure # pucks " << puckCount; return; } @@ -258,18 +287,33 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr controller::Pose secondFootPose = secondFoot.second; if (firstFootPose.translation.x < secondFootPose.translation.x) { _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; + + qDebug() << " --------> Printing out the offset pose <------------"; + glm::mat4 offset = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, firstFootPose); + qDebug() << "----------------> offset Position <------------------"; + qDebug() << QString::fromStdString(glm::to_string(extractTranslation(offset))); + qDebug() << "---------------> offset rotation <-----------------"; + qDebug() << QString::fromStdString(glm::to_string(glmExtractRotation(offset))); _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, firstFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, secondFootPose); } else { _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; qDebug() << " --------> Printing out the offset pose <------------"; + glm::mat4 offset = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, secondFootPose); + qDebug() << "----------------> offset Position <------------------"; + qDebug() << QString::fromStdString(glm::to_string(extractTranslation(offset))); + qDebug() << "---------------> offset rotation <-----------------"; + qDebug() << QString::fromStdString(glm::to_string(glmExtractRotation(offset))); _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, secondFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, firstFootPose); } if (_config == Config::Feet) { + controller::Pose leftPose = addOffsetToPuckPose(controller::LEFT_FOOT); + qDebug() << "------------> InputDevice::updateCalibratedLimbs <---------"; + printPose(leftPose); // done } else if (_config == Config::FeetAndHips) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; @@ -279,7 +323,8 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); - } + } + qDebug() << "-------------------> end:::InputDevice::calibrate <--------------------"; _calibrated = true; } else { @@ -292,6 +337,9 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr void ViveControllerManager::InputDevice::updateCalibratedLimbs() { _poseStateMap[controller::LEFT_FOOT] = addOffsetToPuckPose(controller::LEFT_FOOT); + controller::Pose leftPose = addOffsetToPuckPose(controller::LEFT_FOOT); + //qDebug() << "------------> InputDevice::updateCalibratedLimbs <---------"; + //printPose(leftPose); _poseStateMap[controller::RIGHT_FOOT] = addOffsetToPuckPose(controller::RIGHT_FOOT); _poseStateMap[controller::HIPS] = addOffsetToPuckPose(controller::HIPS); _poseStateMap[controller::SPINE2] = addOffsetToPuckPose(controller::SPINE2); From 8813306857fd864d98998391bfdbd0a2154842b9 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 5 May 2017 23:59:38 +0100 Subject: [PATCH 10/32] fixed the wierd rotation issue --- plugins/openvr/src/ViveControllerManager.cpp | 62 +++----------------- 1 file changed, 9 insertions(+), 53 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 8d480a8e6d..fffdb7cd33 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -230,52 +230,30 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { if (!_calibrated) { // conver the hmd head from sensor space to avatar space - qDebug() << " -------------------> begin:::InputDevice::calibrate <--------------------"; glm::mat4 worldToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; - glm::mat4 hmdHeadInAvatarSpace = worldToAvatarMat * inputCalibration.hmdSensorMat; + glm::mat4 hmdAvatarMat = worldToAvatarMat * inputCalibration.hmdSensorMat; // cancel the roll and pitch for the hmd head - glm::quat canceledRollAndPitch = cancelOutRollAndPitch(glmExtractRotation(hmdHeadInAvatarSpace)); - glm::vec3 hmdHeadPosition = extractTranslation(hmdHeadInAvatarSpace); - glm::mat4 hmdHeadMat = createMatFromQuatAndPos(canceledRollAndPitch, hmdHeadPosition); + glm::quat hmdRotation = cancelOutRollAndPitch(glmExtractRotation(hmdAvatarMat)); + glm::vec3 hmdTranslation = extractTranslation(hmdAvatarMat); + glm::mat4 currentHead = createMatFromQuatAndPos(hmdRotation, hmdTranslation); + + // calculate the offset from the centerOfEye to defaultHeadMat glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; - glm::mat4 defaultRefrenceXform = hmdHeadMat * defaultHeadOffset; - - glm::quat tmpHmdHeadRotation = glmExtractRotation(hmdHeadMat); - /*qDebug() << "----------- hmd head position < ------"; - qDebug() << QString::fromStdString(glm::to_string(hmdHeadPosition)); - qDebug() << "<--------------- hmd head roatation <---------"; - qDebug() << QString::fromStdString(glm::to_string(canceledRollAndPitch));*/ - //calculate the offset from the centerEye to the head hoint - //glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; - glm::vec3 tmpHeadOffsetPosition = extractTranslation(defaultHeadOffset); - glm::quat tmpHeadOffsetRotation = glmExtractRotation(defaultHeadOffset); - - /*qDebug() << "----------------> head offset position <------------------"; - qDebug() << QString::fromStdString(glm::to_string(tmpHeadOffsetPosition)); - qDebug() << "---------------> head offset rotation <-----------------"; - qDebug() << QString::fromStdString(glm::to_string(tmpHeadOffsetRotation));*/ + currentHead *= defaultHeadOffset; - glm::vec3 defaultRefrencePosition = extractTranslation(defaultRefrenceXform); - glm::quat defaultRefrenceRotation = glmExtractRotation(defaultRefrenceXform); - qDebug() << "----------------> defaultToReference position <------------------"; - qDebug() << QString::fromStdString(glm::to_string(defaultRefrencePosition)); - qDebug() << "---------------> defaultToReference rotation <-----------------"; - qDebug() << QString::fromStdString(glm::to_string(defaultRefrenceRotation)); + // calculate the defaultToRefrenceXform + glm::mat4 defaultRefrenceXform = currentHead * glm::inverse(inputCalibration.defaultHeadMat); auto puckCount = _validTrackedObjects.size(); if (puckCount == 2) { - //qDebug() << "-------------< configure feet <-------------"; _config = Config::Feet; } else if (puckCount == 3) { - //qDebug() << "-------------> configure feet and hips <-------------"; _config = Config::FeetAndHips; } else if (puckCount >= 4) { - //qDebug() << "-------------> configure feet, hips and chest <---------------"; _config = Config::FeetHipsAndChest; } else { - //qDebug() << "Could not configure # pucks " << puckCount; return; } @@ -287,24 +265,11 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr controller::Pose secondFootPose = secondFoot.second; if (firstFootPose.translation.x < secondFootPose.translation.x) { _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; - - qDebug() << " --------> Printing out the offset pose <------------"; - glm::mat4 offset = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, firstFootPose); - qDebug() << "----------------> offset Position <------------------"; - qDebug() << QString::fromStdString(glm::to_string(extractTranslation(offset))); - qDebug() << "---------------> offset rotation <-----------------"; - qDebug() << QString::fromStdString(glm::to_string(glmExtractRotation(offset))); _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, firstFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, secondFootPose); } else { _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; - qDebug() << " --------> Printing out the offset pose <------------"; - glm::mat4 offset = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, secondFootPose); - qDebug() << "----------------> offset Position <------------------"; - qDebug() << QString::fromStdString(glm::to_string(extractTranslation(offset))); - qDebug() << "---------------> offset rotation <-----------------"; - qDebug() << QString::fromStdString(glm::to_string(glmExtractRotation(offset))); _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, secondFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, firstFootPose); @@ -312,7 +277,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if (_config == Config::Feet) { controller::Pose leftPose = addOffsetToPuckPose(controller::LEFT_FOOT); - qDebug() << "------------> InputDevice::updateCalibratedLimbs <---------"; printPose(leftPose); // done } else if (_config == Config::FeetAndHips) { @@ -324,12 +288,9 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); } - qDebug() << "-------------------> end:::InputDevice::calibrate <--------------------"; _calibrated = true; } else { - qDebug() << "---- de-calibrated ---"; - } } @@ -337,9 +298,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr void ViveControllerManager::InputDevice::updateCalibratedLimbs() { _poseStateMap[controller::LEFT_FOOT] = addOffsetToPuckPose(controller::LEFT_FOOT); - controller::Pose leftPose = addOffsetToPuckPose(controller::LEFT_FOOT); - //qDebug() << "------------> InputDevice::updateCalibratedLimbs <---------"; - //printPose(leftPose); _poseStateMap[controller::RIGHT_FOOT] = addOffsetToPuckPose(controller::RIGHT_FOOT); _poseStateMap[controller::HIPS] = addOffsetToPuckPose(controller::HIPS); _poseStateMap[controller::SPINE2] = addOffsetToPuckPose(controller::SPINE2); @@ -352,11 +310,9 @@ controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(int joi controller::Pose puckPose = _poseStateMap[puckIndex]; glm::mat4 puckOffset = _pucksOffset[puckIndex]; puckPose.postTransform(puckOffset); - //qDebug() << "-----------> adding offset to puck <-------------- " << puckPose.valid; return puckPose; } - //qDebug() << "---------> joint is not mapped to any thing <--------------"; return controller::Pose(); } From a744db56aaebb7ad27c9a5ea697e69e8e22e9258 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Sat, 6 May 2017 00:21:52 +0100 Subject: [PATCH 11/32] removed dead code --- plugins/openvr/src/ViveControllerManager.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index fffdb7cd33..ff6edccf9f 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -48,29 +48,18 @@ const quint64 CALIBRATION_TIMELAPSE = 3000000; const char* ViveControllerManager::NAME { "OpenVR" }; -/*glm::mat4 computeDefualtHead(glm::mat4 centerOfEye, glm::mat4 jointHead) { - headOffset = glm::muliply(glm::inverse(centerOfEye), jointHead); - return glm:: - }*/ - glm::mat4 computeOffset(glm::mat4 defaultToRefrenceMat, glm::mat4 defaultJointMat, controller::Pose puckPose) { - ///qDebug() << "-------------> computing offset <-------------"; glm::mat4 poseMat = createMatFromQuatAndPos(puckPose.rotation, puckPose.translation); glm::mat4 refrenceJointMat = defaultToRefrenceMat * defaultJointMat; return ( glm::inverse(poseMat) * refrenceJointMat); } + bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { controller::Pose firstPose = firstPuck.second; controller::Pose secondPose = secondPuck.second; return (firstPose.translation.y < secondPose.translation.y); } -void printPose(controller::Pose pose) { - qDebug() << "-------------> printing out controller::Pose <--------------"; - qDebug() << QString::fromStdString(glm::to_string(pose.translation)); - qDebug() << QString::fromStdString(glm::to_string(pose.rotation)); -} - bool ViveControllerManager::isSupported() const { return openVrSupported(); } @@ -276,8 +265,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr } if (_config == Config::Feet) { - controller::Pose leftPose = addOffsetToPuckPose(controller::LEFT_FOOT); - printPose(leftPose); // done } else if (_config == Config::FeetAndHips) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; From 7d0494dd564bcf75d1e915015ce11b5795cb1487 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 8 May 2017 12:15:03 -0700 Subject: [PATCH 12/32] use new images in api/v1/users response json --- scripts/system/pal.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 9229ec772a..254372fba7 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -369,21 +369,7 @@ function getAvailableConnections(domain, callback) { // callback([{usename, loca url += 'filter=connections'; // regardless of whether online } requestJSON(url, function (connectionsData) { - // The back end doesn't include the profile picture data, but we can add that here. - // For our current purposes, there's no need to be fancy and try to reduce latency by doing some number of requests in parallel, - // so these requests are all sequential. - var users = connectionsData.users; - function addPicture(index) { - if (index >= users.length) { - return callback(users); - } - var user = users[index]; - getProfilePicture(user.username, function (url) { - user.profileUrl = url; - addPicture(index + 1); - }); - } - addPicture(0); + callback(connectionsData.users); }); } @@ -397,7 +383,7 @@ function getConnectionData(domain) { // Update all the usernames that I am entit sessionId: formattedSessionId, userName: user.username, connection: user.connection, - profileUrl: user.profileUrl, + profileUrl: user.images.thumbnail, placeName: (user.location.root || user.location.domain || {}).name || '' }; } From 23c3a7511610b6d0c5bd388398f0796505077b62 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 00:27:30 +0100 Subject: [PATCH 13/32] finally fixed rotation issue --- plugins/openvr/src/ViveControllerManager.cpp | 149 ++++++++++--------- plugins/openvr/src/ViveControllerManager.h | 2 +- 2 files changed, 79 insertions(+), 72 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index ff6edccf9f..5a44a432ec 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -1,4 +1,3 @@ - // // Created by Sam Gondelman on 6/29/15. // Copyright 2013 High Fidelity, Inc. @@ -22,7 +21,6 @@ #include #include #include -#include #include @@ -48,10 +46,10 @@ const quint64 CALIBRATION_TIMELAPSE = 3000000; const char* ViveControllerManager::NAME { "OpenVR" }; -glm::mat4 computeOffset(glm::mat4 defaultToRefrenceMat, glm::mat4 defaultJointMat, controller::Pose puckPose) { +glm::mat4 computeOffset(glm::mat4 defaultToReferenceMat, glm::mat4 defaultJointMat, controller::Pose puckPose) { glm::mat4 poseMat = createMatFromQuatAndPos(puckPose.rotation, puckPose.translation); - glm::mat4 refrenceJointMat = defaultToRefrenceMat * defaultJointMat; - return ( glm::inverse(poseMat) * refrenceJointMat); + glm::mat4 referenceJointMat = defaultToReferenceMat * defaultJointMat; + return glm::inverse(poseMat) * referenceJointMat; } bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { @@ -130,7 +128,6 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu userInputMapper->removeDevice(_inputDevice->_deviceID); _registeredWithInputMapper = false; _inputDevice->_poseStateMap.clear(); - //qDebug() << " ----------->>!!!!!!! clear pose state map !!!!!!!<<----------------"; } if (!_registeredWithInputMapper && _inputDevice->_trackedControllers > 0) { @@ -213,78 +210,88 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { quint64 currentTime = usecTimestampNow(); - + auto leftTrigger = _buttonPressedMap.find(controller::LT); auto rightTrigger = _buttonPressedMap.find(controller::RT); if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { - if (!_calibrated) { - // conver the hmd head from sensor space to avatar space - glm::mat4 worldToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; - glm::mat4 hmdAvatarMat = worldToAvatarMat * inputCalibration.hmdSensorMat; + if (!_triggersPressedHandled) { + _triggersPressedHandled = true; + if (!_calibrated) { + // conver the hmd head from sensor space to avatar space + glm::mat4 hmdSensorFlippedMat = inputCalibration.hmdSensorMat * Matrices::Y_180; + glm::mat4 sensorToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; + glm::mat4 hmdAvatarMat = sensorToAvatarMat * hmdSensorFlippedMat; - // cancel the roll and pitch for the hmd head - glm::quat hmdRotation = cancelOutRollAndPitch(glmExtractRotation(hmdAvatarMat)); - glm::vec3 hmdTranslation = extractTranslation(hmdAvatarMat); - glm::mat4 currentHead = createMatFromQuatAndPos(hmdRotation, hmdTranslation); - - // calculate the offset from the centerOfEye to defaultHeadMat - glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + // cancel the roll and pitch for the hmd head + glm::quat hmdRotation = cancelOutRollAndPitch(glmExtractRotation(hmdAvatarMat)); + glm::vec3 hmdTranslation = extractTranslation(hmdAvatarMat); + glm::mat4 currentHead = createMatFromQuatAndPos(hmdRotation, hmdTranslation); + + // calculate the offset from the centerOfEye to defaultHeadMat + glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + + currentHead = currentHead * defaultHeadOffset; + + // calculate the defaultToRefrenceXform + glm::mat4 defaultReferenceXform = currentHead * glm::inverse(inputCalibration.defaultHeadMat); + + auto puckCount = _validTrackedObjects.size(); + if (puckCount == 2) { + _config = Config::Feet; + } else if (puckCount == 3) { + _config = Config::FeetAndHips; + } else if (puckCount >= 4) { + _config = Config::FeetHipsAndChest; + } else { + return; + } + + std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); + + auto firstFoot = _validTrackedObjects[0]; + auto secondFoot = _validTrackedObjects[1]; + controller::Pose firstFootPose = firstFoot.second; + controller::Pose secondFootPose = secondFoot.second; + + if (firstFootPose.translation.x < secondFootPose.translation.x) { + _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultLeftFoot, firstFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultRightFoot, secondFootPose); + + } else { + _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultLeftFoot, secondFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultRightFoot, firstFootPose); + } + + if (_config == Config::Feet) { + // done + } else if (_config == Config::FeetAndHips) { + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultReferenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); + } else if (_config == Config::FeetHipsAndChest) { + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultReferenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); + _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; + _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultReferenceXform, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); + } + _calibrated = true; - currentHead *= defaultHeadOffset; - - // calculate the defaultToRefrenceXform - glm::mat4 defaultRefrenceXform = currentHead * glm::inverse(inputCalibration.defaultHeadMat); - - auto puckCount = _validTrackedObjects.size(); - if (puckCount == 2) { - _config = Config::Feet; - } else if (puckCount == 3) { - _config = Config::FeetAndHips; - } else if (puckCount >= 4) { - _config = Config::FeetHipsAndChest; } else { - return; + _pucksOffset.clear(); + _jointToPuckMap.clear(); + _calibrated = false; } - - std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); - - auto firstFoot = _validTrackedObjects[0]; - auto secondFoot = _validTrackedObjects[1]; - controller::Pose firstFootPose = firstFoot.second; - controller::Pose secondFootPose = secondFoot.second; - if (firstFootPose.translation.x < secondFootPose.translation.x) { - _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, firstFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, secondFootPose); - } else { - _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultLeftFoot, secondFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultRightFoot, firstFootPose); - } - - if (_config == Config::Feet) { - // done - } else if (_config == Config::FeetAndHips) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; - _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); - } else if (_config == Config::FeetHipsAndChest) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; - _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); - _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; - _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultRefrenceXform, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); - } - _calibrated = true; - - } else { } - + } else { + _triggersPressedHandled = false; } } void ViveControllerManager::InputDevice::updateCalibratedLimbs() { - _poseStateMap[controller::LEFT_FOOT] = addOffsetToPuckPose(controller::LEFT_FOOT); + _poseStateMap[controller::LEFT_FOOT] = addOffsetToPuckPose(controller::LEFT_FOOT); _poseStateMap[controller::RIGHT_FOOT] = addOffsetToPuckPose(controller::RIGHT_FOOT); _poseStateMap[controller::HIPS] = addOffsetToPuckPose(controller::HIPS); _poseStateMap[controller::SPINE2] = addOffsetToPuckPose(controller::SPINE2); @@ -296,9 +303,9 @@ controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(int joi uint32_t puckIndex = puck->second; controller::Pose puckPose = _poseStateMap[puckIndex]; glm::mat4 puckOffset = _pucksOffset[puckIndex]; - puckPose.postTransform(puckOffset); - return puckPose; - + controller::Pose newPose = puckPose.postTransform(puckOffset); + return newPose; + } return controller::Pose(); } @@ -374,7 +381,7 @@ void ViveControllerManager::InputDevice::handleAxisEvent(float deltaTime, uint32 _axisStateMap[isLeftHand ? LY : RY] = stick.y; } else if (axis == vr::k_EButton_SteamVR_Trigger) { _axisStateMap[isLeftHand ? LT : RT] = x; - // The click feeling on the Vive controller trigger represents a value of *precisely* 1.0, + // The click feeling on the Vive controller trigger represents a value of *precisely* 1.0, // so we can expose that as an additional button if (x >= 1.0f) { _buttonPressedMap.insert(isLeftHand ? LT_CLICK : RT_CLICK); @@ -519,7 +526,7 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(LEFT_FOOT, "LeftFoot"), makePair(RIGHT_FOOT, "RightFoot"), makePair(HIPS, "Hips"), - makePair(SPINE2, "Spine2"), + makePair(SPINE2, "Spine2"), // 16 tracked poses makePair(TRACKED_OBJECT_00, "TrackedObject00"), diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 43dd982f80..1b0cf4213e 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -114,7 +114,7 @@ private: float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; float _rightHapticDuration { 0.0f }; - bool _calibrate { false }; + bool _triggersPressedHandled { false }; bool _calibrated { false }; mutable std::recursive_mutex _lock; From 00546c55bb2d15ea7bf6ae34fafe1b5693e34b6f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 00:30:06 +0100 Subject: [PATCH 14/32] minimize diff --- plugins/openvr/src/ViveControllerManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 5a44a432ec..00bf42b2d9 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -1,4 +1,7 @@ // +// ViveControllerManager.cpp +// input-plugins/src/input-plugins +// // Created by Sam Gondelman on 6/29/15. // Copyright 2013 High Fidelity, Inc. // From 03ba3f59441f8bee280b8525d5722e1a6fe91fdd Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 00:31:13 +0100 Subject: [PATCH 15/32] minimize diff 2.0 --- plugins/openvr/src/ViveControllerManager.h | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 1b0cf4213e..b9d7c3ea01 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -109,7 +109,6 @@ private: int _trackedControllers { 0 }; vr::IVRSystem*& _system; - quint64 _calibrateAfterTimelapse { 0.f }; float _leftHapticStrength { 0.0f }; float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; From c3d57459d5f9bfeb9e4d518446bec08b0c586fd1 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 00:32:47 +0100 Subject: [PATCH 16/32] minimize diff 3.0 --- plugins/openvr/src/ViveControllerManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 00bf42b2d9..e22195b028 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -212,8 +212,6 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde } void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { - quint64 currentTime = usecTimestampNow(); - auto leftTrigger = _buttonPressedMap.find(controller::LT); auto rightTrigger = _buttonPressedMap.find(controller::RT); if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { From b6f652e0eae8289dfb75f2af39da3f9172eb8b56 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 May 2017 20:05:14 -0400 Subject: [PATCH 17/32] use network period multiple for local audio buffer --- libraries/audio-client/src/AudioClient.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 680e9129aa..1266c4a499 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1525,14 +1525,23 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice connect(_audioOutput, &QAudioOutput::stateChanged, [&, frameSize, requestedSize](QAudio::State state) { if (state == QAudio::ActiveState) { // restrict device callback to _outputPeriod samples - _outputPeriod = (_audioOutput->periodSize() / AudioConstants::SAMPLE_SIZE) * 2; + _outputPeriod = _audioOutput->periodSize() / AudioConstants::SAMPLE_SIZE; + // device callback may exceed reported period, so double it to avoid stutter + _outputPeriod *= 2; + _outputMixBuffer = new float[_outputPeriod]; _outputScratchBuffer = new int16_t[_outputPeriod]; // size local output mix buffer based on resampled network frame size _networkPeriod = _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO); _localOutputMixBuffer = new float[_networkPeriod]; + + // local period should be at least twice the output period, + // in case two device reads happen before more data can be read (worst case) int localPeriod = _outputPeriod * 2; + // round up to an exact multiple of _networkPeriod + localPeriod = ((localPeriod + _networkPeriod - 1) / _networkPeriod) * _networkPeriod; + // this ensures lowest latency without stutter from underrun _localInjectorsStream.resizeForFrameSize(localPeriod); int bufferSize = _audioOutput->bufferSize(); From 73a3bf413bc3bdbd00cfb0f12768b0503803fa1a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 May 2017 20:14:09 -0400 Subject: [PATCH 18/32] update local audio thread name --- libraries/audio-client/src/AudioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 72cb438eab..1561eabf05 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1358,7 +1358,7 @@ bool AudioClient::outputLocalInjector(AudioInjector* injector) { // move local buffer to the LocalAudioThread to avoid dataraces with AudioInjector (like stop()) injectorBuffer->setParent(nullptr); - injectorBuffer->moveToThread(&_localAudioThread); + injectorBuffer->moveToThread(_localInjectorsThread); } else { qCDebug(audioclient) << "injector exists in active list already"; } From 34edc2345c4ef1b6996800b294deb53d5fd0a18d Mon Sep 17 00:00:00 2001 From: volansystech Date: Tue, 9 May 2017 22:07:32 +0530 Subject: [PATCH 19/32] Bug 4255: When you are in HMD and you go to file menu quit, it crashes and you have no menus when you come back. Fixed NPE of buttonProxy while doing addButtonProxyToQmlTablet on quitting the application. --- libraries/script-engine/src/TabletScriptingInterface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index 139fe0552d..644f1e6f0c 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -250,6 +250,10 @@ static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* if (QThread::currentThread() != qmlTablet->thread()) { connectionType = Qt::BlockingQueuedConnection; } + if (buttonProxy == NULL){ + qCCritical(scriptengine) << "TabletScriptingInterface addButtonProxyToQmlTablet buttonProxy is NULL"; + return; + } bool hasResult = QMetaObject::invokeMethod(qmlTablet, "addButtonProxy", connectionType, Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, buttonProxy->getProperties())); if (!hasResult) { From bce9e9ea82a92b5f66aff1b7df8b743ff947ebe9 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 17:51:30 +0100 Subject: [PATCH 20/32] made requested chnages --- plugins/openvr/src/ViveControllerManager.cpp | 195 ++++++++++--------- plugins/openvr/src/ViveControllerManager.h | 5 +- 2 files changed, 110 insertions(+), 90 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index e22195b028..ddf55bf670 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -45,20 +45,20 @@ static const char* MENU_PARENT = "Avatar"; static const char* MENU_NAME = "Vive Controllers"; static const char* MENU_PATH = "Avatar" ">" "Vive Controllers"; static const char* RENDER_CONTROLLERS = "Render Hand Controllers"; -const quint64 CALIBRATION_TIMELAPSE = 3000000; +static const int MIN_PUCK_COUNT = 2; +static const int MIN_FEET_AND_HIPS = 3; +static const int MIN_FEET_HIPS_CHEST = 4; const char* ViveControllerManager::NAME { "OpenVR" }; -glm::mat4 computeOffset(glm::mat4 defaultToReferenceMat, glm::mat4 defaultJointMat, controller::Pose puckPose) { +static glm::mat4 computeOffset(glm::mat4 defaultToReferenceMat, glm::mat4 defaultJointMat, controller::Pose puckPose) { glm::mat4 poseMat = createMatFromQuatAndPos(puckPose.rotation, puckPose.translation); glm::mat4 referenceJointMat = defaultToReferenceMat * defaultJointMat; return glm::inverse(poseMat) * referenceJointMat; } -bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { - controller::Pose firstPose = firstPuck.second; - controller::Pose secondPose = secondPuck.second; - return (firstPose.translation.y < secondPose.translation.y); +static bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { + return (firstPuck.second.translation.y < firstPuck.second.translation.y); } bool ViveControllerManager::isSupported() const { @@ -182,7 +182,16 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle numTrackedControllers++; } _trackedControllers = numTrackedControllers; - calibrate(inputCalibrationData); + + if (checkForCalibrationEvent()) { + if (!_triggersPressedHandled) { + _triggersPressedHandled = true; + calibrateOrUncalibrate(inputCalibrationData); + } + } else { + _triggersPressedHandled = false; + } + updateCalibratedLimbs(); } @@ -211,102 +220,110 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde } } -void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { - auto leftTrigger = _buttonPressedMap.find(controller::LT); - auto rightTrigger = _buttonPressedMap.find(controller::RT); - if ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())) { - if (!_triggersPressedHandled) { - _triggersPressedHandled = true; - if (!_calibrated) { - // conver the hmd head from sensor space to avatar space - glm::mat4 hmdSensorFlippedMat = inputCalibration.hmdSensorMat * Matrices::Y_180; - glm::mat4 sensorToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; - glm::mat4 hmdAvatarMat = sensorToAvatarMat * hmdSensorFlippedMat; - - // cancel the roll and pitch for the hmd head - glm::quat hmdRotation = cancelOutRollAndPitch(glmExtractRotation(hmdAvatarMat)); - glm::vec3 hmdTranslation = extractTranslation(hmdAvatarMat); - glm::mat4 currentHead = createMatFromQuatAndPos(hmdRotation, hmdTranslation); - - // calculate the offset from the centerOfEye to defaultHeadMat - glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; - - currentHead = currentHead * defaultHeadOffset; - - // calculate the defaultToRefrenceXform - glm::mat4 defaultReferenceXform = currentHead * glm::inverse(inputCalibration.defaultHeadMat); - - auto puckCount = _validTrackedObjects.size(); - if (puckCount == 2) { - _config = Config::Feet; - } else if (puckCount == 3) { - _config = Config::FeetAndHips; - } else if (puckCount >= 4) { - _config = Config::FeetHipsAndChest; - } else { - return; - } - - std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); - - auto firstFoot = _validTrackedObjects[0]; - auto secondFoot = _validTrackedObjects[1]; - controller::Pose firstFootPose = firstFoot.second; - controller::Pose secondFootPose = secondFoot.second; - - if (firstFootPose.translation.x < secondFootPose.translation.x) { - _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultLeftFoot, firstFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultRightFoot, secondFootPose); - - } else { - _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultLeftFoot, secondFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultReferenceXform, inputCalibration.defaultRightFoot, firstFootPose); - } - - if (_config == Config::Feet) { - // done - } else if (_config == Config::FeetAndHips) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; - _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultReferenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); - } else if (_config == Config::FeetHipsAndChest) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; - _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultReferenceXform, inputCalibration.defaultHips, _validTrackedObjects[2].second); - _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; - _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultReferenceXform, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); - } - _calibrated = true; - - } else { - _pucksOffset.clear(); - _jointToPuckMap.clear(); - _calibrated = false; - } - } +void ViveControllerManager::InputDevice::calibrateOrUncalibrate(const controller::InputCalibrationData& inputCalibration) { + if (!_calibrated) { + calibrate(inputCalibration); } else { - _triggersPressedHandled = false; + uncalibrate(); } } +bool ViveControllerManager::InputDevice::checkForCalibrationEvent() { + auto& leftTrigger = _buttonPressedMap.find(controller::LT); + auto& rightTrigger = _buttonPressedMap.find(controller::RT); + return ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())); +} + +void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { + // convert the hmd head from sensor space to avatar space + glm::mat4 hmdSensorFlippedMat = inputCalibration.hmdSensorMat * Matrices::Y_180; + glm::mat4 sensorToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; + glm::mat4 hmdAvatarMat = sensorToAvatarMat * hmdSensorFlippedMat; + + // cancel the roll and pitch for the hmd head + glm::quat hmdRotation = cancelOutRollAndPitch(glmExtractRotation(hmdAvatarMat)); + glm::vec3 hmdTranslation = extractTranslation(hmdAvatarMat); + glm::mat4 currentHmd = createMatFromQuatAndPos(hmdRotation, hmdTranslation); + + // calculate the offset from the centerOfEye to defaultHeadMat + glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + + glm::mat4 currentHead = currentHmd * defaultHeadOffset; + + // calculate the defaultToRefrenceXform + glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); + + int puckCount = (int)_validTrackedObjects.size(); + if (puckCount == MIN_PUCK_COUNT) { + _config = Config::Feet; + } else if (puckCount == MIN_FEET_AND_HIPS) { + _config = Config::FeetAndHips; + } else if (puckCount >= MIN_FEET_HIPS_CHEST) { + _config = Config::FeetHipsAndChest; + } else { + return; + } + + std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); + + int firstFootIndex = 0; + int secondFootIndex = 1; + + auto& firstFoot = _validTrackedObjects[firstFootIndex]; + auto& secondFoot = _validTrackedObjects[secondFootIndex]; + controller::Pose& firstFootPose = firstFoot.second; + controller::Pose& secondFootPose = secondFoot.second; + + if (firstFootPose.translation.x < secondFootPose.translation.x) { + _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, firstFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, secondFootPose); + + } else { + _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, secondFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, firstFootPose); + } + + if (_config == Config::Feet) { + // done + } else if (_config == Config::FeetAndHips) { + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[2].second); + } else if (_config == Config::FeetHipsAndChest) { + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[2].second); + _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; + _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); + } + _calibrated = true; +} + +void ViveControllerManager::InputDevice::uncalibrate() { + _pucksOffset.clear(); + _jointToPuckMap.clear(); + _calibrated = false; +} + void ViveControllerManager::InputDevice::updateCalibratedLimbs() { - _poseStateMap[controller::LEFT_FOOT] = addOffsetToPuckPose(controller::LEFT_FOOT); + _poseStateMap[controller::LEFT_FOOT] = addOffsetToPuckPose(controller::LEFT_FOOT); _poseStateMap[controller::RIGHT_FOOT] = addOffsetToPuckPose(controller::RIGHT_FOOT); _poseStateMap[controller::HIPS] = addOffsetToPuckPose(controller::HIPS); _poseStateMap[controller::SPINE2] = addOffsetToPuckPose(controller::SPINE2); } -controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(int joint) { +controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(int joint) const { auto puck = _jointToPuckMap.find(joint); if (puck != _jointToPuckMap.end()) { uint32_t puckIndex = puck->second; - controller::Pose puckPose = _poseStateMap[puckIndex]; - glm::mat4 puckOffset = _pucksOffset[puckIndex]; - controller::Pose newPose = puckPose.postTransform(puckOffset); - return newPose; + auto puckPose = _poseStateMap.find(puckIndex); + auto puckOffset = _pucksOffset.find(puckIndex); + if ((puckPose != _poseStateMap.end()) && (puckOffset != _pucksOffset.end())) { + return puckPose->second.postTransform(puckOffset->second); + } } return controller::Pose(); } diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index b9d7c3ea01..04e2d2b4aa 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -60,9 +60,12 @@ private: bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; void hapticsHelper(float deltaTime, bool leftHand); + void calibrateOrUncalibrate(const controller::InputCalibrationData& inputCalibration); void calibrate(const controller::InputCalibrationData& inputCalibration); - controller::Pose addOffsetToPuckPose(int joint); + void uncalibrate(); + controller::Pose addOffsetToPuckPose(int joint) const; void updateCalibratedLimbs(); + bool checkForCalibrationEvent(); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); From d688b60282047afd7e56ea66b9f2c6f42b64d4d3 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 18:02:12 +0100 Subject: [PATCH 21/32] no magic numbers --- plugins/openvr/src/ViveControllerManager.cpp | 23 +++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index ddf55bf670..851d04497a 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -45,9 +45,13 @@ static const char* MENU_PARENT = "Avatar"; static const char* MENU_NAME = "Vive Controllers"; static const char* MENU_PATH = "Avatar" ">" "Vive Controllers"; static const char* RENDER_CONTROLLERS = "Render Hand Controllers"; -static const int MIN_PUCK_COUNT = 2; -static const int MIN_FEET_AND_HIPS = 3; -static const int MIN_FEET_HIPS_CHEST = 4; +static const int MIN_PUCK_COUNT = 2; +static const int MIN_FEET_AND_HIPS = 3; +static const int MIN_FEET_HIPS_CHEST = 4; +static const int FIRST_FOOT = 0; +static const int SECOND_FOOT = 1; +static const int HIP = 2; +static const int CHEST = 3; const char* ViveControllerManager::NAME { "OpenVR" }; @@ -266,11 +270,10 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); - int firstFootIndex = 0; - int secondFootIndex = 1; - auto& firstFoot = _validTrackedObjects[firstFootIndex]; - auto& secondFoot = _validTrackedObjects[secondFootIndex]; + + auto& firstFoot = _validTrackedObjects[FIRST_FOOT]; + auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; controller::Pose& firstFootPose = firstFoot.second; controller::Pose& secondFootPose = secondFoot.second; @@ -290,12 +293,12 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if (_config == Config::Feet) { // done } else if (_config == Config::FeetAndHips) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[2].second); } else if (_config == Config::FeetHipsAndChest) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[2].first; + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[2].second); - _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[3].first; + _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); } _calibrated = true; From 48c78584c30b5c03f92f2b8fc9dc117dd3c81612 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 9 May 2017 11:09:39 -0700 Subject: [PATCH 22/32] fix a bug that could cause OBJ models with external mtl references to hang the loading thread --- libraries/fbx/src/OBJReader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 167cb8caac..1445d14d84 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -273,10 +273,9 @@ std::tuple requestData(QUrl& url) { return std::make_tuple(false, QByteArray()); } - request->send(); - QEventLoop loop; QObject::connect(request, &ResourceRequest::finished, &loop, &QEventLoop::quit); + request->send(); loop.exec(); if (request->getResult() == ResourceRequest::Success) { From c362ba91647cfbd7567112febca742ea4f8ffca2 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 19:13:47 +0100 Subject: [PATCH 23/32] better calibration event --- plugins/openvr/src/ViveControllerManager.cpp | 25 ++++++++++++++------ plugins/openvr/src/ViveControllerManager.h | 2 ++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 851d04497a..8fedf926dc 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ void releaseOpenVrSystem(); static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b"; +const quint64 CALIBRATION_TIMELAPSE = 3 * USECS_PER_SECOND; static const char* MENU_PARENT = "Avatar"; static const char* MENU_NAME = "Vive Controllers"; @@ -188,12 +190,19 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle _trackedControllers = numTrackedControllers; if (checkForCalibrationEvent()) { - if (!_triggersPressedHandled) { + quint64 currentTime = usecTimestampNow(); + if (!_timeTilCalibrationSet) { + _timeTilCalibrationSet = true; + _timeTilCalibration = currentTime + CALIBRATION_TIMELAPSE; + } + + if (currentTime > _timeTilCalibration && !_triggersPressedHandled) { _triggersPressedHandled = true; calibrateOrUncalibrate(inputCalibrationData); } } else { _triggersPressedHandled = false; + _timeTilCalibrationSet = false; } updateCalibratedLimbs(); @@ -232,12 +241,6 @@ void ViveControllerManager::InputDevice::calibrateOrUncalibrate(const controller } } -bool ViveControllerManager::InputDevice::checkForCalibrationEvent() { - auto& leftTrigger = _buttonPressedMap.find(controller::LT); - auto& rightTrigger = _buttonPressedMap.find(controller::RT); - return ((leftTrigger != _buttonPressedMap.end()) && (rightTrigger != _buttonPressedMap.end())); -} - void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { // convert the hmd head from sensor space to avatar space glm::mat4 hmdSensorFlippedMat = inputCalibration.hmdSensorMat * Matrices::Y_180; @@ -416,6 +419,14 @@ enum ViveButtonChannel { RIGHT_APP_MENU }; +bool ViveControllerManager::InputDevice::checkForCalibrationEvent() { + auto& endOfMap = _buttonPressedMap.end(); + auto& leftTrigger = _buttonPressedMap.find(controller::LT); + auto& rightTrigger = _buttonPressedMap.find(controller::RT); + auto& leftAppButton = _buttonPressedMap.find(LEFT_APP_MENU); + auto& rightAppButton = _buttonPressedMap.find(RIGHT_APP_MENU); + return ((leftTrigger != endOfMap && leftAppButton != endOfMap) && (rightTrigger != endOfMap && rightAppButton != endOfMap)); +} // These functions do translation from the Steam IDs to the standard controller IDs void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand) { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 04e2d2b4aa..9375fd20f0 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -112,12 +112,14 @@ private: int _trackedControllers { 0 }; vr::IVRSystem*& _system; + quint64 _timeTilCalibration { 0.0f }; float _leftHapticStrength { 0.0f }; float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; float _rightHapticDuration { 0.0f }; bool _triggersPressedHandled { false }; bool _calibrated { false }; + bool _timeTilCalibrationSet { false }; mutable std::recursive_mutex _lock; friend class ViveControllerManager; From 5b33e0233c59ba921ee73d9fa23df7d3b92c84b3 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 9 May 2017 13:27:42 -0700 Subject: [PATCH 24/32] fix typo in handshake script --- scripts/system/makeUserConnection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index 6f7b746f18..52afc8883d 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -760,7 +760,7 @@ break; case "done": delete waitingList[senderID]; - if (connectionId !== senderID) { + if (connectingId !== senderID) { break; } if (state === STATES.CONNECTING) { From c478f1a7520d7ef0d4901eaaa2726bd6b043a24d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 9 May 2017 16:34:42 -0400 Subject: [PATCH 25/32] synchronously fill injector buffer on underrun --- libraries/audio-client/src/AudioClient.cpp | 61 +++++++++++++++----- libraries/audio-client/src/AudioClient.h | 12 ++-- libraries/audio/src/AbstractAudioInterface.h | 2 +- 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 1266c4a499..f56d31eea2 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1096,11 +1096,19 @@ void AudioClient::handleRecordedAudioInput(const QByteArray& audio) { handleAudioInput(audioBuffer); } -void AudioClient::prepareLocalAudioInjectors() { +void AudioClient::prepareLocalAudioInjectors(std::unique_ptr localAudioLock) { + bool doSynchronously = localAudioLock.operator bool(); + if (!localAudioLock) { + localAudioLock.reset(new Lock(_localAudioMutex)); + } + int samplesNeeded = std::numeric_limits::max(); while (samplesNeeded > 0) { - // unlock between every write to allow device switching - Lock lock(_localAudioMutex); + if (!doSynchronously) { + // unlock between every write to allow device switching + localAudioLock->unlock(); + localAudioLock->lock(); + } // in case of a device switch, consider bufferCapacity volatile across iterations if (_outputPeriod == 0) { @@ -1154,16 +1162,16 @@ void AudioClient::prepareLocalAudioInjectors() { } bool AudioClient::mixLocalAudioInjectors(float* mixBuffer) { - - QVector injectorsToRemove; - - // lock the injector vector - Lock lock(_injectorsMutex); - - if (_activeLocalAudioInjectors.size() == 0) { + // check the flag for injectors before attempting to lock + if (!_localInjectorsAvailable.load(std::memory_order_acquire)) { return false; } + // lock the injectors + Lock lock(_injectorsMutex); + + QVector injectorsToRemove; + memset(mixBuffer, 0, AudioConstants::NETWORK_FRAME_SAMPLES_STEREO * sizeof(float)); for (AudioInjector* injector : _activeLocalAudioInjectors) { @@ -1242,6 +1250,9 @@ bool AudioClient::mixLocalAudioInjectors(float* mixBuffer) { _activeLocalAudioInjectors.removeOne(injector); } + // update the flag + _localInjectorsAvailable.exchange(!_activeLocalAudioInjectors.empty(), std::memory_order_release); + return true; } @@ -1329,6 +1340,9 @@ bool AudioClient::outputLocalInjector(AudioInjector* injector) { // move local buffer to the LocalAudioThread to avoid dataraces with AudioInjector (like stop()) injectorBuffer->setParent(nullptr); injectorBuffer->moveToThread(&_localAudioThread); + + // update the flag now that injectors are available + _localInjectorsAvailable.exchange(true, std::memory_order_release); } else { qCDebug(audioclient) << "injector exists in active list already"; } @@ -1455,7 +1469,7 @@ void AudioClient::outputNotify() { bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) { bool supportedFormat = false; - Lock lock(_localAudioMutex); + Lock localAudioLock(_localAudioMutex); _localSamplesAvailable.exchange(0, std::memory_order_release); // cleanup any previously initialized device @@ -1556,6 +1570,9 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice qCDebug(audioclient) << "local buffer (samples):" << localPeriod; disconnect(_audioOutput, &QAudioOutput::stateChanged, 0, 0); + + // unlock to avoid a deadlock with the device callback (which always succeeds this initialization) + localAudioLock.unlock(); } }); connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify); @@ -1694,12 +1711,24 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { int injectorSamplesPopped = 0; { bool append = networkSamplesPopped > 0; - // this does not require a lock as of the only two functions adding to _localSamplesAvailable (samples count): + // check the samples we have available locklessly; this is possible because only two functions add to the count: // - prepareLocalAudioInjectors will only increase samples count - // - switchOutputToAudioDevice will zero samples count - // stop the device, so that readData will exhaust the existing buffer or see a zeroed samples count - // and start the device, which can only see a zeroed samples count - samplesRequested = std::min(samplesRequested, _audio->_localSamplesAvailable.load(std::memory_order_acquire)); + // - switchOutputToAudioDevice will zero samples count, + // stop the device - so that readData will exhaust the existing buffer or see a zeroed samples count, + // and start the device - which can then only see a zeroed samples count + int samplesAvailable = _audio->_localSamplesAvailable.load(std::memory_order_acquire); + + // if we do not have enough samples buffered despite having injectors, buffer them synchronously + if (samplesAvailable < samplesRequested && _audio->_localInjectorsAvailable.load(std::memory_order_acquire)) { + // try_to_lock, in case the device is being shut down already + std::unique_ptr localAudioLock(new Lock(_audio->_localAudioMutex, std::try_to_lock)); + if (localAudioLock->owns_lock()) { + _audio->prepareLocalAudioInjectors(std::move(localAudioLock)); + samplesAvailable = _audio->_localSamplesAvailable.load(std::memory_order_acquire); + } + } + + samplesRequested = std::min(samplesRequested, samplesAvailable); if ((injectorSamplesPopped = _localInjectorsStream.appendSamples(mixBuffer, samplesRequested, append)) > 0) { _audio->_localSamplesAvailable.fetch_sub(injectorSamplesPopped, std::memory_order_release); qCDebug(audiostream, "Read %d samples from injectors (%d available, %d requested)", injectorSamplesPopped, _localInjectorsStream.samplesAvailable(), samplesRequested); diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index aaedee7456..3e9ba0fed9 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -158,7 +158,7 @@ public: Q_INVOKABLE void setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 scale); - void checkDevices(); + bool outputLocalInjector(AudioInjector* injector) override; static const float CALLBACK_ACCELERATOR_RATIO; @@ -198,8 +198,6 @@ public slots: int setOutputBufferSize(int numFrames, bool persist = true); - void prepareLocalAudioInjectors(); - bool outputLocalInjector(AudioInjector* injector) override; bool shouldLoopbackInjectors() override { return _shouldEchoToServer; } bool switchInputToAudioDevice(const QString& inputDeviceName); @@ -247,8 +245,13 @@ protected: } private: + friend class CheckDevicesThread; + friend class AudioInjectorsThread; + void outputFormatChanged(); void handleAudioInput(QByteArray& audioBuffer); + void checkDevices(); + void prepareLocalAudioInjectors(std::unique_ptr localAudioLock = nullptr); bool mixLocalAudioInjectors(float* mixBuffer); float azimuthForSource(const glm::vec3& relativePosition); float gainForSource(float distance, float volume); @@ -295,8 +298,9 @@ private: AudioRingBuffer _inputRingBuffer; LocalInjectorsStream _localInjectorsStream; // In order to use _localInjectorsStream as a lock-free pipe, - // use it with a single producer/consumer, and track available samples + // use it with a single producer/consumer, and track available samples and injectors std::atomic _localSamplesAvailable { 0 }; + std::atomic _localInjectorsAvailable { false }; MixedProcessedAudioStream _receivedAudioStream; bool _isStereoInput; diff --git a/libraries/audio/src/AbstractAudioInterface.h b/libraries/audio/src/AbstractAudioInterface.h index 2e4611cd4e..2e14b9956b 100644 --- a/libraries/audio/src/AbstractAudioInterface.h +++ b/libraries/audio/src/AbstractAudioInterface.h @@ -32,12 +32,12 @@ public: const Transform& transform, glm::vec3 avatarBoundingBoxCorner, glm::vec3 avatarBoundingBoxScale, PacketType packetType, QString codecName = QString("")); -public slots: // threadsafe // moves injector->getLocalBuffer() to another thread (so removes its parent) // take care to delete it when ~AudioInjector, as parenting Qt semantics will not work virtual bool outputLocalInjector(AudioInjector* injector) = 0; +public slots: virtual bool shouldLoopbackInjectors() { return false; } virtual void setIsStereoInput(bool stereo) = 0; From 2be6d19dfe5399438611780b1d6cd6995c849abf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 9 May 2017 14:00:18 -0700 Subject: [PATCH 26/32] always call Head::simulate() for Avatar in view --- .../src/avatars-renderer/Avatar.cpp | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index be55653f64..664b0094f4 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -369,23 +369,25 @@ void Avatar::simulate(float deltaTime, bool inView) { PerformanceTimer perfTimer("simulate"); { PROFILE_RANGE(simulation, "updateJoints"); - if (inView && _hasNewJointData) { - _skeletonModel->getRig()->copyJointsFromJointData(_jointData); - glm::mat4 rootTransform = glm::scale(_skeletonModel->getScale()) * glm::translate(_skeletonModel->getOffset()); - _skeletonModel->getRig()->computeExternalPoses(rootTransform); - _jointDataSimulationRate.increment(); - - _skeletonModel->simulate(deltaTime, true); - - locationChanged(); // joints changed, so if there are any children, update them. - _hasNewJointData = false; - - glm::vec3 headPosition = getPosition(); - if (!_skeletonModel->getHeadPosition(headPosition)) { - headPosition = getPosition(); - } + if (inView) { Head* head = getHead(); - head->setPosition(headPosition); + if (_hasNewJointData) { + _skeletonModel->getRig()->copyJointsFromJointData(_jointData); + glm::mat4 rootTransform = glm::scale(_skeletonModel->getScale()) * glm::translate(_skeletonModel->getOffset()); + _skeletonModel->getRig()->computeExternalPoses(rootTransform); + _jointDataSimulationRate.increment(); + + _skeletonModel->simulate(deltaTime, true); + + locationChanged(); // joints changed, so if there are any children, update them. + _hasNewJointData = false; + + glm::vec3 headPosition = getPosition(); + if (!_skeletonModel->getHeadPosition(headPosition)) { + headPosition = getPosition(); + } + head->setPosition(headPosition); + } head->setScale(getUniformScale()); head->simulate(deltaTime); } else { From 53e254152da25fc43362715c03b41e466e9238cf Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 May 2017 22:30:29 +0100 Subject: [PATCH 27/32] fixed puck location --- plugins/openvr/src/ViveControllerManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 8fedf926dc..db12d25e0d 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -41,7 +41,7 @@ void releaseOpenVrSystem(); static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b"; -const quint64 CALIBRATION_TIMELAPSE = 3 * USECS_PER_SECOND; +const quint64 CALIBRATION_TIMELAPSE = 2 * USECS_PER_SECOND; static const char* MENU_PARENT = "Avatar"; static const char* MENU_NAME = "Vive Controllers"; @@ -297,12 +297,12 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr // done } else if (_config == Config::FeetAndHips) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; - _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[2].second); + _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); } else if (_config == Config::FeetHipsAndChest) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; - _pucksOffset[_validTrackedObjects[2].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[2].second); + _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; - _pucksOffset[_validTrackedObjects[3].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[3].second); + _pucksOffset[_validTrackedObjects[CHEST].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[CHEST].second); } _calibrated = true; } From cf3c10c5b114f09ac8647a89c53b34e7073bc866 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 9 May 2017 14:21:38 -0700 Subject: [PATCH 28/32] Fix the bugs, add the feature --- interface/resources/qml/hifi/Pal.qml | 2 +- scripts/system/pal.js | 57 +++++++++++++++++++--------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 1755d2fbec..8f6b00f459 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -844,7 +844,7 @@ Rectangle { boxSize: 24; onClicked: { var newValue = model.connection !== "friend"; - connectionsUserModel.setProperty(model.userIndex, styleData.role, newValue); + connectionsUserModel.setProperty(model.userIndex, styleData.role, (newValue ? "friend" : "connection")); connectionsUserModelData[model.userIndex][styleData.role] = newValue; // Defensive programming pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName}); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 254372fba7..0500c13f9b 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -268,7 +268,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See break; case 'refreshConnections': print('Refreshing Connections...'); - getConnectionData(); + getConnectionData(false); UserActivityLogger.palAction("refresh_connections", ""); break; case 'removeConnection': @@ -281,25 +281,27 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See print("Error: unable to remove connection", connectionUserName, error || response.status); return; } - getConnectionData(); + getConnectionData(false); }); break case 'removeFriend': friendUserName = message.params; + print("Removing " + friendUserName + " from friends."); request({ uri: METAVERSE_BASE + '/api/v1/user/friends/' + friendUserName, method: 'DELETE' }, function (error, response) { if (error || (response.status !== 'success')) { - print("Error: unable to unfriend", friendUserName, error || response.status); + print("Error: unable to unfriend " + friendUserName, error || response.status); return; } - getConnectionData(); + getConnectionData(friendUserName); }); break case 'addFriend': friendUserName = message.params; + print("Adding " + friendUserName + " to friends."); request({ uri: METAVERSE_BASE + '/api/v1/user/friends', method: 'POST', @@ -312,7 +314,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See print("Error: unable to friend " + friendUserName, error || response.status); return; } - getConnectionData(); // For now, just refresh all connection data. Later, just refresh the one friended row. + getConnectionData(friendUserName); } ); break; @@ -360,8 +362,6 @@ function getProfilePicture(username, callback) { // callback(url) if successfull }); } function getAvailableConnections(domain, callback) { // callback([{usename, location}...]) if successfull. (Logs otherwise) - // The back end doesn't do user connections yet. Fake it by getting all users that have made themselves accessible to us, - // and pretending that they are all connections. url = METAVERSE_BASE + '/api/v1/users?' if (domain) { url += 'status=' + domain.slice(1, -1); // without curly braces @@ -372,8 +372,19 @@ function getAvailableConnections(domain, callback) { // callback([{usename, loca callback(connectionsData.users); }); } - -function getConnectionData(domain) { // Update all the usernames that I am entitled to see, using my login but not dependent on canKick. +function getInfoAboutUser(specificUsername, callback) { + url = METAVERSE_BASE + '/api/v1/users?filter=connections' + requestJSON(url, function (connectionsData) { + for (user in connectionsData.users) { + if (connectionsData.users[user].username === specificUsername) { + callback(connectionsData.users[user]); + return; + } + } + callback(false); + }); +} +function getConnectionData(specificUsername, domain) { // Update all the usernames that I am entitled to see, using my login but not dependent on canKick. function frob(user) { // get into the right format var formattedSessionId = user.location.node_id || ''; if (formattedSessionId !== '' && formattedSessionId.indexOf("{") != 0) { @@ -387,15 +398,25 @@ function getConnectionData(domain) { // Update all the usernames that I am entit placeName: (user.location.root || user.location.domain || {}).name || '' }; } - getAvailableConnections(domain, function (users) { - if (domain) { - users.forEach(function (user) { + if (specificUsername) { + getInfoAboutUser(specificUsername, function (user) { + if (user) { updateUser(frob(user)); - }); - } else { - sendToQml({ method: 'connections', params: users.map(frob) }); - } - }); + } else { + print('Error: Unable to find information about ' + specificUsername + ' in connectionsData!'); + } + }); + } else { + getAvailableConnections(domain, function (users) { + if (domain) { + users.forEach(function (user) { + updateUser(frob(user)); + }); + } else { + sendToQml({ method: 'connections', params: users.map(frob) }); + } + }); + } } // @@ -472,7 +493,7 @@ function populateNearbyUserList(selectData, oldAudioData) { data.push(avatarPalDatum); print('PAL data:', JSON.stringify(avatarPalDatum)); }); - getConnectionData(location.domainId); // Even admins don't get relationship data in requestUsernameFromID (which is still needed for admin status, which comes from domain). + getConnectionData(false, location.domainId); // Even admins don't get relationship data in requestUsernameFromID (which is still needed for admin status, which comes from domain). conserveResources = Object.keys(avatarsOfInterest).length > 20; sendToQml({ method: 'nearbyUsers', params: data }); if (selectData) { From bb4c0d972d98f90a27976f3f038ad4fe003a347f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 10 May 2017 00:10:26 +0100 Subject: [PATCH 29/32] head routed through the vive input plugin --- interface/resources/controllers/vive.json | 3 +- plugins/openvr/src/ViveControllerManager.cpp | 30 ++++++++++++++++++++ plugins/openvr/src/ViveControllerManager.h | 3 ++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/interface/resources/controllers/vive.json b/interface/resources/controllers/vive.json index 5bdffadbbf..4491507a9c 100644 --- a/interface/resources/controllers/vive.json +++ b/interface/resources/controllers/vive.json @@ -39,6 +39,7 @@ { "from": "Vive.LeftFoot", "to" : "Standard.LeftFoot", "when": [ "Application.InHMD"] }, { "from": "Vive.RightFoot", "to" : "Standard.RightFoot", "when": [ "Application.InHMD"] }, { "from": "Vive.Hips", "to" : "Standard.Hips", "when": [ "Application.InHMD"] }, - { "from": "Vive.Spine2", "to" : "Standard.Spine2", "when": [ "Application.InHMD"] } + { "from": "Vive.Spine2", "to" : "Standard.Spine2", "when": [ "Application.InHMD"] }, + { "from": "Vive.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] } ] } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index db12d25e0d..8f6e1e8430 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -167,6 +167,7 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle // collect poses for all generic trackers for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { handleTrackedObject(i, inputCalibrationData); + handleHmd(i, inputCalibrationData); } // handle haptics @@ -334,6 +335,22 @@ controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(int joi return controller::Pose(); } +void ViveControllerManager::InputDevice::handleHmd(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) { + uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex; + + if (_system->IsTrackedDeviceConnected(deviceIndex) && + _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_HMD && + _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid && + poseIndex <= controller::TRACKED_OBJECT_15) { + + const mat4& mat = _nextSimPoseData.poses[deviceIndex]; + const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; + const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex]; + + handleHeadPoseEvent(inputCalibrationData, mat, linearVelocity, angularVelocity); + } +} + void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) { if (_system->IsTrackedDeviceConnected(deviceIndex) && @@ -456,6 +473,18 @@ void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint } } +void ViveControllerManager::InputDevice::handleHeadPoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, + const vec3& linearVelocity, const vec3& angularVelocity) { + + glm::mat4 matYFlip = mat * Matrices::Y_180; + controller::Pose pose(extractTranslation(matYFlip), glmExtractRotation(matYFlip), linearVelocity, angularVelocity); + + glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + glm::mat4 defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) * inputCalibrationData.defaultHeadMat; + controller::Pose hmdHeadPose = pose.transform(sensorToAvatar); + _poseStateMap[controller::HEAD] = hmdHeadPose.postTransform(defaultHeadOffset); +} + void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, const vec3& linearVelocity, const vec3& angularVelocity, bool isLeftHand) { @@ -559,6 +588,7 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(RIGHT_FOOT, "RightFoot"), makePair(HIPS, "Hips"), makePair(SPINE2, "Spine2"), + makePair(HEAD, "Head"), // 16 tracked poses makePair(TRACKED_OBJECT_00, "TrackedObject00"), diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 9375fd20f0..4e8b2b3a04 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -67,11 +67,14 @@ private: void updateCalibratedLimbs(); bool checkForCalibrationEvent(); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); + void handleHmd(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand); void handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, const vec3& linearVelocity, const vec3& angularVelocity, bool isLeftHand); + void handleHeadPoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, const vec3& linearVelocity, + const vec3& angularVelocity); void partitionTouchpad(int sButton, int xAxis, int yAxis, int centerPsuedoButton, int xPseudoButton, int yPseudoButton); class FilteredStick { From a0bc8ae2eeaa0d32adea3d43bb7d1b7f691368a4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 10 May 2017 11:40:42 +1200 Subject: [PATCH 30/32] Fix unreachable eye blink code --- libraries/avatars-renderer/src/avatars-renderer/Head.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index a90c9cd5f7..1c54ea269a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -89,8 +89,7 @@ void Head::simulate(float deltaTime) { _timeWithoutTalking += deltaTime; if ((_averageLoudness - _longTermAverageLoudness) > TALKING_LOUDNESS) { _timeWithoutTalking = 0.0f; - - } else if (_timeWithoutTalking < BLINK_AFTER_TALKING && _timeWithoutTalking >= BLINK_AFTER_TALKING) { + } else if (_timeWithoutTalking - deltaTime < BLINK_AFTER_TALKING && _timeWithoutTalking >= BLINK_AFTER_TALKING) { forceBlink = true; } From 571f0d5951ae831bcbed682a3149e9753dba5083 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 10 May 2017 16:14:29 +0100 Subject: [PATCH 31/32] made requested changes --- plugins/openvr/src/ViveControllerManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 8f6e1e8430..452272a5d4 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -340,8 +340,7 @@ void ViveControllerManager::InputDevice::handleHmd(uint32_t deviceIndex, const c if (_system->IsTrackedDeviceConnected(deviceIndex) && _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_HMD && - _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid && - poseIndex <= controller::TRACKED_OBJECT_15) { + _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid) { const mat4& mat = _nextSimPoseData.poses[deviceIndex]; const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; @@ -476,6 +475,7 @@ void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint void ViveControllerManager::InputDevice::handleHeadPoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, const vec3& linearVelocity, const vec3& angularVelocity) { + // perform a 180 flip to make tha HMD face the +z, which is the same direction of the head faces. glm::mat4 matYFlip = mat * Matrices::Y_180; controller::Pose pose(extractTranslation(matYFlip), glmExtractRotation(matYFlip), linearVelocity, angularVelocity); From 0e1ef75d5b15627d147bd75237c176842cb28fdf Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 10 May 2017 16:18:26 +0100 Subject: [PATCH 32/32] fix comment wording --- plugins/openvr/src/ViveControllerManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 452272a5d4..6e5697730b 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -475,7 +475,7 @@ void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint void ViveControllerManager::InputDevice::handleHeadPoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, const vec3& linearVelocity, const vec3& angularVelocity) { - // perform a 180 flip to make tha HMD face the +z, which is the same direction of the head faces. + //perform a 180 flip to make the HMD face the +z instead of -z, beacuse the head faces +z glm::mat4 matYFlip = mat * Matrices::Y_180; controller::Pose pose(extractTranslation(matYFlip), glmExtractRotation(matYFlip), linearVelocity, angularVelocity);