mirror of
https://github.com/overte-org/overte.git
synced 2025-06-15 23:59:43 +02:00
cleaning up plugin architecture, fixed hand controllers
This commit is contained in:
parent
5fe4d06562
commit
01c740f415
20 changed files with 197 additions and 270 deletions
|
@ -76,7 +76,6 @@
|
||||||
#include <InfoView.h>
|
#include <InfoView.h>
|
||||||
#include <input-plugins/InputPlugin.h>
|
#include <input-plugins/InputPlugin.h>
|
||||||
#include <input-plugins/Joystick.h> // this should probably be removed
|
#include <input-plugins/Joystick.h> // this should probably be removed
|
||||||
#include <input-plugins/SixenseManager.h> // this definitely should be removed
|
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
#include <MainWindow.h>
|
#include <MainWindow.h>
|
||||||
#include <MessageDialog.h>
|
#include <MessageDialog.h>
|
||||||
|
@ -2130,7 +2129,7 @@ void Application::setEnableVRMode(bool enableVRMode) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Application::setLowVelocityFilter(bool lowVelocityFilter) {
|
void Application::setLowVelocityFilter(bool lowVelocityFilter) {
|
||||||
SixenseManager::getInstance().setLowVelocityFilter(lowVelocityFilter);
|
InputDevice::setLowVelocityFilter(lowVelocityFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::mouseOnScreen() const {
|
bool Application::mouseOnScreen() const {
|
||||||
|
@ -2365,17 +2364,6 @@ void Application::init() {
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "Loaded settings";
|
qCDebug(interfaceapp) << "Loaded settings";
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseEnabled)) {
|
|
||||||
// on OS X we only setup sixense if the user wants it on - this allows running without the hid_init crash
|
|
||||||
// if hydra support is temporarily not required
|
|
||||||
SixenseManager::getInstance().toggleSixense(true);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// setup sixense
|
|
||||||
SixenseManager::getInstance().toggleSixense(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Leapmotion::init();
|
Leapmotion::init();
|
||||||
RealSense::init();
|
RealSense::init();
|
||||||
|
|
||||||
|
@ -2683,12 +2671,17 @@ void Application::update(float deltaTime) {
|
||||||
userInputMapper->setSensorToWorldMat(_myAvatar->getSensorToWorldMatrix());
|
userInputMapper->setSensorToWorldMat(_myAvatar->getSensorToWorldMatrix());
|
||||||
userInputMapper->update(deltaTime);
|
userInputMapper->update(deltaTime);
|
||||||
|
|
||||||
|
// This needs to go after userInputMapper->update() because of the keyboard
|
||||||
|
bool jointsCaptured = false;
|
||||||
auto inputPlugins = getInputPlugins();
|
auto inputPlugins = getInputPlugins();
|
||||||
foreach(auto inputPlugin, inputPlugins) {
|
foreach(auto inputPlugin, inputPlugins) {
|
||||||
QString name = inputPlugin->getName();
|
QString name = inputPlugin->getName();
|
||||||
QAction* action = Menu::getInstance()->getActionForOption(name);
|
QAction* action = Menu::getInstance()->getActionForOption(name);
|
||||||
if (action->isChecked()) {
|
if (action->isChecked()) {
|
||||||
inputPlugin->pluginUpdate(deltaTime); // add flag to prevent multiple devices from modifying joints
|
inputPlugin->pluginUpdate(deltaTime, jointsCaptured);
|
||||||
|
if (inputPlugin->isJointController()) {
|
||||||
|
jointsCaptured = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2716,8 +2709,8 @@ void Application::update(float deltaTime) {
|
||||||
UserInputMapper::PoseValue leftHand = userInputMapper->getPoseState(UserInputMapper::LEFT_HAND);
|
UserInputMapper::PoseValue leftHand = userInputMapper->getPoseState(UserInputMapper::LEFT_HAND);
|
||||||
UserInputMapper::PoseValue rightHand = userInputMapper->getPoseState(UserInputMapper::RIGHT_HAND);
|
UserInputMapper::PoseValue rightHand = userInputMapper->getPoseState(UserInputMapper::RIGHT_HAND);
|
||||||
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
||||||
setPalmData(hand, leftHand, LEFT_HAND_INDEX);
|
setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX);
|
||||||
setPalmData(hand, rightHand, RIGHT_HAND_INDEX);
|
setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX);
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
||||||
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
|
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
|
||||||
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
||||||
|
@ -2869,7 +2862,7 @@ void Application::update(float deltaTime) {
|
||||||
_myAvatar->updateSensorToWorldMatrix();
|
_myAvatar->updateSensorToWorldMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int index) {
|
void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) {
|
||||||
PalmData* palm;
|
PalmData* palm;
|
||||||
bool foundHand = false;
|
bool foundHand = false;
|
||||||
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
||||||
|
@ -2888,11 +2881,53 @@ void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int i
|
||||||
|
|
||||||
palm->setActive(pose.isValid());
|
palm->setActive(pose.isValid());
|
||||||
|
|
||||||
// TODO: velocity filters, tip velocities, etc.
|
glm::vec3 position = pose.getTranslation();
|
||||||
// see SixenseManager
|
glm::quat rotation = pose.getRotation();
|
||||||
|
|
||||||
|
// TODO: velocity and tip position information should be converted to model space
|
||||||
|
// Compute current velocity from position change
|
||||||
|
glm::vec3 rawVelocity;
|
||||||
|
if (deltaTime > 0.0f) {
|
||||||
|
rawVelocity = (position - palm->getRawPosition()) / deltaTime;
|
||||||
|
} else {
|
||||||
|
rawVelocity = glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
palm->setRawVelocity(rawVelocity); // meters/sec
|
||||||
|
|
||||||
|
// Angular Velocity of Palm
|
||||||
|
glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation());
|
||||||
|
glm::vec3 angularVelocity(0.0f);
|
||||||
|
float rotationAngle = glm::angle(deltaRotation);
|
||||||
|
if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) {
|
||||||
|
angularVelocity = glm::normalize(glm::axis(deltaRotation));
|
||||||
|
angularVelocity *= (rotationAngle / deltaTime);
|
||||||
|
palm->setRawAngularVelocity(angularVelocity);
|
||||||
|
} else {
|
||||||
|
palm->setRawAngularVelocity(glm::vec3(0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InputDevice::getLowVelocityFilter()) {
|
||||||
|
// Use a velocity sensitive filter to damp small motions and preserve large ones with
|
||||||
|
// no latency.
|
||||||
|
float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
|
||||||
|
position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter);
|
||||||
|
rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.0f) {
|
||||||
|
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime);
|
||||||
|
} else {
|
||||||
|
palm->setTipVelocity(glm::vec3(0.0f));
|
||||||
|
}
|
||||||
|
palm->setTipPosition(newTipPosition);
|
||||||
|
|
||||||
// transform from sensor space, to world space, to avatar model space.
|
// transform from sensor space, to world space, to avatar model space.
|
||||||
glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation());
|
glm::mat4 poseMat = createMatFromQuatAndPos(rotation, position);
|
||||||
glm::mat4 sensorToWorldMat = _myAvatar->getSensorToWorldMatrix();
|
glm::mat4 sensorToWorldMat = _myAvatar->getSensorToWorldMatrix();
|
||||||
glm::mat4 modelMat = createMatFromQuatAndPos(_myAvatar->getOrientation(), _myAvatar->getPosition());
|
glm::mat4 modelMat = createMatFromQuatAndPos(_myAvatar->getOrientation(), _myAvatar->getPosition());
|
||||||
glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat;
|
glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat;
|
||||||
|
|
|
@ -475,7 +475,7 @@ private:
|
||||||
|
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
|
|
||||||
void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int index);
|
void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index);
|
||||||
void emulateMouse(Hand* hand, float click, float shift, int index);
|
void emulateMouse(Hand* hand, float click, float shift, int index);
|
||||||
|
|
||||||
// Various helper functions called during update()
|
// Various helper functions called during update()
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <plugins/PluginContainer.h>
|
||||||
|
|
||||||
class InputPlugin;
|
class InputPlugin;
|
||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
|
@ -464,26 +464,17 @@ Menu::Menu() {
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandLasers, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandLasers, 0, false);
|
||||||
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
|
||||||
|
qApp, SLOT(setLowVelocityFilter(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
||||||
|
|
||||||
MenuWrapper* sixenseOptionsMenu = handOptionsMenu->addMenu("Sixense");
|
MenuWrapper* sixenseOptionsMenu = handOptionsMenu->addMenu("Sixense");
|
||||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
|
|
||||||
MenuOption::SixenseEnabled,
|
|
||||||
0, false,
|
|
||||||
&SixenseManager::getInstance(),
|
|
||||||
SLOT(toggleSixense(bool)));
|
|
||||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
|
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
|
||||||
MenuOption::FilterSixense,
|
MenuOption::FilterSixense,
|
||||||
0,
|
0,
|
||||||
true,
|
true,
|
||||||
&SixenseManager::getInstance(),
|
&SixenseManager::getInstance(),
|
||||||
SLOT(setFilter(bool)));
|
SLOT(setFilter(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
|
|
||||||
MenuOption::LowVelocityFilter,
|
|
||||||
0,
|
|
||||||
true,
|
|
||||||
qApp,
|
|
||||||
SLOT(setLowVelocityFilter(bool)));
|
|
||||||
|
|
||||||
MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");
|
MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");
|
||||||
addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false);
|
addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false);
|
||||||
|
|
|
@ -181,8 +181,9 @@ void PreferencesDialog::loadPreferences() {
|
||||||
ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationCompositor().getHmdUIAngularSize());
|
ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationCompositor().getHmdUIAngularSize());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SixenseManager& sixense = SixenseManager::getInstance();
|
|
||||||
ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed());
|
ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed());
|
||||||
|
|
||||||
|
SixenseManager& sixense = SixenseManager::getInstance();
|
||||||
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
|
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
|
||||||
|
|
||||||
// LOD items
|
// LOD items
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
//
|
//
|
||||||
#include "InputDevice.h"
|
#include "InputDevice.h"
|
||||||
|
|
||||||
|
bool InputDevice::_lowVelocityFilter = false;
|
||||||
|
|
||||||
const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f;
|
const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f;
|
||||||
float InputDevice::reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED;
|
float InputDevice::reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
// Update call MUST be called once per simulation loop
|
// Update call MUST be called once per simulation loop
|
||||||
// It takes care of updating the action states and deltas
|
// It takes care of updating the action states and deltas
|
||||||
virtual void update(float deltaTime) = 0;
|
virtual void update(float deltaTime, bool jointsCaptured) = 0;
|
||||||
|
|
||||||
virtual void focusOutEvent() = 0;
|
virtual void focusOutEvent() = 0;
|
||||||
|
|
||||||
|
@ -44,6 +44,11 @@ public:
|
||||||
static float getReticleMoveSpeed() { return reticleMoveSpeed; }
|
static float getReticleMoveSpeed() { return reticleMoveSpeed; }
|
||||||
static void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { reticleMoveSpeed = sixenseReticleMoveSpeed; }
|
static void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { reticleMoveSpeed = sixenseReticleMoveSpeed; }
|
||||||
|
|
||||||
|
static bool getLowVelocityFilter() { return _lowVelocityFilter; };
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
static void setLowVelocityFilter(bool newLowVelocityFilter) { _lowVelocityFilter = newLowVelocityFilter; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _deviceID = 0;
|
int _deviceID = 0;
|
||||||
|
|
||||||
|
@ -53,6 +58,8 @@ protected:
|
||||||
AxisStateMap _axisStateMap;
|
AxisStateMap _axisStateMap;
|
||||||
PoseStateMap _poseStateMap;
|
PoseStateMap _poseStateMap;
|
||||||
|
|
||||||
|
static bool _lowVelocityFilter;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static float reticleMoveSpeed;
|
static float reticleMoveSpeed;
|
||||||
};
|
};
|
|
@ -15,6 +15,6 @@ public:
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() = 0;
|
virtual void pluginFocusOutEvent() = 0;
|
||||||
|
|
||||||
virtual void pluginUpdate(float deltaTime) = 0;
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ void Joystick::closeJoystick() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Joystick::update(float deltaTime) {
|
void Joystick::update(float deltaTime, bool jointsCaptured) {
|
||||||
for (auto axisState : _axisStateMap) {
|
for (auto axisState : _axisStateMap) {
|
||||||
if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) {
|
if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) {
|
||||||
_axisStateMap[axisState.first] = 0.0f;
|
_axisStateMap[axisState.first] = 0.0f;
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
// Device functions
|
// Device functions
|
||||||
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
||||||
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
||||||
virtual void update(float deltaTime) override;
|
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||||
virtual void focusOutEvent() override;
|
virtual void focusOutEvent() override;
|
||||||
|
|
||||||
Joystick() : InputDevice("Joystick") {}
|
Joystick() : InputDevice("Joystick") {}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
||||||
|
|
||||||
void KeyboardMouseDevice::update(float deltaTime) {
|
void KeyboardMouseDevice::update(float deltaTime, bool jointsCaptured) {
|
||||||
_axisStateMap.clear();
|
_axisStateMap.clear();
|
||||||
|
|
||||||
// For touch event, we need to check that the last event is not too long ago
|
// For touch event, we need to check that the last event is not too long ago
|
||||||
|
|
|
@ -65,12 +65,12 @@ public:
|
||||||
virtual void deactivate() override {};
|
virtual void deactivate() override {};
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
||||||
virtual void pluginUpdate(float deltaTime) override { update(deltaTime); }
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||||
|
|
||||||
// Device functions
|
// Device functions
|
||||||
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
||||||
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
||||||
virtual void update(float deltaTime) override;
|
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||||
virtual void focusOutEvent() override;
|
virtual void focusOutEvent() override;
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent* event);
|
void keyPressEvent(QKeyEvent* event);
|
||||||
|
|
|
@ -89,12 +89,12 @@ void SDL2Manager::pluginFocusOutEvent() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL2Manager::pluginUpdate(float deltaTime) {
|
void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) {
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
if (_isInitialized) {
|
if (_isInitialized) {
|
||||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
for (auto joystick : _openJoysticks) {
|
for (auto joystick : _openJoysticks) {
|
||||||
joystick->update(deltaTime);
|
joystick->update(deltaTime, jointsCaptured);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("SDL2Manager::update");
|
PerformanceTimer perfTimer("SDL2Manager::update");
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
virtual void deactivate() override {};
|
virtual void deactivate() override {};
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() override;
|
virtual void pluginFocusOutEvent() override;
|
||||||
virtual void pluginUpdate(float deltaTime) override;
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void joystickAdded(Joystick* joystick);
|
void joystickAdded(Joystick* joystick);
|
||||||
|
|
|
@ -61,8 +61,6 @@ SixenseManager::SixenseManager() :
|
||||||
#if defined(HAVE_SIXENSE) && defined(__APPLE__)
|
#if defined(HAVE_SIXENSE) && defined(__APPLE__)
|
||||||
_sixenseLibrary(NULL),
|
_sixenseLibrary(NULL),
|
||||||
#endif
|
#endif
|
||||||
_isInitialized(false),
|
|
||||||
_isEnabled(true),
|
|
||||||
_hydrasConnected(false)
|
_hydrasConnected(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -76,11 +74,8 @@ bool SixenseManager::isSupported() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::init() {
|
void SixenseManager::activate(PluginContainer* container) {
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
|
|
||||||
if (!_isInitialized) {
|
|
||||||
_lowVelocityFilter = false;
|
|
||||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||||
// By default we assume the _neckBase (in orb frame) is as high above the orb
|
// By default we assume the _neckBase (in orb frame) is as high above the orb
|
||||||
// as the "torso" is below it.
|
// as the "torso" is below it.
|
||||||
|
@ -112,23 +107,17 @@ void SixenseManager::init() {
|
||||||
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
|
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
|
||||||
#endif
|
#endif
|
||||||
sixenseInit();
|
sixenseInit();
|
||||||
|
|
||||||
_isInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::deinit() {
|
void SixenseManager::deinit() {
|
||||||
#ifdef HAVE_SIXENSE_
|
#ifdef HAVE_SIXENSE_
|
||||||
|
|
||||||
if (_isInitialized) {
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit");
|
SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sixenseExit();
|
sixenseExit();
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
delete _sixenseLibrary;
|
delete _sixenseLibrary;
|
||||||
|
@ -139,26 +128,16 @@ void SixenseManager::deinit() {
|
||||||
|
|
||||||
void SixenseManager::setFilter(bool filter) {
|
void SixenseManager::setFilter(bool filter) {
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
|
|
||||||
if (_isInitialized) {
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
|
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
|
||||||
#endif
|
#endif
|
||||||
|
int newFilter = filter ? 1 : 0;
|
||||||
if (filter) {
|
sixenseSetFilterEnabled(newFilter);
|
||||||
sixenseSetFilterEnabled(1);
|
|
||||||
} else {
|
|
||||||
sixenseSetFilterEnabled(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::update(float deltaTime) {
|
void SixenseManager::update(float deltaTime, bool jointsCaptured) {
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
//Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
|
||||||
if (_isInitialized && _isEnabled) {
|
|
||||||
_buttonPressedMap.clear();
|
_buttonPressedMap.clear();
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
@ -182,7 +161,7 @@ void SixenseManager::update(float deltaTime) {
|
||||||
if (!_hydrasConnected) {
|
if (!_hydrasConnected) {
|
||||||
_hydrasConnected = true;
|
_hydrasConnected = true;
|
||||||
registerToUserInputMapper(*userInputMapper);
|
registerToUserInputMapper(*userInputMapper);
|
||||||
getInstance().assignDefaultInputMapping(*userInputMapper);
|
assignDefaultInputMapping(*userInputMapper);
|
||||||
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
|
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +182,7 @@ void SixenseManager::update(float deltaTime) {
|
||||||
SixenseTakeIntAndSixenseControllerData sixenseGetNewestData =
|
SixenseTakeIntAndSixenseControllerData sixenseGetNewestData =
|
||||||
(SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData");
|
(SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData");
|
||||||
#endif
|
#endif
|
||||||
int numControllersAtBase = 0;
|
|
||||||
int numActiveControllers = 0;
|
int numActiveControllers = 0;
|
||||||
for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) {
|
for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) {
|
||||||
if (!sixenseIsControllerEnabled(i)) {
|
if (!sixenseIsControllerEnabled(i)) {
|
||||||
|
@ -213,26 +192,6 @@ void SixenseManager::update(float deltaTime) {
|
||||||
++numActiveControllers;
|
++numActiveControllers;
|
||||||
sixenseGetNewestData(i, data);
|
sixenseGetNewestData(i, data);
|
||||||
|
|
||||||
// Set palm position and normal based on Hydra position/orientation
|
|
||||||
|
|
||||||
// // Either find a palm matching the sixense controller, or make a new one
|
|
||||||
// PalmData* palm;
|
|
||||||
// bool foundHand = false;
|
|
||||||
// for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
|
||||||
// if (hand->getPalms()[j].getSixenseID() == data->controller_index) {
|
|
||||||
// palm = &(hand->getPalms()[j]);
|
|
||||||
// _prevPalms[numActiveControllers - 1] = palm;
|
|
||||||
// foundHand = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (!foundHand) {
|
|
||||||
// PalmData newPalm(hand);
|
|
||||||
// hand->getPalms().push_back(newPalm);
|
|
||||||
// palm = &(hand->getPalms()[hand->getNumPalms() - 1]);
|
|
||||||
// palm->setSixenseID(data->controller_index);
|
|
||||||
// _prevPalms[numActiveControllers - 1] = palm;
|
|
||||||
// qCDebug(interfaceapp, "Found new Sixense controller, ID %i", data->controller_index);
|
|
||||||
// }
|
|
||||||
// NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters.
|
// NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters.
|
||||||
glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]);
|
glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]);
|
||||||
position *= METERS_PER_MILLIMETER;
|
position *= METERS_PER_MILLIMETER;
|
||||||
|
@ -247,34 +206,24 @@ void SixenseManager::update(float deltaTime) {
|
||||||
glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]);
|
glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]);
|
||||||
rotation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)) * _orbRotation * rotation;
|
rotation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)) * _orbRotation * rotation;
|
||||||
|
|
||||||
|
if (!jointsCaptured) {
|
||||||
handlePoseEvent(position, rotation, numActiveControllers - 1);
|
handlePoseEvent(position, rotation, numActiveControllers - 1);
|
||||||
|
} else {
|
||||||
|
_poseStateMap.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_poseStateMap[(numActiveControllers - 1) == 0 ? LEFT_HAND : RIGHT_HAND] = UserInputMapper::PoseValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Disable the hands (and return to default pose) if both controllers are at base station
|
|
||||||
// if (foundHand) {
|
|
||||||
// palm->setActive(!_controllersAtBase);
|
|
||||||
// } else {
|
|
||||||
// palm->setActive(false); // if this isn't a Sixsense ID palm, always make it inactive
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Read controller buttons and joystick into the hand
|
// // Read controller buttons and joystick into the hand
|
||||||
// palm->setControllerButtons(data->buttons);
|
// palm->setControllerButtons(data->buttons);
|
||||||
// palm->setTrigger(data->trigger);
|
// palm->setTrigger(data->trigger);
|
||||||
// palm->setJoystick(data->joystick_x, data->joystick_y);
|
// palm->setJoystick(data->joystick_x, data->joystick_y);
|
||||||
|
|
||||||
//handleButtonEvent(data->buttons, numActiveControllers - 1);
|
|
||||||
//handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1);
|
|
||||||
|
|
||||||
// // Emulate the mouse so we can use scripts
|
|
||||||
// if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput) && !_controllersAtBase) {
|
|
||||||
// emulateMouse(palm, numActiveControllers - 1);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numActiveControllers == 2) {
|
if (numActiveControllers == 2) {
|
||||||
updateCalibration(controllers);
|
updateCalibration(controllers);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (auto axisState : _axisStateMap) {
|
for (auto axisState : _axisStateMap) {
|
||||||
if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) {
|
if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) {
|
||||||
|
@ -284,15 +233,6 @@ void SixenseManager::update(float deltaTime) {
|
||||||
#endif // HAVE_SIXENSE
|
#endif // HAVE_SIXENSE
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::toggleSixense(bool shouldEnable) {
|
|
||||||
if (shouldEnable && !isInitialized()) {
|
|
||||||
init();
|
|
||||||
//setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
|
||||||
//setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter));
|
|
||||||
}
|
|
||||||
setIsEnabled(shouldEnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
|
|
||||||
// the calibration sequence is:
|
// the calibration sequence is:
|
||||||
|
@ -483,56 +423,10 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int
|
||||||
neck.y = 0.0f;
|
neck.y = 0.0f;
|
||||||
position = _orbRotation * (position - neck);
|
position = _orbRotation * (position - neck);
|
||||||
|
|
||||||
// // Compute current velocity from position change
|
|
||||||
// glm::vec3 rawVelocity;
|
|
||||||
// if (deltaTime > 0.0f) {
|
|
||||||
// rawVelocity = (position - palm->getRawPosition()) / deltaTime;
|
|
||||||
// } else {
|
|
||||||
// rawVelocity = glm::vec3(0.0f);
|
|
||||||
// }
|
|
||||||
// palm->setRawVelocity(rawVelocity); // meters/sec
|
|
||||||
|
|
||||||
// adjustment for hydra controllers fit into hands
|
// adjustment for hydra controllers fit into hands
|
||||||
float sign = (index == 0) ? -1.0f : 1.0f;
|
float sign = (index == 0) ? -1.0f : 1.0f;
|
||||||
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
|
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
// // Angular Velocity of Palm
|
|
||||||
// glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation());
|
|
||||||
// glm::vec3 angularVelocity(0.0f);
|
|
||||||
// float rotationAngle = glm::angle(deltaRotation);
|
|
||||||
// if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) {
|
|
||||||
// angularVelocity = glm::normalize(glm::axis(deltaRotation));
|
|
||||||
// angularVelocity *= (rotationAngle / deltaTime);
|
|
||||||
// palm->setRawAngularVelocity(angularVelocity);
|
|
||||||
// } else {
|
|
||||||
// palm->setRawAngularVelocity(glm::vec3(0.0f));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (_lowVelocityFilter) {
|
|
||||||
// // Use a velocity sensitive filter to damp small motions and preserve large ones with
|
|
||||||
// // no latency.
|
|
||||||
// float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
|
|
||||||
// position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter);
|
|
||||||
// rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter);
|
|
||||||
// palm->setRawPosition(position);
|
|
||||||
// palm->setRawRotation(rotation);
|
|
||||||
// } else {
|
|
||||||
// palm->setRawPosition(position);
|
|
||||||
// palm->setRawRotation(rotation);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Store the one fingertip in the palm structure so we can track velocity
|
|
||||||
// const float FINGER_LENGTH = 0.3f; // meters
|
|
||||||
// const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH);
|
|
||||||
// const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR;
|
|
||||||
// glm::vec3 oldTipPosition = palm->getTipRawPosition();
|
|
||||||
// if (deltaTime > 0.0f) {
|
|
||||||
// palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime);
|
|
||||||
// } else {
|
|
||||||
// palm->setTipVelocity(glm::vec3(0.0f));
|
|
||||||
// }
|
|
||||||
// palm->setTipPosition(newTipPosition);
|
|
||||||
|
|
||||||
_poseStateMap[makeInput(JointChannel(index)).getChannel()] = UserInputMapper::PoseValue(position, rotation);
|
_poseStateMap[makeInput(JointChannel(index)).getChannel()] = UserInputMapper::PoseValue(position, rotation);
|
||||||
#endif // HAVE_SIXENSE
|
#endif // HAVE_SIXENSE
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,24 +62,19 @@ public:
|
||||||
virtual bool isJointController() const override { return true; }
|
virtual bool isJointController() const override { return true; }
|
||||||
const QString& getName() const { return NAME; }
|
const QString& getName() const { return NAME; }
|
||||||
|
|
||||||
virtual void init() override;
|
|
||||||
virtual void deinit() override;
|
virtual void deinit() override;
|
||||||
virtual void activate(PluginContainer * container) override {};
|
virtual void activate(PluginContainer * container) override;
|
||||||
virtual void deactivate() override { _poseStateMap.clear(); };
|
virtual void deactivate() override { _poseStateMap.clear(); }
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
||||||
virtual void pluginUpdate(float deltaTime) override { update(deltaTime); }
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||||
|
|
||||||
// Device functions
|
// Device functions
|
||||||
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
||||||
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
||||||
virtual void update(float deltaTime) override;
|
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||||
virtual void focusOutEvent() override;
|
virtual void focusOutEvent() override;
|
||||||
|
|
||||||
bool isInitialized() const { return _isInitialized; }
|
|
||||||
|
|
||||||
void setIsEnabled(bool isEnabled) { _isEnabled = isEnabled; }
|
|
||||||
|
|
||||||
bool getInvertButtons() const { return _invertButtons; }
|
bool getInvertButtons() const { return _invertButtons; }
|
||||||
void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; }
|
void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; }
|
||||||
|
|
||||||
|
@ -88,9 +83,7 @@ public:
|
||||||
UserInputMapper::Input makeInput(JointChannel joint);
|
UserInputMapper::Input makeInput(JointChannel joint);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void toggleSixense(bool shouldEnable);
|
|
||||||
void setFilter(bool filter);
|
void setFilter(bool filter);
|
||||||
void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleButtonEvent(unsigned int buttons, int index);
|
void handleButtonEvent(unsigned int buttons, int index);
|
||||||
|
@ -122,12 +115,8 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
bool _isInitialized;
|
|
||||||
bool _isEnabled;
|
|
||||||
bool _hydrasConnected;
|
bool _hydrasConnected;
|
||||||
|
|
||||||
bool _lowVelocityFilter;
|
|
||||||
|
|
||||||
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
|
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
|
||||||
|
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
|
|
|
@ -192,7 +192,9 @@ void UserInputMapper::update(float deltaTime) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ChannelType::POSE: {
|
case ChannelType::POSE: {
|
||||||
|
if (!_poseStates[channelInput.first].isValid()) {
|
||||||
_poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp);
|
_poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|
|
@ -186,7 +186,8 @@ void ViveControllerManager::renderHand(UserInputMapper::PoseValue pose, gpu::Bat
|
||||||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViveControllerManager::update(float deltaTime) {
|
void ViveControllerManager::update(float deltaTime, bool jointsCaptured) {
|
||||||
|
_poseStateMap.clear();
|
||||||
// TODO: This shouldn't be necessary
|
// TODO: This shouldn't be necessary
|
||||||
if (!_hmd) {
|
if (!_hmd) {
|
||||||
return;
|
return;
|
||||||
|
@ -217,7 +218,9 @@ void ViveControllerManager::update(float deltaTime) {
|
||||||
|
|
||||||
const mat4& mat = _trackedDevicePoseMat4[device];
|
const mat4& mat = _trackedDevicePoseMat4[device];
|
||||||
|
|
||||||
|
if (!jointsCaptured) {
|
||||||
handlePoseEvent(mat, numTrackedControllers - 1);
|
handlePoseEvent(mat, numTrackedControllers - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// handle inputs
|
// handle inputs
|
||||||
vr::VRControllerState_t controllerState = vr::VRControllerState_t();
|
vr::VRControllerState_t controllerState = vr::VRControllerState_t();
|
||||||
|
|
|
@ -59,12 +59,12 @@ public:
|
||||||
virtual void deactivate() override;
|
virtual void deactivate() override;
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
||||||
virtual void pluginUpdate(float deltaTime) override { update(deltaTime); }
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||||
|
|
||||||
// Device functions
|
// Device functions
|
||||||
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
virtual void registerToUserInputMapper(UserInputMapper& mapper) override;
|
||||||
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
virtual void assignDefaultInputMapping(UserInputMapper& mapper) override;
|
||||||
virtual void update(float deltaTime) override;
|
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||||
virtual void focusOutEvent() override;
|
virtual void focusOutEvent() override;
|
||||||
|
|
||||||
void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges);
|
void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class GlWindow;
|
class GlWindow;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue