mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 08:14:48 +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 <input-plugins/InputPlugin.h>
|
||||
#include <input-plugins/Joystick.h> // this should probably be removed
|
||||
#include <input-plugins/SixenseManager.h> // this definitely should be removed
|
||||
#include <LogHandler.h>
|
||||
#include <MainWindow.h>
|
||||
#include <MessageDialog.h>
|
||||
|
@ -2130,7 +2129,7 @@ void Application::setEnableVRMode(bool enableVRMode) {
|
|||
#endif
|
||||
|
||||
void Application::setLowVelocityFilter(bool lowVelocityFilter) {
|
||||
SixenseManager::getInstance().setLowVelocityFilter(lowVelocityFilter);
|
||||
InputDevice::setLowVelocityFilter(lowVelocityFilter);
|
||||
}
|
||||
|
||||
bool Application::mouseOnScreen() const {
|
||||
|
@ -2364,18 +2363,7 @@ void Application::init() {
|
|||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
|
||||
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();
|
||||
RealSense::init();
|
||||
|
||||
|
@ -2683,12 +2671,17 @@ void Application::update(float deltaTime) {
|
|||
userInputMapper->setSensorToWorldMat(_myAvatar->getSensorToWorldMatrix());
|
||||
userInputMapper->update(deltaTime);
|
||||
|
||||
// This needs to go after userInputMapper->update() because of the keyboard
|
||||
bool jointsCaptured = false;
|
||||
auto inputPlugins = getInputPlugins();
|
||||
foreach(auto inputPlugin, inputPlugins) {
|
||||
QString name = inputPlugin->getName();
|
||||
QAction* action = Menu::getInstance()->getActionForOption(name);
|
||||
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 rightHand = userInputMapper->getPoseState(UserInputMapper::RIGHT_HAND);
|
||||
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
||||
setPalmData(hand, leftHand, LEFT_HAND_INDEX);
|
||||
setPalmData(hand, rightHand, RIGHT_HAND_INDEX);
|
||||
setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX);
|
||||
setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX);
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
||||
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
|
||||
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
||||
|
@ -2869,7 +2862,7 @@ void Application::update(float deltaTime) {
|
|||
_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;
|
||||
bool foundHand = false;
|
||||
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
||||
|
@ -2887,12 +2880,54 @@ void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int i
|
|||
}
|
||||
|
||||
palm->setActive(pose.isValid());
|
||||
|
||||
glm::vec3 position = pose.getTranslation();
|
||||
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
|
||||
|
||||
// TODO: velocity filters, tip velocities, etc.
|
||||
// see SixenseManager
|
||||
// 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.
|
||||
glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation());
|
||||
glm::mat4 poseMat = createMatFromQuatAndPos(rotation, position);
|
||||
glm::mat4 sensorToWorldMat = _myAvatar->getSensorToWorldMatrix();
|
||||
glm::mat4 modelMat = createMatFromQuatAndPos(_myAvatar->getOrientation(), _myAvatar->getPosition());
|
||||
glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat;
|
||||
|
|
|
@ -475,7 +475,7 @@ private:
|
|||
|
||||
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);
|
||||
|
||||
// Various helper functions called during update()
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include <plugins/PluginContainer.h>
|
||||
|
||||
class InputPlugin;
|
||||
|
||||
#include <QVector>
|
||||
|
|
|
@ -464,26 +464,17 @@ Menu::Menu() {
|
|||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandLasers, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
|
||||
qApp, SLOT(setLowVelocityFilter(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
||||
|
||||
MenuWrapper* sixenseOptionsMenu = handOptionsMenu->addMenu("Sixense");
|
||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
|
||||
MenuOption::SixenseEnabled,
|
||||
0, false,
|
||||
&SixenseManager::getInstance(),
|
||||
SLOT(toggleSixense(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
|
||||
MenuOption::FilterSixense,
|
||||
0,
|
||||
true,
|
||||
&SixenseManager::getInstance(),
|
||||
SLOT(setFilter(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
|
||||
MenuOption::LowVelocityFilter,
|
||||
0,
|
||||
true,
|
||||
qApp,
|
||||
SLOT(setLowVelocityFilter(bool)));
|
||||
|
||||
MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");
|
||||
addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false);
|
||||
|
|
|
@ -181,8 +181,9 @@ void PreferencesDialog::loadPreferences() {
|
|||
ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationCompositor().getHmdUIAngularSize());
|
||||
#endif
|
||||
|
||||
SixenseManager& sixense = SixenseManager::getInstance();
|
||||
ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed());
|
||||
|
||||
SixenseManager& sixense = SixenseManager::getInstance();
|
||||
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
|
||||
|
||||
// LOD items
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
#include "InputDevice.h"
|
||||
|
||||
bool InputDevice::_lowVelocityFilter = false;
|
||||
|
||||
const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f;
|
||||
float InputDevice::reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
|
||||
// Update call MUST be called once per simulation loop
|
||||
// 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;
|
||||
|
||||
|
@ -44,6 +44,11 @@ public:
|
|||
static float getReticleMoveSpeed() { return reticleMoveSpeed; }
|
||||
static void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { reticleMoveSpeed = sixenseReticleMoveSpeed; }
|
||||
|
||||
static bool getLowVelocityFilter() { return _lowVelocityFilter; };
|
||||
|
||||
public slots:
|
||||
static void setLowVelocityFilter(bool newLowVelocityFilter) { _lowVelocityFilter = newLowVelocityFilter; };
|
||||
|
||||
protected:
|
||||
int _deviceID = 0;
|
||||
|
||||
|
@ -53,6 +58,8 @@ protected:
|
|||
AxisStateMap _axisStateMap;
|
||||
PoseStateMap _poseStateMap;
|
||||
|
||||
static bool _lowVelocityFilter;
|
||||
|
||||
private:
|
||||
static float reticleMoveSpeed;
|
||||
};
|
|
@ -15,6 +15,6 @@ public:
|
|||
|
||||
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
|
||||
}
|
||||
|
||||
void Joystick::update(float deltaTime) {
|
||||
void Joystick::update(float deltaTime, bool jointsCaptured) {
|
||||
for (auto axisState : _axisStateMap) {
|
||||
if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) {
|
||||
_axisStateMap[axisState.first] = 0.0f;
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
// Device functions
|
||||
virtual void registerToUserInputMapper(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;
|
||||
|
||||
Joystick() : InputDevice("Joystick") {}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
||||
|
||||
void KeyboardMouseDevice::update(float deltaTime) {
|
||||
void KeyboardMouseDevice::update(float deltaTime, bool jointsCaptured) {
|
||||
_axisStateMap.clear();
|
||||
|
||||
// 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 pluginFocusOutEvent() override { focusOutEvent(); }
|
||||
virtual void pluginUpdate(float deltaTime) override { update(deltaTime); }
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||
|
||||
// Device functions
|
||||
virtual void registerToUserInputMapper(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;
|
||||
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
|
|
@ -89,12 +89,12 @@ void SDL2Manager::pluginFocusOutEvent() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void SDL2Manager::pluginUpdate(float deltaTime) {
|
||||
void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) {
|
||||
#ifdef HAVE_SDL2
|
||||
if (_isInitialized) {
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
for (auto joystick : _openJoysticks) {
|
||||
joystick->update(deltaTime);
|
||||
joystick->update(deltaTime, jointsCaptured);
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("SDL2Manager::update");
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
virtual void deactivate() override {};
|
||||
|
||||
virtual void pluginFocusOutEvent() override;
|
||||
virtual void pluginUpdate(float deltaTime) override;
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
||||
|
||||
signals:
|
||||
void joystickAdded(Joystick* joystick);
|
||||
|
|
|
@ -61,8 +61,6 @@ SixenseManager::SixenseManager() :
|
|||
#if defined(HAVE_SIXENSE) && defined(__APPLE__)
|
||||
_sixenseLibrary(NULL),
|
||||
#endif
|
||||
_isInitialized(false),
|
||||
_isEnabled(true),
|
||||
_hydrasConnected(false)
|
||||
{
|
||||
|
||||
|
@ -76,59 +74,50 @@ bool SixenseManager::isSupported() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
void SixenseManager::init() {
|
||||
void SixenseManager::activate(PluginContainer* container) {
|
||||
#ifdef HAVE_SIXENSE
|
||||
|
||||
if (!_isInitialized) {
|
||||
_lowVelocityFilter = false;
|
||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
// By default we assume the _neckBase (in orb frame) is as high above the orb
|
||||
// as the "torso" is below it.
|
||||
_neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z);
|
||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
// By default we assume the _neckBase (in orb frame) is as high above the orb
|
||||
// as the "torso" is below it.
|
||||
_neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
if (!_sixenseLibrary) {
|
||||
if (!_sixenseLibrary) {
|
||||
|
||||
#ifdef SIXENSE_LIB_FILENAME
|
||||
_sixenseLibrary = new QLibrary(SIXENSE_LIB_FILENAME);
|
||||
_sixenseLibrary = new QLibrary(SIXENSE_LIB_FILENAME);
|
||||
#else
|
||||
const QString SIXENSE_LIBRARY_NAME = "libsixense_x64";
|
||||
QString frameworkSixenseLibrary = QCoreApplication::applicationDirPath() + "/../Frameworks/"
|
||||
+ SIXENSE_LIBRARY_NAME;
|
||||
const QString SIXENSE_LIBRARY_NAME = "libsixense_x64";
|
||||
QString frameworkSixenseLibrary = QCoreApplication::applicationDirPath() + "/../Frameworks/"
|
||||
+ SIXENSE_LIBRARY_NAME;
|
||||
|
||||
_sixenseLibrary = new QLibrary(frameworkSixenseLibrary);
|
||||
_sixenseLibrary = new QLibrary(frameworkSixenseLibrary);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (_sixenseLibrary->load()){
|
||||
qCDebug(interfaceapp) << "Loaded sixense library for hydra support -" << _sixenseLibrary->fileName();
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Sixense library at" << _sixenseLibrary->fileName() << "failed to load."
|
||||
<< "Continuing without hydra support.";
|
||||
return;
|
||||
}
|
||||
|
||||
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
|
||||
#endif
|
||||
sixenseInit();
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
if (_sixenseLibrary->load()){
|
||||
qCDebug(interfaceapp) << "Loaded sixense library for hydra support -" << _sixenseLibrary->fileName();
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Sixense library at" << _sixenseLibrary->fileName() << "failed to load."
|
||||
<< "Continuing without hydra support.";
|
||||
return;
|
||||
}
|
||||
|
||||
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
|
||||
#endif
|
||||
sixenseInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SixenseManager::deinit() {
|
||||
#ifdef HAVE_SIXENSE_
|
||||
|
||||
if (_isInitialized) {
|
||||
#ifdef __APPLE__
|
||||
SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit");
|
||||
SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit");
|
||||
#endif
|
||||
|
||||
sixenseExit();
|
||||
}
|
||||
sixenseExit();
|
||||
|
||||
#ifdef __APPLE__
|
||||
delete _sixenseLibrary;
|
||||
|
@ -139,141 +128,101 @@ void SixenseManager::deinit() {
|
|||
|
||||
void SixenseManager::setFilter(bool filter) {
|
||||
#ifdef HAVE_SIXENSE
|
||||
|
||||
if (_isInitialized) {
|
||||
#ifdef __APPLE__
|
||||
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
|
||||
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
|
||||
#endif
|
||||
|
||||
if (filter) {
|
||||
sixenseSetFilterEnabled(1);
|
||||
} else {
|
||||
sixenseSetFilterEnabled(0);
|
||||
}
|
||||
}
|
||||
|
||||
int newFilter = filter ? 1 : 0;
|
||||
sixenseSetFilterEnabled(newFilter);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SixenseManager::update(float deltaTime) {
|
||||
void SixenseManager::update(float deltaTime, bool jointsCaptured) {
|
||||
#ifdef HAVE_SIXENSE
|
||||
//Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
||||
if (_isInitialized && _isEnabled) {
|
||||
_buttonPressedMap.clear();
|
||||
_buttonPressedMap.clear();
|
||||
|
||||
#ifdef __APPLE__
|
||||
SixenseBaseFunction sixenseGetNumActiveControllers =
|
||||
(SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers");
|
||||
SixenseBaseFunction sixenseGetNumActiveControllers =
|
||||
(SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers");
|
||||
#endif
|
||||
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
|
||||
if (sixenseGetNumActiveControllers() == 0) {
|
||||
_hydrasConnected = false;
|
||||
if (_deviceID != 0) {
|
||||
userInputMapper->removeDevice(_deviceID);
|
||||
_deviceID = 0;
|
||||
if (sixenseGetNumActiveControllers() == 0) {
|
||||
_hydrasConnected = false;
|
||||
if (_deviceID != 0) {
|
||||
userInputMapper->removeDevice(_deviceID);
|
||||
_deviceID = 0;
|
||||
_poseStateMap.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("sixense");
|
||||
if (!_hydrasConnected) {
|
||||
_hydrasConnected = true;
|
||||
registerToUserInputMapper(*userInputMapper);
|
||||
assignDefaultInputMapping(*userInputMapper);
|
||||
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
SixenseBaseFunction sixenseGetMaxControllers =
|
||||
(SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetMaxControllers");
|
||||
#endif
|
||||
|
||||
int maxControllers = sixenseGetMaxControllers();
|
||||
|
||||
// we only support two controllers
|
||||
sixenseControllerData controllers[2];
|
||||
|
||||
#ifdef __APPLE__
|
||||
SixenseTakeIntFunction sixenseIsControllerEnabled =
|
||||
(SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseIsControllerEnabled");
|
||||
|
||||
SixenseTakeIntAndSixenseControllerData sixenseGetNewestData =
|
||||
(SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData");
|
||||
#endif
|
||||
|
||||
int numActiveControllers = 0;
|
||||
for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) {
|
||||
if (!sixenseIsControllerEnabled(i)) {
|
||||
continue;
|
||||
}
|
||||
sixenseControllerData* data = controllers + numActiveControllers;
|
||||
++numActiveControllers;
|
||||
sixenseGetNewestData(i, data);
|
||||
|
||||
// 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]);
|
||||
position *= METERS_PER_MILLIMETER;
|
||||
|
||||
// Check to see if this hand/controller is on the base
|
||||
const float CONTROLLER_AT_BASE_DISTANCE = 0.075f;
|
||||
if (glm::length(position) >= CONTROLLER_AT_BASE_DISTANCE) {
|
||||
handleButtonEvent(data->buttons, numActiveControllers - 1);
|
||||
handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1);
|
||||
|
||||
// Rotation of Palm
|
||||
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;
|
||||
|
||||
if (!jointsCaptured) {
|
||||
handlePoseEvent(position, rotation, numActiveControllers - 1);
|
||||
} else {
|
||||
_poseStateMap.clear();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
_poseStateMap[(numActiveControllers - 1) == 0 ? LEFT_HAND : RIGHT_HAND] = UserInputMapper::PoseValue();
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("sixense");
|
||||
if (!_hydrasConnected) {
|
||||
_hydrasConnected = true;
|
||||
registerToUserInputMapper(*userInputMapper);
|
||||
getInstance().assignDefaultInputMapping(*userInputMapper);
|
||||
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
SixenseBaseFunction sixenseGetMaxControllers =
|
||||
(SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetMaxControllers");
|
||||
#endif
|
||||
|
||||
int maxControllers = sixenseGetMaxControllers();
|
||||
|
||||
// we only support two controllers
|
||||
sixenseControllerData controllers[2];
|
||||
|
||||
#ifdef __APPLE__
|
||||
SixenseTakeIntFunction sixenseIsControllerEnabled =
|
||||
(SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseIsControllerEnabled");
|
||||
|
||||
SixenseTakeIntAndSixenseControllerData sixenseGetNewestData =
|
||||
(SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData");
|
||||
#endif
|
||||
int numControllersAtBase = 0;
|
||||
int numActiveControllers = 0;
|
||||
for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) {
|
||||
if (!sixenseIsControllerEnabled(i)) {
|
||||
continue;
|
||||
}
|
||||
sixenseControllerData* data = controllers + numActiveControllers;
|
||||
++numActiveControllers;
|
||||
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.
|
||||
glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]);
|
||||
position *= METERS_PER_MILLIMETER;
|
||||
|
||||
// Check to see if this hand/controller is on the base
|
||||
const float CONTROLLER_AT_BASE_DISTANCE = 0.075f;
|
||||
if (glm::length(position) >= CONTROLLER_AT_BASE_DISTANCE) {
|
||||
handleButtonEvent(data->buttons, numActiveControllers - 1);
|
||||
handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1);
|
||||
|
||||
// Rotation of Palm
|
||||
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;
|
||||
|
||||
handlePoseEvent(position, rotation, numActiveControllers - 1);
|
||||
}
|
||||
|
||||
// // 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
|
||||
// palm->setControllerButtons(data->buttons);
|
||||
// palm->setTrigger(data->trigger);
|
||||
// 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) {
|
||||
updateCalibration(controllers);
|
||||
}
|
||||
if (numActiveControllers == 2) {
|
||||
updateCalibration(controllers);
|
||||
}
|
||||
|
||||
for (auto axisState : _axisStateMap) {
|
||||
|
@ -284,15 +233,6 @@ void SixenseManager::update(float deltaTime) {
|
|||
#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
|
||||
|
||||
// the calibration sequence is:
|
||||
|
@ -483,56 +423,10 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int
|
|||
neck.y = 0.0f;
|
||||
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
|
||||
float sign = (index == 0) ? -1.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);
|
||||
#endif // HAVE_SIXENSE
|
||||
}
|
||||
|
|
|
@ -62,24 +62,19 @@ public:
|
|||
virtual bool isJointController() const override { return true; }
|
||||
const QString& getName() const { return NAME; }
|
||||
|
||||
virtual void init() override;
|
||||
virtual void deinit() override;
|
||||
virtual void activate(PluginContainer * container) override {};
|
||||
virtual void deactivate() override { _poseStateMap.clear(); };
|
||||
virtual void activate(PluginContainer * container) override;
|
||||
virtual void deactivate() override { _poseStateMap.clear(); }
|
||||
|
||||
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
|
||||
virtual void registerToUserInputMapper(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;
|
||||
|
||||
bool isInitialized() const { return _isInitialized; }
|
||||
|
||||
void setIsEnabled(bool isEnabled) { _isEnabled = isEnabled; }
|
||||
|
||||
bool getInvertButtons() const { return _invertButtons; }
|
||||
void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; }
|
||||
|
||||
|
@ -88,9 +83,7 @@ public:
|
|||
UserInputMapper::Input makeInput(JointChannel joint);
|
||||
|
||||
public slots:
|
||||
void toggleSixense(bool shouldEnable);
|
||||
void setFilter(bool filter);
|
||||
void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; };
|
||||
|
||||
private:
|
||||
void handleButtonEvent(unsigned int buttons, int index);
|
||||
|
@ -122,11 +115,7 @@ private:
|
|||
#endif
|
||||
|
||||
#endif
|
||||
bool _isInitialized;
|
||||
bool _isEnabled;
|
||||
bool _hydrasConnected;
|
||||
|
||||
bool _lowVelocityFilter;
|
||||
|
||||
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
|
||||
|
||||
|
|
|
@ -192,7 +192,9 @@ void UserInputMapper::update(float deltaTime) {
|
|||
break;
|
||||
}
|
||||
case ChannelType::POSE: {
|
||||
_poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp);
|
||||
if (!_poseStates[channelInput.first].isValid()) {
|
||||
_poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -186,7 +186,8 @@ void ViveControllerManager::renderHand(UserInputMapper::PoseValue pose, gpu::Bat
|
|||
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
|
||||
if (!_hmd) {
|
||||
return;
|
||||
|
@ -216,8 +217,10 @@ void ViveControllerManager::update(float deltaTime) {
|
|||
numTrackedControllers++;
|
||||
|
||||
const mat4& mat = _trackedDevicePoseMat4[device];
|
||||
|
||||
handlePoseEvent(mat, numTrackedControllers - 1);
|
||||
|
||||
if (!jointsCaptured) {
|
||||
handlePoseEvent(mat, numTrackedControllers - 1);
|
||||
}
|
||||
|
||||
// handle inputs
|
||||
vr::VRControllerState_t controllerState = vr::VRControllerState_t();
|
||||
|
|
|
@ -59,12 +59,12 @@ public:
|
|||
virtual void deactivate() override;
|
||||
|
||||
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
|
||||
virtual void registerToUserInputMapper(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;
|
||||
|
||||
void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
|
||||
class GlWindow;
|
||||
|
||||
|
|
Loading…
Reference in a new issue