mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 23:32:48 +02:00
Working on touch
This commit is contained in:
parent
130c0dda31
commit
62051ad297
5 changed files with 106 additions and 80 deletions
|
@ -32,6 +32,7 @@ class Mapping;
|
||||||
using MappingPointer = std::shared_ptr<Mapping>;
|
using MappingPointer = std::shared_ptr<Mapping>;
|
||||||
using MappingList = std::list<MappingPointer>;
|
using MappingList = std::list<MappingPointer>;
|
||||||
|
|
||||||
|
struct Pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,7 +24,17 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrTrue);
|
auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrTrue);
|
||||||
_currentRenderFrameInfo.renderPose = toGlm(trackingState.HeadPose.ThePose);
|
_currentRenderFrameInfo.renderPose = toGlm(trackingState.HeadPose.ThePose);
|
||||||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||||
|
|
||||||
withRenderThreadLock([&] {
|
withRenderThreadLock([&] {
|
||||||
|
// Make controller poses available to the presentation thread
|
||||||
|
ovr_for_each_hand([&](ovrHandType hand){
|
||||||
|
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked & ovrStatus_PositionTracked;
|
||||||
|
if (REQUIRED_HAND_STATUS == (trackingState.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
||||||
|
_handPoses[hand] = toGlm(trackingState.HandPoses[hand].ThePose);
|
||||||
|
} else {
|
||||||
|
_handPoses[hand] = glm::mat4();
|
||||||
|
}
|
||||||
|
});
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -243,91 +243,13 @@ void OculusControllerManager::TouchDevice::focusOutEvent() {
|
||||||
void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
|
void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
|
||||||
const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand,
|
const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand,
|
||||||
const ovrPoseStatef& handPose) {
|
const ovrPoseStatef& handPose) {
|
||||||
// When the sensor-to-world rotation is identity the coordinate axes look like this:
|
|
||||||
//
|
|
||||||
// user
|
|
||||||
// forward
|
|
||||||
// -z
|
|
||||||
// |
|
|
||||||
// y| user
|
|
||||||
// y o----x right
|
|
||||||
// o-----x user
|
|
||||||
// | up
|
|
||||||
// |
|
|
||||||
// z
|
|
||||||
//
|
|
||||||
// Rift
|
|
||||||
|
|
||||||
// From ABOVE the hand canonical axes looks like this:
|
|
||||||
//
|
|
||||||
// | | | | y | | | |
|
|
||||||
// | | | | | | | | |
|
|
||||||
// | | | | |
|
|
||||||
// |left | / x---- + \ |right|
|
|
||||||
// | _/ z \_ |
|
|
||||||
// | | | |
|
|
||||||
// | | | |
|
|
||||||
//
|
|
||||||
|
|
||||||
// So when the user is in Rift space facing the -zAxis with hands outstretched and palms down
|
|
||||||
// the rotation to align the Touch axes with those of the hands is:
|
|
||||||
//
|
|
||||||
// touchToHand = halfTurnAboutY * quaterTurnAboutX
|
|
||||||
|
|
||||||
// Due to how the Touch controllers fit into the palm there is an offset that is different for each hand.
|
|
||||||
// You can think of this offset as the inverse of the measured rotation when the hands are posed, such that
|
|
||||||
// the combination (measurement * offset) is identity at this orientation.
|
|
||||||
//
|
|
||||||
// Qoffset = glm::inverse(deltaRotation when hand is posed fingers forward, palm down)
|
|
||||||
//
|
|
||||||
// An approximate offset for the Touch can be obtained by inspection:
|
|
||||||
//
|
|
||||||
// Qoffset = glm::inverse(glm::angleAxis(sign * PI/2.0f, zAxis) * glm::angleAxis(PI/4.0f, xAxis))
|
|
||||||
//
|
|
||||||
// So the full equation is:
|
|
||||||
//
|
|
||||||
// Q = combinedMeasurement * touchToHand
|
|
||||||
//
|
|
||||||
// Q = (deltaQ * QOffset) * (yFlip * quarterTurnAboutX)
|
|
||||||
//
|
|
||||||
// Q = (deltaQ * inverse(deltaQForAlignedHand)) * (yFlip * quarterTurnAboutX)
|
|
||||||
|
|
||||||
auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
||||||
auto& pose = _poseStateMap[poseId];
|
auto& pose = _poseStateMap[poseId];
|
||||||
|
pose = ovrControllerPoseToHandPose(hand, handPose);
|
||||||
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
|
|
||||||
static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X);
|
|
||||||
static const glm::quat touchToHand = yFlip * quarterX;
|
|
||||||
|
|
||||||
static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z);
|
|
||||||
static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z);
|
|
||||||
static const glm::quat eighthX = glm::angleAxis(PI / 4.0f, Vectors::UNIT_X);
|
|
||||||
|
|
||||||
static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ * eighthX) * touchToHand;
|
|
||||||
static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ * eighthX) * touchToHand;
|
|
||||||
|
|
||||||
static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
|
||||||
static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
|
|
||||||
CONTROLLER_LENGTH_OFFSET / 2.0f,
|
|
||||||
CONTROLLER_LENGTH_OFFSET * 2.0f);
|
|
||||||
static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
|
||||||
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
|
||||||
|
|
||||||
auto translationOffset = (hand == ovrHand_Left ? leftTranslationOffset : rightTranslationOffset);
|
|
||||||
auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset);
|
|
||||||
|
|
||||||
glm::quat rotation = toGlm(handPose.ThePose.Orientation);
|
|
||||||
|
|
||||||
pose.translation = toGlm(handPose.ThePose.Position);
|
|
||||||
pose.translation += rotation * translationOffset;
|
|
||||||
pose.rotation = rotation * rotationOffset;
|
|
||||||
pose.angularVelocity = toGlm(handPose.AngularVelocity);
|
|
||||||
pose.velocity = toGlm(handPose.LinearVelocity);
|
|
||||||
pose.valid = true;
|
|
||||||
|
|
||||||
// transform into avatar frame
|
// transform into avatar frame
|
||||||
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||||
pose = pose.transform(controllerToAvatar);
|
pose = pose.transform(controllerToAvatar);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
|
|
||||||
|
#include <controllers/Input.h>
|
||||||
|
#include <controllers/Pose.h>
|
||||||
|
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
using Lock = std::unique_lock<Mutex>;
|
using Lock = std::unique_lock<Mutex>;
|
||||||
|
|
||||||
|
@ -191,3 +194,88 @@ void SwapFramebufferWrapper::onBind(oglplus::Framebuffer::Target target) {
|
||||||
void SwapFramebufferWrapper::onUnbind(oglplus::Framebuffer::Target target) {
|
void SwapFramebufferWrapper::onUnbind(oglplus::Framebuffer::Target target) {
|
||||||
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
controller::Pose ovrControllerPoseToHandPose(
|
||||||
|
ovrHandType hand,
|
||||||
|
const ovrPoseStatef& handPose) {
|
||||||
|
// When the sensor-to-world rotation is identity the coordinate axes look like this:
|
||||||
|
//
|
||||||
|
// user
|
||||||
|
// forward
|
||||||
|
// -z
|
||||||
|
// |
|
||||||
|
// y| user
|
||||||
|
// y o----x right
|
||||||
|
// o-----x user
|
||||||
|
// | up
|
||||||
|
// |
|
||||||
|
// z
|
||||||
|
//
|
||||||
|
// Rift
|
||||||
|
|
||||||
|
// From ABOVE the hand canonical axes looks like this:
|
||||||
|
//
|
||||||
|
// | | | | y | | | |
|
||||||
|
// | | | | | | | | |
|
||||||
|
// | | | | |
|
||||||
|
// |left | / x---- + \ |right|
|
||||||
|
// | _/ z \_ |
|
||||||
|
// | | | |
|
||||||
|
// | | | |
|
||||||
|
//
|
||||||
|
|
||||||
|
// So when the user is in Rift space facing the -zAxis with hands outstretched and palms down
|
||||||
|
// the rotation to align the Touch axes with those of the hands is:
|
||||||
|
//
|
||||||
|
// touchToHand = halfTurnAboutY * quaterTurnAboutX
|
||||||
|
|
||||||
|
// Due to how the Touch controllers fit into the palm there is an offset that is different for each hand.
|
||||||
|
// You can think of this offset as the inverse of the measured rotation when the hands are posed, such that
|
||||||
|
// the combination (measurement * offset) is identity at this orientation.
|
||||||
|
//
|
||||||
|
// Qoffset = glm::inverse(deltaRotation when hand is posed fingers forward, palm down)
|
||||||
|
//
|
||||||
|
// An approximate offset for the Touch can be obtained by inspection:
|
||||||
|
//
|
||||||
|
// Qoffset = glm::inverse(glm::angleAxis(sign * PI/2.0f, zAxis) * glm::angleAxis(PI/4.0f, xAxis))
|
||||||
|
//
|
||||||
|
// So the full equation is:
|
||||||
|
//
|
||||||
|
// Q = combinedMeasurement * touchToHand
|
||||||
|
//
|
||||||
|
// Q = (deltaQ * QOffset) * (yFlip * quarterTurnAboutX)
|
||||||
|
//
|
||||||
|
// Q = (deltaQ * inverse(deltaQForAlignedHand)) * (yFlip * quarterTurnAboutX)
|
||||||
|
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
|
||||||
|
static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X);
|
||||||
|
static const glm::quat touchToHand = yFlip * quarterX;
|
||||||
|
|
||||||
|
static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z);
|
||||||
|
static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z);
|
||||||
|
static const glm::quat eighthX = glm::angleAxis(PI / 4.0f, Vectors::UNIT_X);
|
||||||
|
|
||||||
|
static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ * eighthX) * touchToHand;
|
||||||
|
static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ * eighthX) * touchToHand;
|
||||||
|
|
||||||
|
static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
||||||
|
static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||||
|
CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||||
|
CONTROLLER_LENGTH_OFFSET * 2.0f);
|
||||||
|
static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
||||||
|
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
||||||
|
|
||||||
|
auto translationOffset = (hand == ovrHand_Left ? leftTranslationOffset : rightTranslationOffset);
|
||||||
|
auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset);
|
||||||
|
|
||||||
|
glm::quat rotation = toGlm(handPose.ThePose.Orientation);
|
||||||
|
|
||||||
|
controller::Pose pose;
|
||||||
|
pose.translation = toGlm(handPose.ThePose.Position);
|
||||||
|
pose.translation += rotation * translationOffset;
|
||||||
|
pose.rotation = rotation * rotationOffset;
|
||||||
|
pose.angularVelocity = toGlm(handPose.AngularVelocity);
|
||||||
|
pose.velocity = toGlm(handPose.LinearVelocity);
|
||||||
|
pose.valid = true;
|
||||||
|
return pose;
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <gl/OglplusHelpers.h>
|
#include <gl/OglplusHelpers.h>
|
||||||
|
#include <controllers/Forward.h>
|
||||||
|
|
||||||
void logWarning(const char* what);
|
void logWarning(const char* what);
|
||||||
void logFatal(const char* what);
|
void logFatal(const char* what);
|
||||||
|
@ -128,3 +129,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
ovrSession _session;
|
ovrSession _session;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
controller::Pose ovrControllerPoseToHandPose(
|
||||||
|
ovrHandType hand,
|
||||||
|
const ovrPoseStatef& handPose);
|
||||||
|
|
Loading…
Reference in a new issue