From e28a838c9af6adc93c32dac1adfc077c508beeb7 Mon Sep 17 00:00:00 2001
From: Jens Koenen <koenen@vr.rwth-aachen.de>
Date: Wed, 11 Jan 2023 17:37:59 +0100
Subject: [PATCH] Worked on correction of scene orientation

---
 CMakeLists.txt                                |  4 ++++
 liblava/app/camera.cpp                        |  2 +-
 liblava/core/math.hpp                         |  2 --
 .../multi_view/multi_view_stereo.vert         |  5 +++--
 .../native_stereo_deferred.vert               |  3 ++-
 .../native_forward/native_stereo_forward.vert |  3 ++-
 res/dpr/utility/indirect_capture.vert         |  3 ++-
 res/dpr/utility/math_library.glsl             |  7 ++++++
 res/dpr/utility/shadow.vert                   |  3 ++-
 src/headset/emulated_headset.cpp              |  6 ++---
 src/headset/openvr_headset.cpp                | 10 +++++++--
 src/headset/openxr_headset.cpp                |  5 +----
 src/scene.cpp                                 | 22 +++++++++++++------
 src/scene.hpp                                 |  4 +++-
 src/vr_application.cpp                        |  1 +
 15 files changed, 54 insertions(+), 26 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 89e362ad..e72ec405 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,6 +31,10 @@ add_compile_definitions(VK_ENABLE_BETA_EXTENSIONS)
 # Use OpenXR together with Vulkan
 add_compile_definitions(XR_USE_GRAPHICS_API_VULKAN)
 
+# GLM Coordinate system definitions
+add_compile_definitions(GLM_FORCE_RADIANS)
+add_compile_definitions(GLM_FORCE_DEPTH_ZERO_TO_ONE)
+
 set(LIBLAVA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/liblava)
 set(LIBLAVA_EXT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext)
 set(LIBLAVA_RES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/res)
diff --git a/liblava/app/camera.cpp b/liblava/app/camera.cpp
index 4e0cbdef..d6f639ba 100644
--- a/liblava/app/camera.cpp
+++ b/liblava/app/camera.cpp
@@ -60,7 +60,7 @@ namespace lava {
 
             if (rotate && !lock_rotation) {
                 auto speed = dt * rotation_speed;
-                rotation += v3(dy * speed, -dx * speed, 0.f);
+                rotation -= v3(dy * speed, dx * speed, 0.f);
             }
 
             if (translate) {
diff --git a/liblava/core/math.hpp b/liblava/core/math.hpp
index 3a27662c..1de5dbc4 100644
--- a/liblava/core/math.hpp
+++ b/liblava/core/math.hpp
@@ -6,8 +6,6 @@
 
 #include <liblava/core/types.hpp>
 
-#define GLM_FORCE_RADIANS
-#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 #include <glm/glm.hpp>
 #include <glm/gtc/matrix_transform.hpp>
 #include <glm/gtc/type_ptr.hpp>
diff --git a/res/dpr/strategy/multi_view/multi_view_stereo.vert b/res/dpr/strategy/multi_view/multi_view_stereo.vert
index e7849d5d..743f6acb 100644
--- a/res/dpr/strategy/multi_view/multi_view_stereo.vert
+++ b/res/dpr/strategy/multi_view/multi_view_stereo.vert
@@ -4,6 +4,7 @@
 
 #include "mesh_data.inc"
 #include "per_frame.inc"
+#include "math_library.glsl"
 
 layout(location = 0) out vec3 outPos;
 layout(location = 1) out vec3 outNormal;
@@ -44,11 +45,11 @@ void main()
 
     if (gl_ViewIndex == 0) //Left Eye
     {
-        gl_Position = left_frame.viewProjection * vec4(outPos, 1.0);
+        gl_Position = convert_right_handed(left_frame.viewProjection * vec4(outPos, 1.0));
     }
 
     else if (gl_ViewIndex == 1) //Right Eye
     {
-        gl_Position = right_frame.viewProjection * vec4(outPos, 1.0);
+        gl_Position = convert_right_handed(right_frame.viewProjection * vec4(outPos, 1.0));
     }
 }
diff --git a/res/dpr/strategy/native_deferred/native_stereo_deferred.vert b/res/dpr/strategy/native_deferred/native_stereo_deferred.vert
index a920692d..48b67a44 100644
--- a/res/dpr/strategy/native_deferred/native_stereo_deferred.vert
+++ b/res/dpr/strategy/native_deferred/native_stereo_deferred.vert
@@ -3,6 +3,7 @@
 
 #include "mesh_data.inc"
 #include "per_frame.inc"
+#include "math_library.glsl"
 
 layout(location = 0) out vec3 outPos;
 layout(location = 1) out vec3 outNormal;
@@ -36,5 +37,5 @@ void main()
     outTangent = normalize((meshData.vectorToWorldSpace * vec4(inTangent, 0.0)).xyz);
     outUV = inUV;
 
-    gl_Position =  frame.viewProjection * vec4(outPos, 1.0);
+    gl_Position = convert_right_handed(frame.viewProjection * vec4(outPos, 1.0));
 }
diff --git a/res/dpr/strategy/native_forward/native_stereo_forward.vert b/res/dpr/strategy/native_forward/native_stereo_forward.vert
index a920692d..48b67a44 100644
--- a/res/dpr/strategy/native_forward/native_stereo_forward.vert
+++ b/res/dpr/strategy/native_forward/native_stereo_forward.vert
@@ -3,6 +3,7 @@
 
 #include "mesh_data.inc"
 #include "per_frame.inc"
+#include "math_library.glsl"
 
 layout(location = 0) out vec3 outPos;
 layout(location = 1) out vec3 outNormal;
@@ -36,5 +37,5 @@ void main()
     outTangent = normalize((meshData.vectorToWorldSpace * vec4(inTangent, 0.0)).xyz);
     outUV = inUV;
 
-    gl_Position =  frame.viewProjection * vec4(outPos, 1.0);
+    gl_Position = convert_right_handed(frame.viewProjection * vec4(outPos, 1.0));
 }
diff --git a/res/dpr/utility/indirect_capture.vert b/res/dpr/utility/indirect_capture.vert
index 56fa702b..7e51ce02 100644
--- a/res/dpr/utility/indirect_capture.vert
+++ b/res/dpr/utility/indirect_capture.vert
@@ -3,6 +3,7 @@
 
 #include "light_data.inc"
 #include "mesh_data.inc"
+#include "math_library.glsl"
 
 layout(set = 0, binding = 0) uniform MeshBuffer
 {
@@ -43,5 +44,5 @@ void main()
     outUV = inUV;
 
     mat4 shadow_matrix = lights[light_index].shadow_matrix[0];
-    gl_Position = shadow_matrix * vec4(outPos, 1.0);
+    gl_Position = convert_right_handed(shadow_matrix * vec4(outPos, 1.0));
 }
diff --git a/res/dpr/utility/math_library.glsl b/res/dpr/utility/math_library.glsl
index fa3f35ac..41845c5a 100644
--- a/res/dpr/utility/math_library.glsl
+++ b/res/dpr/utility/math_library.glsl
@@ -44,4 +44,11 @@ vec3 decode_normal(vec2 vector)
     return normalize(normal);
 }
 
+// Converts the OpenGL left handed NDC-space (x : right, y: up, z: into the screen)
+// to the right handed NDC-space (x: right, y: down, z: into the screen) that is used by Vulkan.
+vec4 convert_right_handed(vec4 vector)
+{
+    return vec4(vector.x, 1.0 - vector.y, vector.zw);
+}
+
 #endif
\ No newline at end of file
diff --git a/res/dpr/utility/shadow.vert b/res/dpr/utility/shadow.vert
index 49c0365b..00ae3694 100644
--- a/res/dpr/utility/shadow.vert
+++ b/res/dpr/utility/shadow.vert
@@ -3,6 +3,7 @@
 
 #include "light_data.inc"
 #include "mesh_data.inc"
+#include "math_library.glsl"
 
 layout(set = 0, binding = 0) uniform LightParameterBuffer
 {
@@ -33,5 +34,5 @@ void main()
     mat4 shadow_matrix = lights[light_index].shadow_matrix[frustum_index];
     mat4 model_matrix = mesh.localToWorldSpace;
 
-    gl_Position = shadow_matrix * model_matrix * vec4(inPos, 1.0);
+    gl_Position = convert_right_handed(shadow_matrix * model_matrix * vec4(inPos, 1.0));
 }
diff --git a/src/headset/emulated_headset.cpp b/src/headset/emulated_headset.cpp
index 3bd74ecd..ccfbb336 100644
--- a/src/headset/emulated_headset.cpp
+++ b/src/headset/emulated_headset.cpp
@@ -60,11 +60,11 @@ bool EmulatedHeadset::on_update(lava::delta delta_time)
 
     camera.update_view(delta_time, input.get_mouse_position());
 
-    this->view_matrix = camera.view * glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)); //Flip y
+    this->view_matrix = camera.view;
     this->submitted = false;
 
-    this->controller_matrices[0] = glm::inverse(this->view_matrix) * glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)) * glm::translate(glm::mat4(1.0f), glm::vec3(-0.3f, -0.2f, -0.4f));
-    this->controller_matrices[1] = glm::inverse(this->view_matrix) * glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)) * glm::translate(glm::mat4(1.0f), glm::vec3(0.3f, -0.2f, -0.4f));
+    this->controller_matrices[0] = glm::inverse(this->view_matrix) * glm::translate(glm::mat4(1.0f), glm::vec3(-0.3f, -0.2f, -0.4f));
+    this->controller_matrices[1] = glm::inverse(this->view_matrix) * glm::translate(glm::mat4(1.0f), glm::vec3( 0.3f, -0.2f, -0.4f));
 
     return true;
 }
diff --git a/src/headset/openvr_headset.cpp b/src/headset/openvr_headset.cpp
index 712fc85e..d82c95ec 100644
--- a/src/headset/openvr_headset.cpp
+++ b/src/headset/openvr_headset.cpp
@@ -3,7 +3,6 @@
 
 #include <iostream>
 #include <glm/ext.hpp>
-#include <glm/gtx/matrix_operation.hpp>
 #include <imgui.h>
 
 struct OpenVRActionButtonBinding
@@ -394,6 +393,13 @@ bool OpenVRHeadset::update_actions()
     {
         for (uint32_t button = 0; button < this->controller_button_handles[controller].size(); button++)
         {
+            if (this->controller_button_handles[controller][button] == vr::k_ulInvalidActionHandle)
+            {
+                this->controller_buttons[controller][button] = BUTTON_STATE_RELEASED;
+
+                continue;
+            }
+
             vr::InputDigitalActionData_t button_data;
 
             if (vr::VRInput()->GetDigitalActionData(this->controller_button_handles[controller][button], &button_data, sizeof(button_data), vr::k_ulInvalidInputValueHandle) != vr::VRInputError_None)
@@ -457,7 +463,7 @@ bool OpenVRHeadset::update_head_pose()
     
     if (this->head_pose.bPoseIsValid)
     {
-        this->head_matrix = glm::inverse(glm::mat4(glm::transpose(glm::make_mat3x4(&this->head_pose.mDeviceToAbsoluteTracking.m[0][0]))) * glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)));
+        this->head_matrix = glm::inverse(glm::mat4(glm::transpose(glm::make_mat3x4(&this->head_pose.mDeviceToAbsoluteTracking.m[0][0]))));
     }
 
     return true;
diff --git a/src/headset/openxr_headset.cpp b/src/headset/openxr_headset.cpp
index 6a53e517..37fc5f21 100644
--- a/src/headset/openxr_headset.cpp
+++ b/src/headset/openxr_headset.cpp
@@ -3,7 +3,6 @@
 
 #include <iostream>
 #include <imgui.h>
-#include <glm/gtx/matrix_operation.hpp>
 
 PFN_xrGetVulkanGraphicsRequirementsKHR xrGetVulkanGraphicsRequirementsKHR = nullptr;
 PFN_xrGetVulkanInstanceExtensionsKHR xrGetVulkanInstanceExtensionsKHR = nullptr;
@@ -1178,9 +1177,7 @@ bool OpenXRHeadset::update_views()
         XrQuaternionf quaternion = view.pose.orientation;
         XrVector3f position = view.pose.position;
 
-        glm::mat4 pose_transform = (glm::mat4) glm::inverse(glm::quat(quaternion.w, quaternion.x, quaternion.y, quaternion.z)) * glm::translate(glm::mat4(1.0f), glm::vec3(-position.x, -position.y, -position.z));
-        
-        this->head_to_eye_matrices[index] = glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)) * pose_transform;
+        this->head_to_eye_matrices[index] = (glm::mat4)glm::inverse(glm::quat(quaternion.w, quaternion.x, quaternion.y, quaternion.z)) * glm::translate(glm::mat4(1.0f), glm::vec3(-position.x, -position.y, -position.z));
 
         float left = this->near_plane * glm::tan(view.fov.angleLeft);
         float right = this->near_plane * glm::tan(view.fov.angleRight);
diff --git a/src/scene.cpp b/src/scene.cpp
index 6f841f3b..fd617492 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -562,7 +562,7 @@ void Scene::create_default_light()
     SceneLight default_light;
     default_light.node_index = INVALID_NODE;
     default_light.initial_position = glm::vec3(0.0f);
-    default_light.initial_direction = glm::normalize(glm::vec3(0.1, 1.0f, 0.25));
+    default_light.initial_direction = glm::normalize(glm::vec3(0.1f, -1.0f, 0.25f));
 
     glsl::LightData& light_data = default_light.data;
     light_data.position = default_light.initial_position;
@@ -1148,12 +1148,14 @@ bool Scene::load_cameras(const aiScene* scene, float scale, const std::map<std::
 
             return false;
         }
-
+        
         SceneCamera& scene_camera = this->cameras.emplace_back();
         scene_camera.node_index = node_indices.at(camera->mName.C_Str());
         scene_camera.name = camera->mName.C_Str();
         scene_camera.projection_matrix = glm::perspective(camera->mHorizontalFOV, camera->mAspect, camera->mClipPlaneNear * scale, camera->mClipPlaneFar * scale);
-        scene_camera.initial_view_matrix = glm::lookAt(glm::make_vec3(&camera->mPosition.x) * scale, glm::make_vec3(&camera->mLookAt.x) * scale, glm::make_vec3(&camera->mUp.x));
+        scene_camera.local_position = glm::make_vec3(&camera->mPosition.x);
+        scene_camera.local_look_at = glm::make_vec3(&camera->mLookAt.x);
+        scene_camera.local_up = glm::make_vec3(&camera->mUp.x);
         scene_camera.near_plane = camera->mClipPlaneNear * scale;
         scene_camera.far_plane = camera->mClipPlaneFar * scale;
     }
@@ -2111,7 +2113,11 @@ void Scene::apply_transforms()
     {
         const SceneNode& node = this->nodes[camera.node_index];
 
-        camera.view_matrix = glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)) * glm::transpose(camera.initial_view_matrix) * glm::inverse(node.current_global_transform);
+        glm::vec3 global_location = node.current_global_transform * glm::vec4(camera.local_position, 1.0f);
+        glm::vec3 global_look_at = node.current_global_transform * glm::vec4(camera.local_look_at, 0.0f);
+        glm::vec3 global_up = node.current_global_transform * glm::vec4(camera.local_up, 0.0f);
+
+        camera.view_matrix = glm::lookAt(global_location, global_look_at, global_up);
     }
 
     for (SceneMesh& mesh : this->meshes)
@@ -2147,8 +2153,8 @@ void Scene::apply_transforms()
             current_global_transform = node.current_global_transform;
         }
 
-        light.data.position = glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)) * current_global_transform * glm::vec4(light.initial_position, 1.0f);
-        light.data.direction = glm::diagonal4x4(glm::vec4(1.0f, -1.0f, 1.0f, 1.0f)) * current_global_transform * glm::vec4(light.initial_direction, 0.0f);
+        light.data.position = current_global_transform * glm::vec4(light.initial_position, 1.0f);
+        light.data.direction = current_global_transform * glm::vec4(light.initial_direction, 0.0f);
         light.data.direction = glm::normalize(light.data.direction);
 
         this->compute_light_matrices(light);
@@ -2158,13 +2164,15 @@ void Scene::apply_transforms()
 bool Scene::setup_post_processes(SceneOrientation orientation, uint32_t& post_processes)
 {
     post_processes = aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType | aiProcess_GenBoundingBoxes;
+    post_processes |= aiProcess_FlipUVs;
 
     switch (orientation)
     {
     case SCENE_ORIENTATION_RIGHT_HANDED:
-        post_processes |= aiProcess_ConvertToLeftHanded;
+        //post_processes |= aiProcess_ConvertToLeftHanded;
         break;
     case SCENE_ORIENTATION_LEFT_HANDED:
+        post_processes |= aiProcess_ConvertToLeftHanded;
         break;
     default:
         lava::log()->error("Can't setup post processes due to unknown scene orientation!");
diff --git a/src/scene.hpp b/src/scene.hpp
index 00088fc6..a30d2b6c 100644
--- a/src/scene.hpp
+++ b/src/scene.hpp
@@ -68,8 +68,10 @@ struct SceneCamera
     SceneNodeIndex node_index = INVALID_NODE;
     std::string name;
     glm::mat4 projection_matrix = glm::mat4(1.0f);
-    glm::mat4 initial_view_matrix = glm::mat4(1.0f);
     glm::mat4 view_matrix = glm::mat4(1.0f);
+    glm::vec3 local_position = glm::vec3(0.0f);
+    glm::vec3 local_look_at = glm::vec3(0.0f);
+    glm::vec3 local_up = glm::vec3(0.0f);
     float near_plane = 0.0f;
     float far_plane = 0.0f;
 };
diff --git a/src/vr_application.cpp b/src/vr_application.cpp
index 716e32fa..18c6c864 100644
--- a/src/vr_application.cpp
+++ b/src/vr_application.cpp
@@ -330,6 +330,7 @@ bool VRApplication::on_create()
     {
         config.controller_left_file = std::string(RESOURCE_FOLDER) + "/dpr-controller/ObjModelViveFocus3ControllerLeft.fbx";
         config.controller_left_unit = SCENE_UNIT_CENTIMETERS;
+        config.controller_left_orientation = SCENE_ORIENTATION_LEFT_HANDED;
 
         config.controller_right_file = std::string(RESOURCE_FOLDER) + "/dpr-controller/ObjModelViveFocus3ControllerRight.fbx";
         config.controller_right_unit = SCENE_UNIT_CENTIMETERS;
-- 
GitLab