From 6dd08ca1bf0cb98ffa52dad5c7b28352ce2aaaa0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 15 May 2014 17:09:28 -0700 Subject: [PATCH 1/9] Working on joystick support using SDL. --- interface/CMakeLists.txt | 8 +++ interface/src/Application.h | 3 ++ interface/src/devices/JoystickManager.cpp | 63 +++++++++++++++++++++++ interface/src/devices/JoystickManager.h | 52 +++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 interface/src/devices/JoystickManager.cpp create mode 100644 interface/src/devices/JoystickManager.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 96c212add6..3cbeff7801 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -136,6 +136,7 @@ find_package(Faceplus) find_package(Faceshift) find_package(LibOVR) find_package(PrioVR) +find_package(SDL) find_package(Sixense) find_package(Visage) find_package(ZLIB) @@ -193,6 +194,13 @@ if (PRIOVR_FOUND AND NOT DISABLE_PRIOVR) target_link_libraries(${TARGET_NAME} "${PRIOVR_LIBRARIES}") endif (PRIOVR_FOUND AND NOT DISABLE_PRIOVR) +# and with SDL for joysticks +if (SDL_FOUND AND NOT DISABLE_SDL) + add_definitions(-DHAVE_SDL) + include_directories(SYSTEM "${SDL_INCLUDE_DIR}") + target_link_libraries(${TARGET_NAME} "${SDL_LIBRARY}") +endif (SDL_FOUND AND NOT DISABLE_SDL) + # and with qxmpp for chat if (QXMPP_FOUND AND NOT DISABLE_QXMPP) add_definitions(-DHAVE_QXMPP -DQXMPP_STATIC) diff --git a/interface/src/Application.h b/interface/src/Application.h index 33ec9ca856..b9b73ac86a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -58,6 +58,7 @@ #include "avatar/MyAvatar.h" #include "devices/Faceplus.h" #include "devices/Faceshift.h" +#include "devices/JoystickManager.h" #include "devices/PrioVR.h" #include "devices/SixenseManager.h" #include "devices/Visage.h" @@ -196,6 +197,7 @@ public: FaceTracker* getActiveFaceTracker(); SixenseManager* getSixenseManager() { return &_sixenseManager; } PrioVR* getPrioVR() { return &_prioVR; } + JoystickManager* getJoystickManager() { return &_joystickManager; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } QUndoStack* getUndoStack() { return &_undoStack; } @@ -449,6 +451,7 @@ private: SixenseManager _sixenseManager; PrioVR _prioVR; + JoystickManager _joystickManager; Camera _myCamera; // My view onto the world Camera _viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode diff --git a/interface/src/devices/JoystickManager.cpp b/interface/src/devices/JoystickManager.cpp new file mode 100644 index 0000000000..77e53f3dcc --- /dev/null +++ b/interface/src/devices/JoystickManager.cpp @@ -0,0 +1,63 @@ +// +// JoystickManager.cpp +// interface/src/devices +// +// Created by Andrzej Kapolka on 5/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include + +#include "JoystickManager.h" + +using namespace std; + +JoystickManager::JoystickManager() { +#ifdef HAVE_SDL + SDL_Init(SDL_INIT_JOYSTICK); + int joystickCount = SDL_NumJoysticks(); + for (int i = 0; i < joystickCount; i++) { + SDL_Joystick* joystick = SDL_JoystickOpen(i); + if (joystick) { + JoystickState state = { SDL_JoystickName(i), QVector(SDL_JoystickNumAxes(joystick)), + QVector(SDL_JoystickNumButtons(joystick)) }; + qDebug() << state.name << state.axes.size() << state.buttons.size(); + _joystickStates.append(state); + _joysticks.append(joystick); + } + } +#endif +} + +JoystickManager::~JoystickManager() { +#ifdef HAVE_SDL + foreach (SDL_Joystick* joystick, _joysticks) { + SDL_JoystickClose(joystick); + } + SDL_Quit(); +#endif +} + +void JoystickManager::update() { +#ifdef HAVE_SDL + SDL_JoystickUpdate(); + + for (int i = 0; i < _joystickStates.size(); i++) { + SDL_Joystick* joystick = _joysticks.at(i); + JoystickState& state = _joystickStates[i]; + for (int j = 0; j < state.axes.size(); j++) { + state.axes[j] = glm::round(SDL_JoystickGetAxis(joystick, j) + 0.5f) / numeric_limits::max(); + } + for (int j = 0; j < state.buttons.size(); j++) { + state.buttons[j] = SDL_JoystickGetButton(joystick, j); + } + } +#endif +} diff --git a/interface/src/devices/JoystickManager.h b/interface/src/devices/JoystickManager.h new file mode 100644 index 0000000000..61cc2b2571 --- /dev/null +++ b/interface/src/devices/JoystickManager.h @@ -0,0 +1,52 @@ +// +// JoystickManager.h +// interface/src/devices +// +// Created by Andrzej Kapolka on 5/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_JoystickManager_h +#define hifi_JoystickManager_h + +#include +#include + +#ifdef HAVE_SDL +#include +#endif + +class JoystickState; + +/// Handles joystick input through SDL. +class JoystickManager : public QObject { + Q_OBJECT + +public: + + JoystickManager(); + virtual ~JoystickManager(); + + const QVector& getJoystickStates() const { return _joystickStates; } + + void update(); + +private: + QVector _joystickStates; + +#ifdef HAVE_SDL + QVector _joysticks; +#endif +}; + +class JoystickState { +public: + QString name; + QVector axes; + QVector buttons; +}; + +#endif // hifi_JoystickManager_h From 946e2b574308013375c83aacda0a2a0cde795d62 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 15 May 2014 17:15:25 -0700 Subject: [PATCH 2/9] Avoid unused variable warnings in Xcode. --- interface/src/devices/PrioVR.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index 28564f6f2e..e6e948422e 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -17,6 +17,7 @@ #include "PrioVR.h" #include "ui/TextRenderer.h" +#ifdef HAVE_PRIOVR const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A, 0x0000000C, 0x0000000D, 0x0000000E, 0x00000004, 0x00000005, 0x00000010, 0x00000011 }; const unsigned char AXIS_LIST[] = { 9, 43, 37, 37, 37, 13, 13, 13, 52, 52, 28, 28 }; @@ -25,7 +26,6 @@ const int LIST_LENGTH = sizeof(SERIAL_LIST) / sizeof(SERIAL_LIST[0]); const char* JOINT_NAMES[] = { "Neck", "Spine", "LeftArm", "LeftForeArm", "LeftHand", "RightArm", "RightForeArm", "RightHand", "LeftUpLeg", "LeftLeg", "RightUpLeg", "RightLeg" }; -#ifdef HAVE_PRIOVR static int indexOfHumanIKJoint(const char* jointName) { for (int i = 0;; i++) { QByteArray humanIKJoint = HUMANIK_JOINTS[i]; From a544489f3020e21529872aeb1c20291de5a8b71a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 15 May 2014 17:44:35 -0700 Subject: [PATCH 3/9] First cut at adding external joysticks to the mix. --- interface/src/devices/JoystickManager.cpp | 1 - interface/src/devices/JoystickManager.h | 1 + .../ControllerScriptingInterface.cpp | 25 +++++++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/interface/src/devices/JoystickManager.cpp b/interface/src/devices/JoystickManager.cpp index 77e53f3dcc..da3c1834af 100644 --- a/interface/src/devices/JoystickManager.cpp +++ b/interface/src/devices/JoystickManager.cpp @@ -28,7 +28,6 @@ JoystickManager::JoystickManager() { if (joystick) { JoystickState state = { SDL_JoystickName(i), QVector(SDL_JoystickNumAxes(joystick)), QVector(SDL_JoystickNumButtons(joystick)) }; - qDebug() << state.name << state.axes.size() << state.buttons.size(); _joystickStates.append(state); _joysticks.append(joystick); } diff --git a/interface/src/devices/JoystickManager.h b/interface/src/devices/JoystickManager.h index 61cc2b2571..53a255e129 100644 --- a/interface/src/devices/JoystickManager.h +++ b/interface/src/devices/JoystickManager.h @@ -17,6 +17,7 @@ #ifdef HAVE_SDL #include +#undef main #endif class JoystickState; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 58a08066d6..929be1df5e 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -88,10 +88,24 @@ glm::vec2 ControllerScriptingInterface::getPrimaryJoystickPosition() const { } int ControllerScriptingInterface::getNumberOfButtons() const { - return getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; + int buttonCount = 0; + foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { + buttonCount += state.buttons.size(); + } + return buttonCount + getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; } bool ControllerScriptingInterface::isButtonPressed(int buttonIndex) const { + int managedButtonIndex = buttonIndex - getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; + if (managedButtonIndex >= 0) { + foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { + if (managedButtonIndex < state.buttons.size()) { + return state.buttons.at(managedButtonIndex); + } + managedButtonIndex -= state.buttons.size(); + } + return false; + } int palmIndex = buttonIndex / NUMBER_OF_BUTTONS_PER_PALM; int buttonOnPalm = buttonIndex % NUMBER_OF_BUTTONS_PER_PALM; const PalmData* palmData = getActivePalm(palmIndex); @@ -129,11 +143,18 @@ float ControllerScriptingInterface::getTriggerValue(int triggerIndex) const { } int ControllerScriptingInterface::getNumberOfJoysticks() const { - return getNumberOfActivePalms() * NUMBER_OF_JOYSTICKS_PER_PALM; + return getNumberOfActivePalms() * NUMBER_OF_JOYSTICKS_PER_PALM + + Application::getInstance()->getJoystickManager()->getJoystickStates().size(); } glm::vec2 ControllerScriptingInterface::getJoystickPosition(int joystickIndex) const { // we know there's one joystick per palm, so the joystickIndex is the palm Index + int managedJoystickIndex = joystickIndex - getNumberOfActivePalms(); + if (managedJoystickIndex >= 0) { + const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at( + managedJoystickIndex); + return glm::vec2(state.axes.size() > 0 ? state.axes.at(0) : 0.0f, state.axes.size() > 1 ? state.axes.at(1) : 0.0f); + } int palmIndex = joystickIndex; const PalmData* palmData = getActivePalm(palmIndex); if (palmData) { From e41500652606212d0bf865706ff754eb60ff2cbc Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 15 May 2014 18:22:57 -0700 Subject: [PATCH 4/9] Fixed index of out bounds error, issue with head not being tracked in PrioVR. --- interface/src/scripting/ControllerScriptingInterface.cpp | 3 ++- libraries/fbx/src/FBXReader.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 929be1df5e..df97af1a16 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -150,7 +150,8 @@ int ControllerScriptingInterface::getNumberOfJoysticks() const { glm::vec2 ControllerScriptingInterface::getJoystickPosition(int joystickIndex) const { // we know there's one joystick per palm, so the joystickIndex is the palm Index int managedJoystickIndex = joystickIndex - getNumberOfActivePalms(); - if (managedJoystickIndex >= 0) { + if (managedJoystickIndex >= 0 && managedJoystickIndex < + Application::getInstance()->getJoystickManager()->getJoystickStates().size()) { const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at( managedJoystickIndex); return glm::vec2(state.axes.size() > 0 ? state.axes.at(0) : 0.0f, state.axes.size() > 1 ? state.axes.at(1) : 0.0f); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 264f58f0d4..44ef3f3aab 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -585,6 +585,7 @@ const char* HUMANIK_JOINTS[] = { "LeftArm", "LeftForeArm", "LeftHand", + "Neck", "Spine", "Hips", "RightUpLeg", From c29708f22c3a8f2484a486b6d6abcc6884b03ac9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 15 May 2014 19:18:19 -0700 Subject: [PATCH 5/9] Basic joystick integration. --- interface/src/Application.cpp | 1 + interface/src/devices/JoystickManager.cpp | 4 +- interface/src/devices/PrioVR.cpp | 3 ++ interface/src/devices/PrioVR.h | 3 ++ .../ControllerScriptingInterface.cpp | 40 ++++++++++++++----- 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 91e95bb4e3..85fb77908a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1990,6 +1990,7 @@ void Application::update(float deltaTime) { _myAvatar->updateLookAtTargetAvatar(); updateMyAvatarLookAtPosition(); _sixenseManager.update(deltaTime); + _joystickManager.update(); _prioVR.update(); updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... diff --git a/interface/src/devices/JoystickManager.cpp b/interface/src/devices/JoystickManager.cpp index da3c1834af..005505441c 100644 --- a/interface/src/devices/JoystickManager.cpp +++ b/interface/src/devices/JoystickManager.cpp @@ -52,7 +52,9 @@ void JoystickManager::update() { SDL_Joystick* joystick = _joysticks.at(i); JoystickState& state = _joystickStates[i]; for (int j = 0; j < state.axes.size(); j++) { - state.axes[j] = glm::round(SDL_JoystickGetAxis(joystick, j) + 0.5f) / numeric_limits::max(); + float value = glm::round(SDL_JoystickGetAxis(joystick, j) + 0.5f) / numeric_limits::max(); + const float DEAD_ZONE = 0.1f; + state.axes[j] = glm::abs(value) < DEAD_ZONE ? 0.0f : value; } for (int j = 0; j < state.buttons.size(); j++) { state.buttons[j] = SDL_JoystickGetButton(joystick, j); diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index e6e948422e..c97d35b9d2 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include @@ -52,6 +53,8 @@ PrioVR::PrioVR() { for (int i = 0; i < LIST_LENGTH; i++) { _humanIKJointIndices.append(jointsDiscovered[i] ? indexOfHumanIKJoint(JOINT_NAMES[i]) : -1); } + const int INITIAL_RESET_DELAY = 5000; + QTimer::singleShot(INITIAL_RESET_DELAY, this, SLOT(reset())); #endif } diff --git a/interface/src/devices/PrioVR.h b/interface/src/devices/PrioVR.h index 8f01574356..59352d2ac4 100644 --- a/interface/src/devices/PrioVR.h +++ b/interface/src/devices/PrioVR.h @@ -44,6 +44,9 @@ public: const QVector& getJointRotations() const { return _jointRotations; } void update(); + +public slots: + void reset(); private slots: diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index df97af1a16..b5619191fa 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -90,19 +90,20 @@ glm::vec2 ControllerScriptingInterface::getPrimaryJoystickPosition() const { int ControllerScriptingInterface::getNumberOfButtons() const { int buttonCount = 0; foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { - buttonCount += state.buttons.size(); + buttonCount += state.buttons.size() / 2; } return buttonCount + getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; } bool ControllerScriptingInterface::isButtonPressed(int buttonIndex) const { + // as a temporary hack, we consider every other button a trigger int managedButtonIndex = buttonIndex - getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; if (managedButtonIndex >= 0) { foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { - if (managedButtonIndex < state.buttons.size()) { - return state.buttons.at(managedButtonIndex); + if (managedButtonIndex * 2 + 1 < state.buttons.size()) { + return state.buttons.at(managedButtonIndex * 2 + 1); } - managedButtonIndex -= state.buttons.size(); + managedButtonIndex -= state.buttons.size() / 2; } return false; } @@ -129,10 +130,24 @@ bool ControllerScriptingInterface::isButtonPressed(int buttonIndex) const { } int ControllerScriptingInterface::getNumberOfTriggers() const { - return getNumberOfActivePalms() * NUMBER_OF_TRIGGERS_PER_PALM; + int buttonCount = 0; + foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { + buttonCount += state.buttons.size() / 2; + } + return buttonCount + getNumberOfActivePalms() * NUMBER_OF_TRIGGERS_PER_PALM; } float ControllerScriptingInterface::getTriggerValue(int triggerIndex) const { + int managedButtonIndex = triggerIndex - getNumberOfActivePalms() * NUMBER_OF_TRIGGERS_PER_PALM; + if (managedButtonIndex >= 0) { + foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { + if (managedButtonIndex * 2 < state.buttons.size()) { + return state.buttons.at(managedButtonIndex * 2) ? 1.0f : 0.0f; + } + managedButtonIndex -= state.buttons.size() / 2; + } + return false; + } // we know there's one trigger per palm, so the triggerIndex is the palm Index int palmIndex = triggerIndex; const PalmData* palmData = getActivePalm(palmIndex); @@ -149,12 +164,15 @@ int ControllerScriptingInterface::getNumberOfJoysticks() const { glm::vec2 ControllerScriptingInterface::getJoystickPosition(int joystickIndex) const { // we know there's one joystick per palm, so the joystickIndex is the palm Index - int managedJoystickIndex = joystickIndex - getNumberOfActivePalms(); - if (managedJoystickIndex >= 0 && managedJoystickIndex < - Application::getInstance()->getJoystickManager()->getJoystickStates().size()) { - const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at( - managedJoystickIndex); - return glm::vec2(state.axes.size() > 0 ? state.axes.at(0) : 0.0f, state.axes.size() > 1 ? state.axes.at(1) : 0.0f); + int managedAxisIndex = (joystickIndex - getNumberOfActivePalms()) * 2; + if (managedAxisIndex >= 0) { + foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { + if (managedAxisIndex + 1 < state.axes.size()) { + return glm::vec2(state.axes.at(managedAxisIndex), -state.axes.at(managedAxisIndex + 1)); + } + managedAxisIndex -= state.axes.size(); + } + return glm::vec2(); } int palmIndex = joystickIndex; const PalmData* palmData = getActivePalm(palmIndex); From 20eadab9700adb05a3ceb46909d8b59ffcf0500b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 16 May 2014 11:18:21 -0700 Subject: [PATCH 6/9] Lock joystick states for thread safety. --- interface/src/devices/JoystickManager.cpp | 6 ++++++ interface/src/devices/JoystickManager.h | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/JoystickManager.cpp b/interface/src/devices/JoystickManager.cpp index da3c1834af..6b8fd9563f 100644 --- a/interface/src/devices/JoystickManager.cpp +++ b/interface/src/devices/JoystickManager.cpp @@ -44,10 +44,16 @@ JoystickManager::~JoystickManager() { #endif } +QVector JoystickManager::getJoystickStates() { + QMutexLocker locker(&_joystickMutex); + return _joystickStates; +} + void JoystickManager::update() { #ifdef HAVE_SDL SDL_JoystickUpdate(); + QMutexLocker locker(&_joystickMutex); for (int i = 0; i < _joystickStates.size(); i++) { SDL_Joystick* joystick = _joysticks.at(i); JoystickState& state = _joystickStates[i]; diff --git a/interface/src/devices/JoystickManager.h b/interface/src/devices/JoystickManager.h index 53a255e129..1979cf0205 100644 --- a/interface/src/devices/JoystickManager.h +++ b/interface/src/devices/JoystickManager.h @@ -12,6 +12,7 @@ #ifndef hifi_JoystickManager_h #define hifi_JoystickManager_h +#include #include #include @@ -31,12 +32,13 @@ public: JoystickManager(); virtual ~JoystickManager(); - const QVector& getJoystickStates() const { return _joystickStates; } + QVector getJoystickStates(); void update(); private: QVector _joystickStates; + QMutex _joystickMutex; #ifdef HAVE_SDL QVector _joysticks; From c42368594d7035f33327cb8a54884e8e40eea060 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 16 May 2014 11:24:45 -0700 Subject: [PATCH 7/9] Scratch that; going to shoehorn joystick data into palms. --- interface/src/devices/JoystickManager.cpp | 6 ----- interface/src/devices/JoystickManager.h | 4 +-- .../ControllerScriptingInterface.cpp | 26 ++----------------- 3 files changed, 3 insertions(+), 33 deletions(-) diff --git a/interface/src/devices/JoystickManager.cpp b/interface/src/devices/JoystickManager.cpp index 6b8fd9563f..da3c1834af 100644 --- a/interface/src/devices/JoystickManager.cpp +++ b/interface/src/devices/JoystickManager.cpp @@ -44,16 +44,10 @@ JoystickManager::~JoystickManager() { #endif } -QVector JoystickManager::getJoystickStates() { - QMutexLocker locker(&_joystickMutex); - return _joystickStates; -} - void JoystickManager::update() { #ifdef HAVE_SDL SDL_JoystickUpdate(); - QMutexLocker locker(&_joystickMutex); for (int i = 0; i < _joystickStates.size(); i++) { SDL_Joystick* joystick = _joysticks.at(i); JoystickState& state = _joystickStates[i]; diff --git a/interface/src/devices/JoystickManager.h b/interface/src/devices/JoystickManager.h index 1979cf0205..53a255e129 100644 --- a/interface/src/devices/JoystickManager.h +++ b/interface/src/devices/JoystickManager.h @@ -12,7 +12,6 @@ #ifndef hifi_JoystickManager_h #define hifi_JoystickManager_h -#include #include #include @@ -32,13 +31,12 @@ public: JoystickManager(); virtual ~JoystickManager(); - QVector getJoystickStates(); + const QVector& getJoystickStates() const { return _joystickStates; } void update(); private: QVector _joystickStates; - QMutex _joystickMutex; #ifdef HAVE_SDL QVector _joysticks; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 929be1df5e..286d55081d 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -74,7 +74,6 @@ bool ControllerScriptingInterface::isPrimaryButtonPressed() const { return true; } } - return false; } @@ -88,24 +87,10 @@ glm::vec2 ControllerScriptingInterface::getPrimaryJoystickPosition() const { } int ControllerScriptingInterface::getNumberOfButtons() const { - int buttonCount = 0; - foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { - buttonCount += state.buttons.size(); - } - return buttonCount + getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; + return getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; } bool ControllerScriptingInterface::isButtonPressed(int buttonIndex) const { - int managedButtonIndex = buttonIndex - getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; - if (managedButtonIndex >= 0) { - foreach (const JoystickState& state, Application::getInstance()->getJoystickManager()->getJoystickStates()) { - if (managedButtonIndex < state.buttons.size()) { - return state.buttons.at(managedButtonIndex); - } - managedButtonIndex -= state.buttons.size(); - } - return false; - } int palmIndex = buttonIndex / NUMBER_OF_BUTTONS_PER_PALM; int buttonOnPalm = buttonIndex % NUMBER_OF_BUTTONS_PER_PALM; const PalmData* palmData = getActivePalm(palmIndex); @@ -143,18 +128,11 @@ float ControllerScriptingInterface::getTriggerValue(int triggerIndex) const { } int ControllerScriptingInterface::getNumberOfJoysticks() const { - return getNumberOfActivePalms() * NUMBER_OF_JOYSTICKS_PER_PALM + - Application::getInstance()->getJoystickManager()->getJoystickStates().size(); + return getNumberOfActivePalms() * NUMBER_OF_JOYSTICKS_PER_PALM; } glm::vec2 ControllerScriptingInterface::getJoystickPosition(int joystickIndex) const { // we know there's one joystick per palm, so the joystickIndex is the palm Index - int managedJoystickIndex = joystickIndex - getNumberOfActivePalms(); - if (managedJoystickIndex >= 0) { - const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at( - managedJoystickIndex); - return glm::vec2(state.axes.size() > 0 ? state.axes.at(0) : 0.0f, state.axes.size() > 1 ? state.axes.at(1) : 0.0f); - } int palmIndex = joystickIndex; const PalmData* palmData = getActivePalm(palmIndex); if (palmData) { From a7234fd8d33e72dba01eb5c9485f408138994a4e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 16 May 2014 12:10:21 -0700 Subject: [PATCH 8/9] Stuff the joystick and position bits into the palms. --- interface/src/Application.cpp | 2 +- interface/src/devices/PrioVR.cpp | 87 ++++++++++++++++++- interface/src/devices/PrioVR.h | 2 +- .../ControllerScriptingInterface.cpp | 1 + 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 91e95bb4e3..9f391aa36b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1990,7 +1990,7 @@ void Application::update(float deltaTime) { _myAvatar->updateLookAtTargetAvatar(); updateMyAvatarLookAtPosition(); _sixenseManager.update(deltaTime); - _prioVR.update(); + _prioVR.update(deltaTime); updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... _avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them... diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index e6e948422e..dcc3d314f3 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -37,6 +37,87 @@ static int indexOfHumanIKJoint(const char* jointName) { } } } + +static void setPalm(float deltaTime, int index) { + MyAvatar* avatar = Application::getInstance()->getAvatar(); + Hand* hand = avatar->getHand(); + PalmData* palm; + bool foundHand = false; + for (size_t j = 0; j < hand->getNumPalms(); j++) { + if (hand->getPalms()[j].getSixenseID() == index) { + palm = &(hand->getPalms()[j]); + foundHand = true; + } + } + if (!foundHand) { + PalmData newPalm(hand); + hand->getPalms().push_back(newPalm); + palm = &(hand->getPalms()[hand->getNumPalms() - 1]); + palm->setSixenseID(index); + } + + palm->setActive(true); + + // Read controller buttons and joystick into the hand + if (!Application::getInstance()->getJoystickManager()->getJoystickStates().isEmpty()) { + const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at(0); + if (state.axes.size() >= 4 && state.buttons.size() >= 4) { + if (index == 0) { + palm->setControllerButtons(state.buttons.at(1) ? BUTTON_FWD : 0); + palm->setTrigger(state.buttons.at(0) ? 1.0f : 0.0f); + palm->setJoystick(state.axes.at(0), -state.axes.at(1)); + + } else { + palm->setControllerButtons(state.buttons.at(3) ? BUTTON_FWD : 0); + palm->setTrigger(state.buttons.at(2) ? 1.0f : 0.0f); + palm->setJoystick(state.axes.at(2), -state.axes.at(3)); + } + } + } + + glm::vec3 position; + glm::quat rotation; + + Model* skeletonModel = &Application::getInstance()->getAvatar()->getSkeletonModel(); + int jointIndex; + glm::quat inverseRotation = glm::inverse(skeletonModel->getRotation()); + if (index == 0) { + jointIndex = skeletonModel->getLeftHandJointIndex(); + skeletonModel->getJointRotation(jointIndex, rotation, true); + rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f)); + + } else { + jointIndex = skeletonModel->getRightHandJointIndex(); + skeletonModel->getJointRotation(jointIndex, rotation, true); + rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); + } + skeletonModel->getJointPosition(jointIndex, position); + position = inverseRotation * (position - skeletonModel->getTranslation()); + + palm->setRawRotation(rotation); + + // Compute current velocity from position change + glm::vec3 rawVelocity; + if (deltaTime > 0.f) { + rawVelocity = (position - palm->getRawPosition()) / deltaTime; + } else { + rawVelocity = glm::vec3(0.0f); + } + palm->setRawVelocity(rawVelocity); + palm->setRawPosition(position); + + // Store the one fingertip in the palm structure so we can track velocity + const float FINGER_LENGTH = 0.3f; // meters + const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); + const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; + glm::vec3 oldTipPosition = palm->getTipRawPosition(); + if (deltaTime > 0.f) { + palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); + } else { + palm->setTipVelocity(glm::vec3(0.f)); + } + palm->setTipPosition(newTipPosition); +} #endif PrioVR::PrioVR() { @@ -78,7 +159,7 @@ glm::quat PrioVR::getTorsoRotation() const { return _jointRotations.size() > TORSO_ROTATION_INDEX ? _jointRotations.at(TORSO_ROTATION_INDEX) : glm::quat(); } -void PrioVR::update() { +void PrioVR::update(float deltaTime) { #ifdef HAVE_PRIOVR if (!_skeletalDevice) { return; @@ -96,6 +177,10 @@ void PrioVR::update() { _lastJointRotations[i] = _jointRotations.at(i); _jointRotations[i] = safeMix(lastRotation, _jointRotations.at(i), 0.5f); } + + // convert the joysticks into palm data + setPalm(deltaTime, 0); + setPalm(deltaTime, 1); #endif } diff --git a/interface/src/devices/PrioVR.h b/interface/src/devices/PrioVR.h index 8f01574356..bb563bf807 100644 --- a/interface/src/devices/PrioVR.h +++ b/interface/src/devices/PrioVR.h @@ -43,7 +43,7 @@ public: const QVector& getHumanIKJointIndices() const { return _humanIKJointIndices; } const QVector& getJointRotations() const { return _jointRotations; } - void update(); + void update(float deltaTime); void reset(); private slots: diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 286d55081d..34c1cc2f1c 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -74,6 +74,7 @@ bool ControllerScriptingInterface::isPrimaryButtonPressed() const { return true; } } + return false; } From 956c5d2eb67310d7b0c822a4cca74780e610d2c9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 16 May 2014 14:24:49 -0700 Subject: [PATCH 9/9] More joystick fixes. --- interface/src/Application.cpp | 1 + interface/src/devices/PrioVR.cpp | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9f391aa36b..fc23a50f7b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1990,6 +1990,7 @@ void Application::update(float deltaTime) { _myAvatar->updateLookAtTargetAvatar(); updateMyAvatarLookAtPosition(); _sixenseManager.update(deltaTime); + _joystickManager.update(); _prioVR.update(deltaTime); updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index f38a2964b4..deba4f82a5 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -63,7 +63,7 @@ static void setPalm(float deltaTime, int index) { if (!Application::getInstance()->getJoystickManager()->getJoystickStates().isEmpty()) { const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at(0); if (state.axes.size() >= 4 && state.buttons.size() >= 4) { - if (index == 0) { + if (index == SIXENSE_CONTROLLER_ID_LEFT_HAND) { palm->setControllerButtons(state.buttons.at(1) ? BUTTON_FWD : 0); palm->setTrigger(state.buttons.at(0) ? 1.0f : 0.0f); palm->setJoystick(state.axes.at(0), -state.axes.at(1)); @@ -71,7 +71,7 @@ static void setPalm(float deltaTime, int index) { } else { palm->setControllerButtons(state.buttons.at(3) ? BUTTON_FWD : 0); palm->setTrigger(state.buttons.at(2) ? 1.0f : 0.0f); - palm->setJoystick(state.axes.at(2), -state.axes.at(3)); + palm->setJoystick(state.axes.at(2), -state.axes.at(3)); } } } @@ -81,16 +81,16 @@ static void setPalm(float deltaTime, int index) { Model* skeletonModel = &Application::getInstance()->getAvatar()->getSkeletonModel(); int jointIndex; - glm::quat inverseRotation = glm::inverse(skeletonModel->getRotation()); - if (index == 0) { + glm::quat inverseRotation = glm::inverse(Application::getInstance()->getAvatar()->getOrientation()); + if (index == SIXENSE_CONTROLLER_ID_LEFT_HAND) { jointIndex = skeletonModel->getLeftHandJointIndex(); skeletonModel->getJointRotation(jointIndex, rotation, true); - rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f)); + rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); } else { jointIndex = skeletonModel->getRightHandJointIndex(); skeletonModel->getJointRotation(jointIndex, rotation, true); - rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); + rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f)); } skeletonModel->getJointPosition(jointIndex, position); position = inverseRotation * (position - skeletonModel->getTranslation()); @@ -134,8 +134,6 @@ PrioVR::PrioVR() { for (int i = 0; i < LIST_LENGTH; i++) { _humanIKJointIndices.append(jointsDiscovered[i] ? indexOfHumanIKJoint(JOINT_NAMES[i]) : -1); } - const int INITIAL_RESET_DELAY = 5000; - QTimer::singleShot(INITIAL_RESET_DELAY, this, SLOT(reset())); #endif } @@ -182,8 +180,8 @@ void PrioVR::update(float deltaTime) { } // convert the joysticks into palm data - setPalm(deltaTime, 0); - setPalm(deltaTime, 1); + setPalm(deltaTime, SIXENSE_CONTROLLER_ID_LEFT_HAND); + setPalm(deltaTime, SIXENSE_CONTROLLER_ID_RIGHT_HAND); #endif }