Merge pull request #7139 from hyperlogic/tony/better-vive-tracking

OpenVRDisplayPlugin: predict poses for better tracking
This commit is contained in:
Chris Collins 2016-02-19 11:36:06 -08:00
commit 75429e39bc
2 changed files with 28 additions and 22 deletions

View file

@ -30,7 +30,6 @@ const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)");
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
static vr::IVRCompositor* _compositor{ nullptr }; static vr::IVRCompositor* _compositor{ nullptr };
static vr::TrackedDevicePose_t _presentThreadTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
static mat4 _sensorResetMat; static mat4 _sensorResetMat;
@ -43,12 +42,12 @@ bool OpenVrDisplayPlugin::isSupported() const {
void OpenVrDisplayPlugin::activate() { void OpenVrDisplayPlugin::activate() {
_container->setIsOptionChecked(StandingHMDSensorMode, true); _container->setIsOptionChecked(StandingHMDSensorMode, true);
if (!_hmd) { if (!_system) {
_hmd = acquireOpenVrSystem(); _system = acquireOpenVrSystem();
} }
Q_ASSERT(_hmd); Q_ASSERT(_system);
_hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); _system->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y);
// Recommended render target size is per-eye, so double the X size for // Recommended render target size is per-eye, so double the X size for
// left + right eyes // left + right eyes
_renderTargetSize.x *= 2; _renderTargetSize.x *= 2;
@ -56,8 +55,8 @@ void OpenVrDisplayPlugin::activate() {
{ {
Lock lock(_poseMutex); Lock lock(_poseMutex);
openvr_for_each_eye([&](vr::Hmd_Eye eye) { openvr_for_each_eye([&](vr::Hmd_Eye eye) {
_eyeOffsets[eye] = toGlm(_hmd->GetEyeToHeadTransform(eye)); _eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye));
_eyeProjections[eye] = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); _eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
}); });
// FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes // FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes
_cullingProjection = _eyeProjections[0]; _cullingProjection = _eyeProjections[0];
@ -71,9 +70,9 @@ void OpenVrDisplayPlugin::activate() {
void OpenVrDisplayPlugin::deactivate() { void OpenVrDisplayPlugin::deactivate() {
_container->setIsOptionChecked(StandingHMDSensorMode, false); _container->setIsOptionChecked(StandingHMDSensorMode, false);
if (_hmd) { if (_system) {
releaseOpenVrSystem(); releaseOpenVrSystem();
_hmd = nullptr; _system = nullptr;
} }
_compositor = nullptr; _compositor = nullptr;
HmdDisplayPlugin::deactivate(); HmdDisplayPlugin::deactivate();
@ -96,9 +95,24 @@ void OpenVrDisplayPlugin::resetSensors() {
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m)); _sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
} }
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const { glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
Lock lock(_poseMutex);
float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
float frameDuration = 1.f / displayFrequency;
float vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
// TODO: this seems awfuly long, 44ms total, but it produced the best results.
const float NUM_PREDICTION_FRAMES = 3.0f;
float predictedSecondsFromNow = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
// copy and process predictedTrackedDevicePoses
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
_trackedDevicePose[i] = predictedTrackedDevicePose[i];
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
}
return _trackedDevicePoseMat4[0]; return _trackedDevicePoseMat4[0];
} }
@ -114,16 +128,8 @@ void OpenVrDisplayPlugin::internalPresent() {
glFinish(); glFinish();
_compositor->WaitGetPoses(_presentThreadTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0); vr::TrackedDevicePose_t currentTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
_compositor->WaitGetPoses(currentTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
{
// copy and process _presentThreadTrackedDevicePoses
Lock lock(_poseMutex);
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
_trackedDevicePose[i] = _presentThreadTrackedDevicePose[i];
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
}
}
// Handle the mirroring in the base class // Handle the mirroring in the base class
HmdDisplayPlugin::internalPresent(); HmdDisplayPlugin::internalPresent();

View file

@ -35,7 +35,7 @@ protected:
virtual void internalPresent() override; virtual void internalPresent() override;
private: private:
vr::IVRSystem* _hmd { nullptr }; vr::IVRSystem* _system { nullptr };
static const QString NAME; static const QString NAME;
mutable Mutex _poseMutex; mutable Mutex _poseMutex;
}; };