mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:37:51 +02:00
Merge pull request #7067 from hyperlogic/tony/vive-support
Re-enable OpenVR support
This commit is contained in:
commit
ff3c934c6c
7 changed files with 78 additions and 57 deletions
4
cmake/externals/openvr/CMakeLists.txt
vendored
4
cmake/externals/openvr/CMakeLists.txt
vendored
|
@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL https://github.com/ValveSoftware/openvr/archive/v0.9.12.zip
|
URL https://github.com/ValveSoftware/openvr/archive/v0.9.15.zip
|
||||||
URL_MD5 c08dced68ce4e341e1467e6814ae419d
|
URL_MD5 0ff8560b49b6da1150fcc47360e8ceca
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
|
|
@ -39,6 +39,7 @@ glm::mat4 OculusBaseDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
||||||
|
|
||||||
bool OculusBaseDisplayPlugin::isSupported() const {
|
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||||
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
||||||
|
qDebug() << "OculusBaseDisplayPlugin : ovr_Initialize() failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ bool OculusBaseDisplayPlugin::isSupported() const {
|
||||||
if (!OVR_SUCCESS(result)) {
|
if (!OVR_SUCCESS(result)) {
|
||||||
ovrErrorInfo error;
|
ovrErrorInfo error;
|
||||||
ovr_GetLastErrorInfo(&error);
|
ovr_GetLastErrorInfo(&error);
|
||||||
|
qDebug() << "OculusBaseDisplayPlugin : ovr_Create() failed" << result << error.Result << error.ErrorString;
|
||||||
ovr_Shutdown();
|
ovr_Shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,17 @@
|
||||||
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
||||||
#
|
#
|
||||||
|
|
||||||
# OpenVR is disabled until a) it works with threaded present and
|
if (WIN32)
|
||||||
# b) it doesn't interfere with Oculus SDK 0.8
|
|
||||||
if (FALSE)
|
|
||||||
#if (WIN32)
|
|
||||||
# we're using static GLEW, so define GLEW_STATIC
|
# we're using static GLEW, so define GLEW_STATIC
|
||||||
add_definitions(-DGLEW_STATIC)
|
add_definitions(-DGLEW_STATIC)
|
||||||
set(TARGET_NAME openvr)
|
set(TARGET_NAME openvr)
|
||||||
setup_hifi_plugin(OpenGL Script Qml Widgets)
|
setup_hifi_plugin(OpenGL Script Qml Widgets)
|
||||||
link_hifi_libraries(shared gl networking controllers
|
link_hifi_libraries(shared gl networking controllers
|
||||||
plugins display-plugins input-plugins script-engine
|
plugins display-plugins input-plugins script-engine
|
||||||
render-utils model gpu render model-networking fbx)
|
render-utils model gpu render model-networking fbx)
|
||||||
|
|
||||||
include_hifi_library_headers(octree)
|
include_hifi_library_headers(octree)
|
||||||
|
|
||||||
add_dependency_external_projects(OpenVR)
|
add_dependency_external_projects(OpenVR)
|
||||||
find_package(OpenVR REQUIRED)
|
find_package(OpenVR REQUIRED)
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS})
|
target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS})
|
||||||
|
|
|
@ -32,12 +32,15 @@ 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;
|
||||||
static uvec2 _windowSize;
|
static uvec2 _windowSize;
|
||||||
static uvec2 _renderTargetSize;
|
static uvec2 _renderTargetSize;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct PerEyeData {
|
struct PerEyeData {
|
||||||
//uvec2 _viewportOrigin;
|
//uvec2 _viewportOrigin;
|
||||||
//uvec2 _viewportSize;
|
//uvec2 _viewportSize;
|
||||||
|
@ -69,10 +72,7 @@ mat4 toGlm(const vr::HmdMatrix34_t& m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenVrDisplayPlugin::isSupported() const {
|
bool OpenVrDisplayPlugin::isSupported() const {
|
||||||
auto hmd = acquireOpenVrSystem();
|
return vr::VR_IsHmdPresent();
|
||||||
bool success = nullptr != hmd;
|
|
||||||
releaseOpenVrSystem();
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::activate() {
|
void OpenVrDisplayPlugin::activate() {
|
||||||
|
@ -87,11 +87,16 @@ void OpenVrDisplayPlugin::activate() {
|
||||||
// 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;
|
||||||
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
|
||||||
PerEyeData& eyeData = _eyesData[eye];
|
{
|
||||||
eyeData._projectionMatrix = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
|
Lock lock(_poseMutex);
|
||||||
eyeData._eyeOffset = toGlm(_hmd->GetEyeToHeadTransform(eye));
|
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||||
});
|
PerEyeData& eyeData = _eyesData[eye];
|
||||||
|
eyeData._projectionMatrix = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
|
||||||
|
eyeData._eyeOffset = toGlm(_hmd->GetEyeToHeadTransform(eye));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_compositor = vr::VRCompositor();
|
_compositor = vr::VRCompositor();
|
||||||
Q_ASSERT(_compositor);
|
Q_ASSERT(_compositor);
|
||||||
WindowOpenGLDisplayPlugin::activate();
|
WindowOpenGLDisplayPlugin::activate();
|
||||||
|
@ -115,6 +120,10 @@ void OpenVrDisplayPlugin::customizeContext() {
|
||||||
glGetError();
|
glGetError();
|
||||||
});
|
});
|
||||||
WindowOpenGLDisplayPlugin::customizeContext();
|
WindowOpenGLDisplayPlugin::customizeContext();
|
||||||
|
|
||||||
|
enableVsync(false);
|
||||||
|
// Only enable mirroring if we know vsync is disabled
|
||||||
|
_enablePreview = !isVsyncEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
uvec2 OpenVrDisplayPlugin::getRecommendedRenderSize() const {
|
uvec2 OpenVrDisplayPlugin::getRecommendedRenderSize() const {
|
||||||
|
@ -126,25 +135,24 @@ mat4 OpenVrDisplayPlugin::getProjection(Eye eye, const mat4& baseProjection) con
|
||||||
if (eye == Mono) {
|
if (eye == Mono) {
|
||||||
eye = Left;
|
eye = Left;
|
||||||
}
|
}
|
||||||
|
Lock lock(_poseMutex);
|
||||||
return _eyesData[eye]._projectionMatrix;
|
return _eyesData[eye]._projectionMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::resetSensors() {
|
void OpenVrDisplayPlugin::resetSensors() {
|
||||||
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(_trackedDevicePoseMat4[0]));
|
Lock lock(_poseMutex);
|
||||||
|
glm::mat4 m = toGlm(_trackedDevicePose[0].mDeviceToAbsoluteTracking);
|
||||||
|
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 OpenVrDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
|
glm::mat4 OpenVrDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
|
||||||
|
Lock lock(_poseMutex);
|
||||||
return _eyesData[eye]._eyeOffset;
|
return _eyesData[eye]._eyeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
||||||
glm::mat4 result;
|
Lock lock(_poseMutex);
|
||||||
{
|
return _trackedDevicePoseMat4[0];
|
||||||
Lock lock(_mutex);
|
|
||||||
result = _trackedDevicePoseMat4[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,17 +164,40 @@ void OpenVrDisplayPlugin::internalPresent() {
|
||||||
// Flip y-axis since GL UV coords are backwards.
|
// Flip y-axis since GL UV coords are backwards.
|
||||||
static vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 };
|
static vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 };
|
||||||
static vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 };
|
static vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 };
|
||||||
vr::Texture_t texture{ (void*)_currentSceneTexture, vr::API_OpenGL, vr::ColorSpace_Auto };
|
|
||||||
{
|
// screen preview mirroring
|
||||||
Lock lock(_mutex);
|
if (_enablePreview) {
|
||||||
_compositor->Submit(vr::Eye_Left, &texture, &leftBounds);
|
auto windowSize = toGlm(_window->size());
|
||||||
_compositor->Submit(vr::Eye_Right, &texture, &rightBounds);
|
if (_monoPreview) {
|
||||||
|
glViewport(0, 0, windowSize.x * 2, windowSize.y);
|
||||||
|
glScissor(0, windowSize.y, windowSize.x, windowSize.y);
|
||||||
|
} else {
|
||||||
|
glViewport(0, 0, windowSize.x, windowSize.y);
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _currentSceneTexture);
|
||||||
|
GLenum err = glGetError();
|
||||||
|
Q_ASSERT(0 == err);
|
||||||
|
drawUnitQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vr::Texture_t texture{ (void*)_currentSceneTexture, vr::API_OpenGL, vr::ColorSpace_Auto };
|
||||||
|
|
||||||
|
_compositor->Submit(vr::Eye_Left, &texture, &leftBounds);
|
||||||
|
_compositor->Submit(vr::Eye_Right, &texture, &rightBounds);
|
||||||
|
|
||||||
glFinish();
|
glFinish();
|
||||||
|
|
||||||
|
if (_enablePreview) {
|
||||||
|
swapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
_compositor->WaitGetPoses(_presentThreadTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
|
||||||
|
|
||||||
{
|
{
|
||||||
Lock lock(_mutex);
|
// copy and process _presentThreadTrackedDevicePoses
|
||||||
_compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
|
Lock lock(_poseMutex);
|
||||||
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||||
|
_trackedDevicePose[i] = _presentThreadTrackedDevicePose[i];
|
||||||
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
|
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
|
||||||
}
|
}
|
||||||
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||||
|
|
|
@ -45,5 +45,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
vr::IVRSystem* _hmd { nullptr };
|
vr::IVRSystem* _hmd { nullptr };
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
|
bool _enablePreview { false };
|
||||||
|
bool _monoPreview { true };
|
||||||
|
mutable Mutex _poseMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,11 @@ using Lock = std::unique_lock<Mutex>;
|
||||||
static int refCount { 0 };
|
static int refCount { 0 };
|
||||||
static Mutex mutex;
|
static Mutex mutex;
|
||||||
static vr::IVRSystem* activeHmd { nullptr };
|
static vr::IVRSystem* activeHmd { nullptr };
|
||||||
static bool hmdPresent = vr::VR_IsHmdPresent();
|
|
||||||
|
|
||||||
static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
|
static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
|
||||||
|
|
||||||
vr::IVRSystem* acquireOpenVrSystem() {
|
vr::IVRSystem* acquireOpenVrSystem() {
|
||||||
|
bool hmdPresent = vr::VR_IsHmdPresent();
|
||||||
if (hmdPresent) {
|
if (hmdPresent) {
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
if (!activeHmd) {
|
if (!activeHmd) {
|
||||||
|
@ -40,6 +40,8 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
||||||
qCDebug(displayplugins) << "openvr: incrementing refcount";
|
qCDebug(displayplugins) << "openvr: incrementing refcount";
|
||||||
++refCount;
|
++refCount;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
qCDebug(displayplugins) << "openvr: no hmd present";
|
||||||
}
|
}
|
||||||
return activeHmd;
|
return activeHmd;
|
||||||
}
|
}
|
||||||
|
@ -51,24 +53,7 @@ void releaseOpenVrSystem() {
|
||||||
--refCount;
|
--refCount;
|
||||||
if (0 == refCount) {
|
if (0 == refCount) {
|
||||||
qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system";
|
qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system";
|
||||||
// Avoid spamming the VR system with activate/deactivate calls at system startup by
|
vr::VR_Shutdown();
|
||||||
// putting in a delay before we destory the shutdown the VR subsystem
|
|
||||||
|
|
||||||
// FIXME releasing the VR system at all seems to trigger an exception deep inside the Oculus DLL.
|
|
||||||
// disabling for now.
|
|
||||||
//QTimer* releaseTimer = new QTimer();
|
|
||||||
//releaseTimer->singleShot(RELEASE_OPENVR_HMD_DELAY_MS, [releaseTimer] {
|
|
||||||
// Lock lock(mutex);
|
|
||||||
// qDebug() << "Delayed openvr destroy activated";
|
|
||||||
// if (0 == refCount && nullptr != activeHmd) {
|
|
||||||
// qDebug() << "Delayed openvr destroy: releasing resources";
|
|
||||||
// activeHmd = nullptr;
|
|
||||||
// vr::VR_Shutdown();
|
|
||||||
// } else {
|
|
||||||
// qDebug() << "Delayed openvr destroy: HMD still in use";
|
|
||||||
// }
|
|
||||||
// releaseTimer->deleteLater();
|
|
||||||
//});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,10 +48,7 @@ static const QString RENDER_CONTROLLERS = "Render Hand Controllers";
|
||||||
const QString ViveControllerManager::NAME = "OpenVR";
|
const QString ViveControllerManager::NAME = "OpenVR";
|
||||||
|
|
||||||
bool ViveControllerManager::isSupported() const {
|
bool ViveControllerManager::isSupported() const {
|
||||||
auto hmd = acquireOpenVrSystem();
|
return vr::VR_IsHmdPresent();
|
||||||
bool success = hmd != nullptr;
|
|
||||||
releaseOpenVrSystem();
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViveControllerManager::activate() {
|
void ViveControllerManager::activate() {
|
||||||
|
@ -66,10 +63,12 @@ void ViveControllerManager::activate() {
|
||||||
}
|
}
|
||||||
Q_ASSERT(_hmd);
|
Q_ASSERT(_hmd);
|
||||||
|
|
||||||
|
// OpenVR provides 3d mesh representations of the controllers
|
||||||
|
// Disabled controller rendering code
|
||||||
|
/*
|
||||||
auto renderModels = vr::VRRenderModels();
|
auto renderModels = vr::VRRenderModels();
|
||||||
|
|
||||||
vr::RenderModel_t model;
|
vr::RenderModel_t model;
|
||||||
/*
|
|
||||||
if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) {
|
if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) {
|
||||||
qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING);
|
qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING);
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,6 +144,7 @@ void ViveControllerManager::deactivate() {
|
||||||
void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) {
|
void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) {
|
||||||
PerformanceTimer perfTimer("ViveControllerManager::updateRendering");
|
PerformanceTimer perfTimer("ViveControllerManager::updateRendering");
|
||||||
|
|
||||||
|
/*
|
||||||
if (_modelLoaded) {
|
if (_modelLoaded) {
|
||||||
//auto controllerPayload = new render::Payload<ViveControllerManager>(this);
|
//auto controllerPayload = new render::Payload<ViveControllerManager>(this);
|
||||||
//auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload);
|
//auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload);
|
||||||
|
@ -175,9 +175,11 @@ void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePoint
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign) {
|
void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign) {
|
||||||
|
/*
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
Transform transform(userInputMapper->getSensorToWorldMat());
|
Transform transform(userInputMapper->getSensorToWorldMat());
|
||||||
transform.postTranslate(pose.getTranslation() + pose.getRotation() * glm::vec3(0, 0, CONTROLLER_LENGTH_OFFSET));
|
transform.postTranslate(pose.getTranslation() + pose.getRotation() * glm::vec3(0, 0, CONTROLLER_LENGTH_OFFSET));
|
||||||
|
@ -199,6 +201,7 @@ void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch&
|
||||||
// mesh->getVertexBuffer()._stride);
|
// mesh->getVertexBuffer()._stride);
|
||||||
batch.setIndexBuffer(gpu::UINT16, mesh->getIndexBuffer()._buffer, 0);
|
batch.setIndexBuffer(gpu::UINT16, mesh->getIndexBuffer()._buffer, 0);
|
||||||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue