overte/interface/src/devices/SixenseManager.cpp
2014-03-12 12:29:01 -07:00

139 lines
4.9 KiB
C++

//
// Sixense.cpp
// interface
//
// Created by Andrzej Kapolka on 11/15/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifdef HAVE_SIXENSE
#include "sixense.h"
#endif
#include "Application.h"
#include "SixenseManager.h"
using namespace std;
SixenseManager::SixenseManager() : _lastMovement(0) {
#ifdef HAVE_SIXENSE
sixenseInit();
#endif
}
SixenseManager::~SixenseManager() {
#ifdef HAVE_SIXENSE
sixenseExit();
#endif
}
void SixenseManager::setFilter(bool filter) {
#ifdef HAVE_SIXENSE
if (filter) {
qDebug("Sixense Filter ON");
sixenseSetFilterEnabled(1);
} else {
qDebug("Sixense Filter OFF");
sixenseSetFilterEnabled(0);
}
#endif
}
void SixenseManager::update(float deltaTime) {
#ifdef HAVE_SIXENSE
if (sixenseGetNumActiveControllers() == 0) {
return;
}
MyAvatar* avatar = Application::getInstance()->getAvatar();
Hand* hand = avatar->getHand();
int maxControllers = sixenseGetMaxControllers();
for (int i = 0; i < maxControllers; i++) {
if (!sixenseIsControllerEnabled(i)) {
continue;
}
sixenseControllerData 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]);
foundHand = true;
}
}
if (!foundHand) {
PalmData newPalm(hand);
hand->getPalms().push_back(newPalm);
palm = &(hand->getPalms()[hand->getNumPalms() - 1]);
palm->setSixenseID(data.controller_index);
printf("Found new Sixense controller, ID %i\n", data.controller_index);
}
palm->setActive(true);
// Read controller buttons and joystick into the hand
palm->setControllerButtons(data.buttons);
palm->setTrigger(data.trigger);
palm->setJoystick(data.joystick_x, data.joystick_y);
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
// Adjust for distance between acquisition 'orb' and the user's torso
// (distance to the right of body center, distance below torso, distance behind torso)
const glm::vec3 SPHERE_TO_TORSO(-250.f, -300.f, -300.f);
position = SPHERE_TO_TORSO + position;
// 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.f, 1.f, 0.f)) * rotation;
const glm::vec3 PALM_VECTOR(0.0f, -1.0f, 0.0f);
glm::vec3 newNormal = rotation * PALM_VECTOR;
palm->setRawNormal(newNormal);
palm->setRawRotation(rotation);
// Compute current velocity from position change
glm::vec3 rawVelocity = (position - palm->getRawPosition()) / deltaTime / 1000.f;
palm->setRawVelocity(rawVelocity); // meters/sec
palm->setRawPosition(position);
// use the velocity to determine whether there's any movement (if the hand isn't new)
const float MOVEMENT_SPEED_THRESHOLD = 0.05f;
if (glm::length(rawVelocity) > MOVEMENT_SPEED_THRESHOLD && foundHand) {
_lastMovement = usecTimestampNow();
}
// initialize the "finger" based on the direction
FingerData finger(palm, hand);
finger.setActive(true);
finger.setRawRootPosition(position);
const float FINGER_LENGTH = 300.0f; // Millimeters
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH);
const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR;
finger.setRawTipPosition(position + rotation * FINGER_VECTOR);
// Store the one fingertip in the palm structure so we can track velocity
glm::vec3 oldTipPosition = palm->getTipRawPosition();
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime / 1000.f);
palm->setTipPosition(newTipPosition);
// three fingers indicates to the skeleton that we have enough data to determine direction
palm->getFingers().clear();
palm->getFingers().push_back(finger);
palm->getFingers().push_back(finger);
palm->getFingers().push_back(finger);
}
// if the controllers haven't been moved in a while, disable
const unsigned int MOVEMENT_DISABLE_DURATION = 30 * 1000 * 1000;
if (usecTimestampNow() - _lastMovement > MOVEMENT_DISABLE_DURATION) {
for (vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
it->setActive(false);
}
}
#endif
}