mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #16350 from lvonasek/refactor_openxr_matrices
OpenXR - Refactor
This commit is contained in:
commit
7beff4da96
6 changed files with 268 additions and 459 deletions
|
@ -11,12 +11,37 @@
|
|||
|
||||
#include "Common/GPU/Vulkan/VulkanContext.h"
|
||||
|
||||
#include "Common/Math/lin/matrix4x4.h"
|
||||
|
||||
#include "Core/HLE/sceDisplay.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/KeyMap.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
enum VRMatrix {
|
||||
VR_PROJECTION_MATRIX,
|
||||
VR_VIEW_MATRIX_LEFT_EYE,
|
||||
VR_VIEW_MATRIX_RIGHT_EYE,
|
||||
VR_MATRIX_COUNT
|
||||
};
|
||||
|
||||
enum VRMirroring {
|
||||
VR_MIRRORING_UPDATED,
|
||||
VR_MIRRORING_AXIS_X,
|
||||
VR_MIRRORING_AXIS_Y,
|
||||
VR_MIRRORING_AXIS_Z,
|
||||
VR_MIRRORING_PITCH,
|
||||
VR_MIRRORING_YAW,
|
||||
VR_MIRRORING_ROLL,
|
||||
VR_MIRRORING_COUNT
|
||||
};
|
||||
|
||||
static std::map<int, bool> pspKeys;
|
||||
|
||||
static int vr3DGeometryCount = 0;
|
||||
static long vrCompat[VR_COMPAT_MAX];
|
||||
static float vrMatrix[VR_MATRIX_COUNT][16];
|
||||
static bool vrMirroring[VR_MIRRORING_COUNT];
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
@ -174,7 +199,6 @@ void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool(*NativeTouch)(con
|
|||
KeyInput keyInput = {};
|
||||
for (int j = 0; j < 2; j++) {
|
||||
int status = IN_VRGetButtonState(j);
|
||||
bool cameraControl = VR_GetConfig(VR_CONFIG_CAMERA_CONTROL);
|
||||
for (ButtonMapping& m : controllerMapping[j]) {
|
||||
|
||||
//check if camera key was pressed
|
||||
|
@ -200,14 +224,14 @@ void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool(*NativeTouch)(con
|
|||
if (pressed && haptics) {
|
||||
INVR_Vibrate(100, j, 1000);
|
||||
}
|
||||
if (!cameraControl || cameraKey) {
|
||||
if (!pspKeys[VIRTKEY_VR_CAMERA_ADJUST] || cameraKey) {
|
||||
NativeKey(keyInput);
|
||||
}
|
||||
m.pressed = pressed;
|
||||
m.repeat = 0;
|
||||
} else if (pressed && (m.repeat > 30)) {
|
||||
keyInput.flags |= KEY_IS_REPEAT;
|
||||
if (!cameraControl || cameraKey) {
|
||||
if (!pspKeys[VIRTKEY_VR_CAMERA_ADJUST] || cameraKey) {
|
||||
NativeKey(keyInput);
|
||||
}
|
||||
m.repeat = 0;
|
||||
|
@ -321,14 +345,7 @@ void UpdateVRSpecialKeys(const KeyInput &key) {
|
|||
std::vector<int> nativeKeys;
|
||||
if (KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &nativeKeys)) {
|
||||
for (int& nativeKey : nativeKeys) {
|
||||
// adjust camera parameters
|
||||
if (nativeKey == VIRTKEY_VR_CAMERA_ADJUST) {
|
||||
VR_SetConfig(VR_CONFIG_CAMERA_CONTROL, key.flags & KEY_DOWN);
|
||||
}
|
||||
// force 2D rendering
|
||||
else if (nativeKey == CTRL_SCREEN) {
|
||||
VR_SetConfig(VR_CONFIG_FORCE_2D, key.flags & KEY_DOWN);
|
||||
}
|
||||
pspKeys[nativeKey] = key.flags & KEY_DOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -420,20 +437,147 @@ bool StartVRRender() {
|
|||
|
||||
if (VR_InitFrame(VR_GetEngine())) {
|
||||
|
||||
// Get OpenXR view and fov
|
||||
XrFovf fov = {};
|
||||
XrPosef invViewTransform[2];
|
||||
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||
XrView view = VR_GetView(eye);
|
||||
fov.angleLeft += view.fov.angleLeft / 2.0f;
|
||||
fov.angleRight += view.fov.angleRight / 2.0f;
|
||||
fov.angleUp += view.fov.angleUp / 2.0f;
|
||||
fov.angleDown += view.fov.angleDown / 2.0f;
|
||||
invViewTransform[eye] = view.pose;
|
||||
}
|
||||
|
||||
// Get 6DoF scale
|
||||
float scale = 1.0f;
|
||||
bool hasUnitScale = false;
|
||||
if (PSP_CoreParameter().compat.vrCompat().UnitsPerMeter > 0) {
|
||||
scale = PSP_CoreParameter().compat.vrCompat().UnitsPerMeter;
|
||||
hasUnitScale = true;
|
||||
}
|
||||
|
||||
// Update matrices
|
||||
for (int matrix = 0; matrix < VR_MATRIX_COUNT; matrix++) {
|
||||
if (matrix == VR_PROJECTION_MATRIX) {
|
||||
float nearZ = g_Config.fFieldOfViewPercentage / 200.0f;
|
||||
float tanAngleLeft = tanf(fov.angleLeft);
|
||||
float tanAngleRight = tanf(fov.angleRight);
|
||||
float tanAngleDown = tanf(fov.angleDown);
|
||||
float tanAngleUp = tanf(fov.angleUp);
|
||||
|
||||
float M[16] = {};
|
||||
M[0] = 2 / (tanAngleRight - tanAngleLeft);
|
||||
M[2] = (tanAngleRight + tanAngleLeft) / (tanAngleRight - tanAngleLeft);
|
||||
M[5] = 2 / (tanAngleUp - tanAngleDown);
|
||||
M[6] = (tanAngleUp + tanAngleDown) / (tanAngleUp - tanAngleDown);
|
||||
M[10] = -1;
|
||||
M[11] = -(nearZ + nearZ);
|
||||
M[14] = -1;
|
||||
|
||||
memcpy(vrMatrix[matrix], M, sizeof(float) * 16);
|
||||
} else if ((matrix == VR_VIEW_MATRIX_LEFT_EYE) || (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) {
|
||||
bool flatScreen = false;
|
||||
XrPosef invView = invViewTransform[0];
|
||||
int vrMode = VR_GetConfig(VR_CONFIG_MODE);
|
||||
if ((vrMode == VR_MODE_MONO_SCREEN) || (vrMode == VR_MODE_STEREO_SCREEN)) {
|
||||
invView = XrPosef_Identity();
|
||||
flatScreen = true;
|
||||
}
|
||||
|
||||
// get axis mirroring configuration
|
||||
float mx = vrMirroring[VR_MIRRORING_PITCH] ? -1.0f : 1.0f;
|
||||
float my = vrMirroring[VR_MIRRORING_YAW] ? -1.0f : 1.0f;
|
||||
float mz = vrMirroring[VR_MIRRORING_ROLL] ? -1.0f : 1.0f;
|
||||
|
||||
// ensure there is maximally one axis to mirror rotation
|
||||
if (mx + my + mz < 0) {
|
||||
mx *= -1.0f;
|
||||
my *= -1.0f;
|
||||
mz *= -1.0f;
|
||||
} else {
|
||||
invView = XrPosef_Inverse(invView);
|
||||
}
|
||||
|
||||
// create updated quaternion
|
||||
if (mx + my + mz < 3 - EPSILON) {
|
||||
XrVector3f rotation = XrQuaternionf_ToEulerAngles(invView.orientation);
|
||||
XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mx * ToRadians(rotation.x));
|
||||
XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, my * ToRadians(rotation.y));
|
||||
XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mz * ToRadians(rotation.z));
|
||||
invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw));
|
||||
}
|
||||
|
||||
float M[16];
|
||||
XrQuaternionf_ToMatrix4f(&invView.orientation, M);
|
||||
memcpy(&M, M, sizeof(float) * 16);
|
||||
|
||||
// Apply 6Dof head movement
|
||||
if (!flatScreen && g_Config.bEnable6DoF) {
|
||||
M[3] -= invViewTransform[0].position.x * (vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f) * scale;
|
||||
M[7] -= invViewTransform[0].position.y * (vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f) * scale;
|
||||
M[11] -= invViewTransform[0].position.z * (vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f) * scale;
|
||||
}
|
||||
// Camera adjust - distance
|
||||
if (fabsf(g_Config.fCameraDistance) > 0.0f) {
|
||||
XrVector3f forward = {0.0f, 0.0f, g_Config.fCameraDistance * scale};
|
||||
forward = XrQuaternionf_Rotate(invView.orientation, forward);
|
||||
forward = XrVector3f_ScalarMultiply(forward, vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f);
|
||||
M[3] += forward.x;
|
||||
M[7] += forward.y;
|
||||
M[11] += forward.z;
|
||||
}
|
||||
// Camera adjust - height
|
||||
if (fabsf(g_Config.fCameraHeight) > 0.0f) {
|
||||
XrVector3f up = {0.0f, -g_Config.fCameraHeight * scale, 0.0f};
|
||||
up = XrQuaternionf_Rotate(invView.orientation, up);
|
||||
up = XrVector3f_ScalarMultiply(up, vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f);
|
||||
M[3] += up.x;
|
||||
M[7] += up.y;
|
||||
M[11] += up.z;
|
||||
}
|
||||
// Camera adjust - side
|
||||
if (fabsf(g_Config.fCameraSide) > 0.0f) {
|
||||
XrVector3f side = {-g_Config.fCameraSide * scale, 0.0f, 0.0f};
|
||||
side = XrQuaternionf_Rotate(invView.orientation, side);
|
||||
side = XrVector3f_ScalarMultiply(side, vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f);
|
||||
M[3] += side.x;
|
||||
M[7] += side.y;
|
||||
M[11] += side.z;
|
||||
}
|
||||
// Stereoscopy
|
||||
if (hasUnitScale && (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) {
|
||||
float dx = fabs(invViewTransform[1].position.x - invViewTransform[0].position.x);
|
||||
float dy = fabs(invViewTransform[1].position.y - invViewTransform[0].position.y);
|
||||
float dz = fabs(invViewTransform[1].position.z - invViewTransform[0].position.z);
|
||||
float ipd = sqrt(dx * dx + dy * dy + dz * dz);
|
||||
XrVector3f separation = {ipd * scale, 0.0f, 0.0f};
|
||||
separation = XrQuaternionf_Rotate(invView.orientation, separation);
|
||||
separation = XrVector3f_ScalarMultiply(separation, vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f);
|
||||
M[3] -= separation.x;
|
||||
M[7] -= separation.y;
|
||||
M[11] -= separation.z;
|
||||
}
|
||||
memcpy(vrMatrix[matrix], M, sizeof(float) * 16);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Decide if the scene is 3D or not
|
||||
if (g_Config.bEnableVR && !VR_GetConfig(VR_CONFIG_FORCE_2D) && (VR_GetConfig(VR_CONFIG_3D_GEOMETRY_COUNT) > 15)) {
|
||||
bool stereo = VR_GetConfig(VR_CONFIG_HAS_UNIT_SCALE) && g_Config.bEnableStereo;
|
||||
if (g_Config.bEnableVR && !pspKeys[CTRL_SCREEN] && (vr3DGeometryCount > 15)) {
|
||||
bool stereo = hasUnitScale && g_Config.bEnableStereo;
|
||||
VR_SetConfig(VR_CONFIG_MODE, stereo ? VR_MODE_STEREO_6DOF : VR_MODE_MONO_6DOF);
|
||||
} else {
|
||||
VR_SetConfig(VR_CONFIG_MODE, g_Config.bEnableStereo ? VR_MODE_STEREO_SCREEN : VR_MODE_MONO_SCREEN);
|
||||
}
|
||||
VR_SetConfig(VR_CONFIG_3D_GEOMETRY_COUNT, VR_GetConfig(VR_CONFIG_3D_GEOMETRY_COUNT) / 2);
|
||||
vr3DGeometryCount /= 2;
|
||||
|
||||
// Set compatibility
|
||||
vrCompat[VR_COMPAT_SKYPLANE] = PSP_CoreParameter().compat.vrCompat().Skyplane;
|
||||
|
||||
// Camera control
|
||||
if (VR_GetConfig(VR_CONFIG_CAMERA_CONTROL)) {
|
||||
if (pspKeys[VIRTKEY_VR_CAMERA_ADJUST]) {
|
||||
//left joystick controls height and side
|
||||
float height = g_Config.fCameraHeight;
|
||||
float side = g_Config.fCameraSide;
|
||||
|
@ -467,13 +611,8 @@ bool StartVRRender() {
|
|||
|
||||
// Set customizations
|
||||
__DisplaySetFramerate(g_Config.bForce72Hz ? 72 : 60);
|
||||
VR_SetConfig(VR_CONFIG_6DOF_ENABLED, g_Config.bEnable6DoF);
|
||||
VR_SetConfigFloat(VR_CONFIG_CAMERA_DISTANCE, g_Config.fCameraDistance);
|
||||
VR_SetConfigFloat(VR_CONFIG_CAMERA_HEIGHT, g_Config.fCameraHeight);
|
||||
VR_SetConfigFloat(VR_CONFIG_CAMERA_SIDE, g_Config.fCameraSide);
|
||||
VR_SetConfigFloat(VR_CONFIG_CANVAS_DISTANCE, g_Config.fCanvasDistance);
|
||||
VR_SetConfigFloat(VR_CONFIG_FOV_SCALE, g_Config.fFieldOfViewPercentage);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_UPDATED, false);
|
||||
vrMirroring[VR_MIRRORING_UPDATED] = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -539,7 +678,7 @@ bool Is2DVRObject(float* projMatrix, bool ortho) {
|
|||
|
||||
// Update 3D geometry count
|
||||
if (!identity && !ortho) {
|
||||
VR_SetConfig(VR_CONFIG_3D_GEOMETRY_COUNT, VR_GetConfig(VR_CONFIG_3D_GEOMETRY_COUNT) + 1);
|
||||
vr3DGeometryCount++;
|
||||
}
|
||||
return identity;
|
||||
}
|
||||
|
@ -547,71 +686,57 @@ bool Is2DVRObject(float* projMatrix, bool ortho) {
|
|||
void UpdateVRParams(float* projMatrix) {
|
||||
|
||||
// Set mirroring of axes
|
||||
if (!VR_GetConfig(VR_CONFIG_MIRROR_UPDATED)) {
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_UPDATED, true);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_AXIS_X, projMatrix[0] < 0);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_AXIS_Y, projMatrix[5] < 0);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_AXIS_Z, projMatrix[10] > 0);
|
||||
if (!vrMirroring[VR_MIRRORING_UPDATED]) {
|
||||
vrMirroring[VR_MIRRORING_UPDATED] = true;
|
||||
vrMirroring[VR_MIRRORING_AXIS_X] = projMatrix[0] < 0;
|
||||
vrMirroring[VR_MIRRORING_AXIS_Y] = projMatrix[5] < 0;
|
||||
vrMirroring[VR_MIRRORING_AXIS_Z] = projMatrix[10] > 0;
|
||||
if ((projMatrix[0] < 0) && (projMatrix[10] < 0)) { //e.g. Dante's inferno
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_PITCH, true);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_YAW, true);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_ROLL, false);
|
||||
vrMirroring[VR_MIRRORING_PITCH] = true;
|
||||
vrMirroring[VR_MIRRORING_YAW] = true;
|
||||
vrMirroring[VR_MIRRORING_ROLL] = false;
|
||||
} else if (projMatrix[10] < 0) { //e.g. GTA - Liberty city
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_PITCH, false);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_YAW, false);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_ROLL, false);
|
||||
vrMirroring[VR_MIRRORING_PITCH] = false;
|
||||
vrMirroring[VR_MIRRORING_YAW] = false;
|
||||
vrMirroring[VR_MIRRORING_ROLL] = false;
|
||||
} else if (projMatrix[5] < 0) { //e.g. PES 2014
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_PITCH, true);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_YAW, true);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_ROLL, false);
|
||||
vrMirroring[VR_MIRRORING_PITCH] = true;
|
||||
vrMirroring[VR_MIRRORING_YAW] = true;
|
||||
vrMirroring[VR_MIRRORING_ROLL] = false;
|
||||
} else { //e.g. Lego Pirates
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_PITCH, false);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_YAW, true);
|
||||
VR_SetConfig(VR_CONFIG_MIRROR_ROLL, true);
|
||||
vrMirroring[VR_MIRRORING_PITCH] = false;
|
||||
vrMirroring[VR_MIRRORING_YAW] = true;
|
||||
vrMirroring[VR_MIRRORING_ROLL] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Set 6DoF scale
|
||||
float scale = 1.0f;
|
||||
if (PSP_CoreParameter().compat.vrCompat().UnitsPerMeter > 0) {
|
||||
scale = PSP_CoreParameter().compat.vrCompat().UnitsPerMeter;
|
||||
VR_SetConfig(VR_CONFIG_HAS_UNIT_SCALE, true);
|
||||
} else {
|
||||
VR_SetConfig(VR_CONFIG_HAS_UNIT_SCALE, false);
|
||||
}
|
||||
VR_SetConfigFloat(VR_CONFIG_6DOF_SCALE, scale);
|
||||
}
|
||||
|
||||
void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye) {
|
||||
float* dst[] = {leftEye, rightEye};
|
||||
VRMatrix enums[] = {VR_PROJECTION_MATRIX_LEFT_EYE, VR_PROJECTION_MATRIX_RIGHT_EYE};
|
||||
for (int index = 0; index < 2; index++) {
|
||||
ovrMatrix4f hmdProjection = VR_GetMatrix(enums[index]);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if ((hmdProjection.M[i][j] > 0) != (projMatrix[i * 4 + j] > 0)) {
|
||||
hmdProjection.M[i][j] *= -1.0f;
|
||||
}
|
||||
}
|
||||
float* hmdProjection = vrMatrix[VR_PROJECTION_MATRIX];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((hmdProjection[i] > 0) != (projMatrix[i] > 0)) {
|
||||
hmdProjection[i] *= -1.0f;
|
||||
}
|
||||
memcpy(dst[index], hmdProjection.M, 16 * sizeof(float));
|
||||
}
|
||||
memcpy(leftEye, hmdProjection, 16 * sizeof(float));
|
||||
memcpy(rightEye, hmdProjection, 16 * sizeof(float));
|
||||
}
|
||||
|
||||
void UpdateVRView(float* leftEye, float* rightEye) {
|
||||
float* dst[] = {leftEye, rightEye};
|
||||
VRMatrix enums[] = {VR_VIEW_MATRIX_LEFT_EYE, VR_VIEW_MATRIX_RIGHT_EYE};
|
||||
float* matrix[] = {vrMatrix[VR_VIEW_MATRIX_LEFT_EYE], vrMatrix[VR_VIEW_MATRIX_RIGHT_EYE]};
|
||||
for (int index = 0; index < 2; index++) {
|
||||
|
||||
// Get view matrix from the game
|
||||
ovrMatrix4f gameView;
|
||||
memcpy(gameView.M, dst[index], 16 * sizeof(float));
|
||||
Lin::Matrix4x4 gameView = {};
|
||||
memcpy(gameView.m, dst[index], 16 * sizeof(float));
|
||||
|
||||
// Get view matrix from the headset
|
||||
ovrMatrix4f hmdView = VR_GetMatrix(enums[index]);
|
||||
Lin::Matrix4x4 hmdView = {};
|
||||
memcpy(hmdView.m, matrix[index], 16 * sizeof(float));
|
||||
|
||||
// Combine the matrices
|
||||
ovrMatrix4f renderView = ovrMatrix4f_Multiply(&hmdView, &gameView);
|
||||
memcpy(dst[index], renderView.M, 16 * sizeof(float));
|
||||
Lin::Matrix4x4 renderView = hmdView * gameView;
|
||||
memcpy(dst[index], renderView.m, 16 * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(_DEBUG) && (defined(XR_USE_GRAPHICS_API_OPENGL) || defined(XR_USE_GRAPHICS_API_OPENGL_ES))
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "VRMath.h"
|
||||
|
||||
|
@ -15,240 +16,21 @@ float ToRadians(float deg) {
|
|||
/*
|
||||
================================================================================
|
||||
|
||||
ovrMatrix4f
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
float ovrMatrix4f_Minor(const ovrMatrix4f* m, int r0, int r1, int r2, int c0, int c1, int c2) {
|
||||
return m->M[r0][c0] * (m->M[r1][c1] * m->M[r2][c2] - m->M[r2][c1] * m->M[r1][c2]) -
|
||||
m->M[r0][c1] * (m->M[r1][c0] * m->M[r2][c2] - m->M[r2][c0] * m->M[r1][c2]) +
|
||||
m->M[r0][c2] * (m->M[r1][c0] * m->M[r2][c1] - m->M[r2][c0] * m->M[r1][c1]);
|
||||
}
|
||||
|
||||
ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q) {
|
||||
const float ww = q->w * q->w;
|
||||
const float xx = q->x * q->x;
|
||||
const float yy = q->y * q->y;
|
||||
const float zz = q->z * q->z;
|
||||
|
||||
ovrMatrix4f out;
|
||||
out.M[0][0] = ww + xx - yy - zz;
|
||||
out.M[0][1] = 2 * (q->x * q->y - q->w * q->z);
|
||||
out.M[0][2] = 2 * (q->x * q->z + q->w * q->y);
|
||||
out.M[0][3] = 0;
|
||||
|
||||
out.M[1][0] = 2 * (q->x * q->y + q->w * q->z);
|
||||
out.M[1][1] = ww - xx + yy - zz;
|
||||
out.M[1][2] = 2 * (q->y * q->z - q->w * q->x);
|
||||
out.M[1][3] = 0;
|
||||
|
||||
out.M[2][0] = 2 * (q->x * q->z - q->w * q->y);
|
||||
out.M[2][1] = 2 * (q->y * q->z + q->w * q->x);
|
||||
out.M[2][2] = ww - xx - yy + zz;
|
||||
out.M[2][3] = 0;
|
||||
|
||||
out.M[3][0] = 0;
|
||||
out.M[3][1] = 0;
|
||||
out.M[3][2] = 0;
|
||||
out.M[3][3] = 1;
|
||||
return out;
|
||||
}
|
||||
|
||||
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
|
||||
const float angleLeft,
|
||||
const float angleRight,
|
||||
const float angleUp,
|
||||
const float angleDown,
|
||||
const float nearZ,
|
||||
const float farZ) {
|
||||
|
||||
const float tanAngleLeft = tanf(angleLeft);
|
||||
const float tanAngleRight = tanf(angleRight);
|
||||
|
||||
const float tanAngleDown = tanf(angleDown);
|
||||
const float tanAngleUp = tanf(angleUp);
|
||||
|
||||
const float tanAngleWidth = tanAngleRight - tanAngleLeft;
|
||||
|
||||
// Set to tanAngleDown - tanAngleUp for a clip space with positive Y
|
||||
// down (Vulkan). Set to tanAngleUp - tanAngleDown for a clip space with
|
||||
// positive Y up (OpenGL / D3D / Metal).
|
||||
const float tanAngleHeight = tanAngleUp - tanAngleDown;
|
||||
|
||||
// Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
|
||||
// Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
|
||||
const float offsetZ = nearZ;
|
||||
|
||||
ovrMatrix4f result;
|
||||
if (farZ <= nearZ) {
|
||||
// place the far plane at infinity
|
||||
result.M[0][0] = 2 / tanAngleWidth;
|
||||
result.M[0][1] = 0;
|
||||
result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
|
||||
result.M[0][3] = 0;
|
||||
|
||||
result.M[1][0] = 0;
|
||||
result.M[1][1] = 2 / tanAngleHeight;
|
||||
result.M[1][2] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
|
||||
result.M[1][3] = 0;
|
||||
|
||||
result.M[2][0] = 0;
|
||||
result.M[2][1] = 0;
|
||||
result.M[2][2] = -1;
|
||||
result.M[2][3] = -(nearZ + offsetZ);
|
||||
|
||||
result.M[3][0] = 0;
|
||||
result.M[3][1] = 0;
|
||||
result.M[3][2] = -1;
|
||||
result.M[3][3] = 0;
|
||||
} else {
|
||||
// normal projection
|
||||
result.M[0][0] = 2 / tanAngleWidth;
|
||||
result.M[0][1] = 0;
|
||||
result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
|
||||
result.M[0][3] = 0;
|
||||
|
||||
result.M[1][0] = 0;
|
||||
result.M[1][1] = 2 / tanAngleHeight;
|
||||
result.M[1][2] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
|
||||
result.M[1][3] = 0;
|
||||
|
||||
result.M[2][0] = 0;
|
||||
result.M[2][1] = 0;
|
||||
result.M[2][2] = -(farZ + offsetZ) / (farZ - nearZ);
|
||||
result.M[2][3] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
|
||||
|
||||
result.M[3][0] = 0;
|
||||
result.M[3][1] = 0;
|
||||
result.M[3][2] = -1;
|
||||
result.M[3][3] = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ovrMatrix4f ovrMatrix4f_CreateRotation(const float radiansX, const float radiansY, const float radiansZ) {
|
||||
const float sinX = sinf(radiansX);
|
||||
const float cosX = cosf(radiansX);
|
||||
const ovrMatrix4f rotationX = {
|
||||
{{1, 0, 0, 0}, {0, cosX, -sinX, 0}, {0, sinX, cosX, 0}, {0, 0, 0, 1}}};
|
||||
const float sinY = sinf(radiansY);
|
||||
const float cosY = cosf(radiansY);
|
||||
const ovrMatrix4f rotationY = {
|
||||
{{cosY, 0, sinY, 0}, {0, 1, 0, 0}, {-sinY, 0, cosY, 0}, {0, 0, 0, 1}}};
|
||||
const float sinZ = sinf(radiansZ);
|
||||
const float cosZ = cosf(radiansZ);
|
||||
const ovrMatrix4f rotationZ = {
|
||||
{{cosZ, -sinZ, 0, 0}, {sinZ, cosZ, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}};
|
||||
const ovrMatrix4f rotationXY = ovrMatrix4f_Multiply(&rotationY, &rotationX);
|
||||
return ovrMatrix4f_Multiply(&rotationZ, &rotationXY);
|
||||
}
|
||||
|
||||
ovrMatrix4f ovrMatrix4f_Inverse(const ovrMatrix4f* m) {
|
||||
const float rcpDet = 1.0f /
|
||||
(m->M[0][0] * ovrMatrix4f_Minor(m, 1, 2, 3, 1, 2, 3) -
|
||||
m->M[0][1] * ovrMatrix4f_Minor(m, 1, 2, 3, 0, 2, 3) +
|
||||
m->M[0][2] * ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 3) -
|
||||
m->M[0][3] * ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 2));
|
||||
ovrMatrix4f out;
|
||||
out.M[0][0] = ovrMatrix4f_Minor(m, 1, 2, 3, 1, 2, 3) * rcpDet;
|
||||
out.M[0][1] = -ovrMatrix4f_Minor(m, 0, 2, 3, 1, 2, 3) * rcpDet;
|
||||
out.M[0][2] = ovrMatrix4f_Minor(m, 0, 1, 3, 1, 2, 3) * rcpDet;
|
||||
out.M[0][3] = -ovrMatrix4f_Minor(m, 0, 1, 2, 1, 2, 3) * rcpDet;
|
||||
out.M[1][0] = -ovrMatrix4f_Minor(m, 1, 2, 3, 0, 2, 3) * rcpDet;
|
||||
out.M[1][1] = ovrMatrix4f_Minor(m, 0, 2, 3, 0, 2, 3) * rcpDet;
|
||||
out.M[1][2] = -ovrMatrix4f_Minor(m, 0, 1, 3, 0, 2, 3) * rcpDet;
|
||||
out.M[1][3] = ovrMatrix4f_Minor(m, 0, 1, 2, 0, 2, 3) * rcpDet;
|
||||
out.M[2][0] = ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 3) * rcpDet;
|
||||
out.M[2][1] = -ovrMatrix4f_Minor(m, 0, 2, 3, 0, 1, 3) * rcpDet;
|
||||
out.M[2][2] = ovrMatrix4f_Minor(m, 0, 1, 3, 0, 1, 3) * rcpDet;
|
||||
out.M[2][3] = -ovrMatrix4f_Minor(m, 0, 1, 2, 0, 1, 3) * rcpDet;
|
||||
out.M[3][0] = -ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 2) * rcpDet;
|
||||
out.M[3][1] = ovrMatrix4f_Minor(m, 0, 2, 3, 0, 1, 2) * rcpDet;
|
||||
out.M[3][2] = -ovrMatrix4f_Minor(m, 0, 1, 3, 0, 1, 2) * rcpDet;
|
||||
out.M[3][3] = ovrMatrix4f_Minor(m, 0, 1, 2, 0, 1, 2) * rcpDet;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Use left-multiplication to accumulate transformations.
|
||||
ovrMatrix4f ovrMatrix4f_Multiply(const ovrMatrix4f* a, const ovrMatrix4f* b) {
|
||||
ovrMatrix4f out;
|
||||
out.M[0][0] = a->M[0][0] * b->M[0][0] + a->M[0][1] * b->M[1][0] + a->M[0][2] * b->M[2][0] +
|
||||
a->M[0][3] * b->M[3][0];
|
||||
out.M[1][0] = a->M[1][0] * b->M[0][0] + a->M[1][1] * b->M[1][0] + a->M[1][2] * b->M[2][0] +
|
||||
a->M[1][3] * b->M[3][0];
|
||||
out.M[2][0] = a->M[2][0] * b->M[0][0] + a->M[2][1] * b->M[1][0] + a->M[2][2] * b->M[2][0] +
|
||||
a->M[2][3] * b->M[3][0];
|
||||
out.M[3][0] = a->M[3][0] * b->M[0][0] + a->M[3][1] * b->M[1][0] + a->M[3][2] * b->M[2][0] +
|
||||
a->M[3][3] * b->M[3][0];
|
||||
|
||||
out.M[0][1] = a->M[0][0] * b->M[0][1] + a->M[0][1] * b->M[1][1] + a->M[0][2] * b->M[2][1] +
|
||||
a->M[0][3] * b->M[3][1];
|
||||
out.M[1][1] = a->M[1][0] * b->M[0][1] + a->M[1][1] * b->M[1][1] + a->M[1][2] * b->M[2][1] +
|
||||
a->M[1][3] * b->M[3][1];
|
||||
out.M[2][1] = a->M[2][0] * b->M[0][1] + a->M[2][1] * b->M[1][1] + a->M[2][2] * b->M[2][1] +
|
||||
a->M[2][3] * b->M[3][1];
|
||||
out.M[3][1] = a->M[3][0] * b->M[0][1] + a->M[3][1] * b->M[1][1] + a->M[3][2] * b->M[2][1] +
|
||||
a->M[3][3] * b->M[3][1];
|
||||
|
||||
out.M[0][2] = a->M[0][0] * b->M[0][2] + a->M[0][1] * b->M[1][2] + a->M[0][2] * b->M[2][2] +
|
||||
a->M[0][3] * b->M[3][2];
|
||||
out.M[1][2] = a->M[1][0] * b->M[0][2] + a->M[1][1] * b->M[1][2] + a->M[1][2] * b->M[2][2] +
|
||||
a->M[1][3] * b->M[3][2];
|
||||
out.M[2][2] = a->M[2][0] * b->M[0][2] + a->M[2][1] * b->M[1][2] + a->M[2][2] * b->M[2][2] +
|
||||
a->M[2][3] * b->M[3][2];
|
||||
out.M[3][2] = a->M[3][0] * b->M[0][2] + a->M[3][1] * b->M[1][2] + a->M[3][2] * b->M[2][2] +
|
||||
a->M[3][3] * b->M[3][2];
|
||||
|
||||
out.M[0][3] = a->M[0][0] * b->M[0][3] + a->M[0][1] * b->M[1][3] + a->M[0][2] * b->M[2][3] +
|
||||
a->M[0][3] * b->M[3][3];
|
||||
out.M[1][3] = a->M[1][0] * b->M[0][3] + a->M[1][1] * b->M[1][3] + a->M[1][2] * b->M[2][3] +
|
||||
a->M[1][3] * b->M[3][3];
|
||||
out.M[2][3] = a->M[2][0] * b->M[0][3] + a->M[2][1] * b->M[1][3] + a->M[2][2] * b->M[2][3] +
|
||||
a->M[2][3] * b->M[3][3];
|
||||
out.M[3][3] = a->M[3][0] * b->M[0][3] + a->M[3][1] * b->M[1][3] + a->M[3][2] * b->M[2][3] +
|
||||
a->M[3][3] * b->M[3][3];
|
||||
return out;
|
||||
}
|
||||
|
||||
XrVector3f ovrMatrix4f_ToEulerAngles(const ovrMatrix4f* m) {
|
||||
XrVector4f v1 = {0, 0, -1, 0};
|
||||
XrVector4f v2 = {1, 0, 0, 0};
|
||||
XrVector4f v3 = {0, 1, 0, 0};
|
||||
|
||||
XrVector4f forwardInVRSpace = XrVector4f_MultiplyMatrix4f(m, &v1);
|
||||
XrVector4f rightInVRSpace = XrVector4f_MultiplyMatrix4f(m, &v2);
|
||||
XrVector4f upInVRSpace = XrVector4f_MultiplyMatrix4f(m, &v3);
|
||||
|
||||
XrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y};
|
||||
XrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y};
|
||||
XrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y};
|
||||
|
||||
XrVector3f forwardNormal = XrVector3f_Normalized(forward);
|
||||
XrVector3f rightNormal = XrVector3f_Normalized(right);
|
||||
XrVector3f upNormal = XrVector3f_Normalized(up);
|
||||
|
||||
return XrVector3f_GetAnglesFromVectors(forwardNormal, rightNormal, upNormal);
|
||||
}
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
XrPosef
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
XrPosef XrPosef_Identity() {
|
||||
XrPosef r;
|
||||
r.orientation.x = 0;
|
||||
r.orientation.y = 0;
|
||||
r.orientation.z = 0;
|
||||
r.orientation.w = 1;
|
||||
r.position.x = 0;
|
||||
r.position.y = 0;
|
||||
r.position.z = 0;
|
||||
return r;
|
||||
XrPosef r;
|
||||
r.orientation.x = 0;
|
||||
r.orientation.y = 0;
|
||||
r.orientation.z = 0;
|
||||
r.orientation.w = 1;
|
||||
r.position.x = 0;
|
||||
r.position.y = 0;
|
||||
r.position.z = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
XrPosef XrPosef_Inverse(const XrPosef a) {
|
||||
|
@ -258,18 +40,6 @@ XrPosef XrPosef_Inverse(const XrPosef a) {
|
|||
return b;
|
||||
}
|
||||
|
||||
XrPosef XrPosef_Multiply(const XrPosef a, const XrPosef b) {
|
||||
XrPosef c;
|
||||
c.orientation = XrQuaternionf_Multiply(a.orientation, b.orientation);
|
||||
c.position = XrPosef_Transform(a, b.position);
|
||||
return c;
|
||||
}
|
||||
|
||||
XrVector3f XrPosef_Transform(const XrPosef a, const XrVector3f v) {
|
||||
XrVector3f r0 = XrQuaternionf_Rotate(a.orientation, v);
|
||||
return XrVector3f_Add(r0, a.position);
|
||||
}
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
|
@ -329,8 +99,56 @@ XrVector3f XrQuaternionf_Rotate(const XrQuaternionf a, const XrVector3f v) {
|
|||
}
|
||||
|
||||
XrVector3f XrQuaternionf_ToEulerAngles(const XrQuaternionf q) {
|
||||
ovrMatrix4f m = ovrMatrix4f_CreateFromQuaternion( &q );
|
||||
return ovrMatrix4f_ToEulerAngles(&m);
|
||||
float M[16];
|
||||
XrQuaternionf_ToMatrix4f( &q, M);
|
||||
|
||||
XrVector4f v1 = {0, 0, -1, 0};
|
||||
XrVector4f v2 = {1, 0, 0, 0};
|
||||
XrVector4f v3 = {0, 1, 0, 0};
|
||||
|
||||
XrVector4f forwardInVRSpace = XrVector4f_MultiplyMatrix4f(M, &v1);
|
||||
XrVector4f rightInVRSpace = XrVector4f_MultiplyMatrix4f(M, &v2);
|
||||
XrVector4f upInVRSpace = XrVector4f_MultiplyMatrix4f(M, &v3);
|
||||
|
||||
XrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y};
|
||||
XrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y};
|
||||
XrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y};
|
||||
|
||||
XrVector3f forwardNormal = XrVector3f_Normalized(forward);
|
||||
XrVector3f rightNormal = XrVector3f_Normalized(right);
|
||||
XrVector3f upNormal = XrVector3f_Normalized(up);
|
||||
|
||||
return XrVector3f_GetAnglesFromVectors(forwardNormal, rightNormal, upNormal);
|
||||
}
|
||||
|
||||
void XrQuaternionf_ToMatrix4f(const XrQuaternionf* q, float* matrix) {
|
||||
const float ww = q->w * q->w;
|
||||
const float xx = q->x * q->x;
|
||||
const float yy = q->y * q->y;
|
||||
const float zz = q->z * q->z;
|
||||
|
||||
float M[4][4];
|
||||
M[0][0] = ww + xx - yy - zz;
|
||||
M[0][1] = 2 * (q->x * q->y - q->w * q->z);
|
||||
M[0][2] = 2 * (q->x * q->z + q->w * q->y);
|
||||
M[0][3] = 0;
|
||||
|
||||
M[1][0] = 2 * (q->x * q->y + q->w * q->z);
|
||||
M[1][1] = ww - xx + yy - zz;
|
||||
M[1][2] = 2 * (q->y * q->z - q->w * q->x);
|
||||
M[1][3] = 0;
|
||||
|
||||
M[2][0] = 2 * (q->x * q->z - q->w * q->y);
|
||||
M[2][1] = 2 * (q->y * q->z + q->w * q->x);
|
||||
M[2][2] = ww - xx - yy + zz;
|
||||
M[2][3] = 0;
|
||||
|
||||
M[3][0] = 0;
|
||||
M[3][1] = 0;
|
||||
M[3][2] = 0;
|
||||
M[3][3] = 1;
|
||||
|
||||
memcpy(matrix, &M, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -341,22 +159,10 @@ XrVector3f, XrVector4f
|
|||
================================================================================
|
||||
*/
|
||||
|
||||
float XrVector3f_Length(const XrVector3f v) {
|
||||
return sqrtf(XrVector3f_LengthSquared(v));
|
||||
}
|
||||
|
||||
float XrVector3f_LengthSquared(const XrVector3f v) {
|
||||
return v.x * v.x + v.y * v.y + v.z * v.z;;
|
||||
}
|
||||
|
||||
XrVector3f XrVector3f_Add(const XrVector3f u, const XrVector3f v) {
|
||||
XrVector3f w;
|
||||
w.x = u.x + v.x;
|
||||
w.y = u.y + v.y;
|
||||
w.z = u.z + v.z;
|
||||
return w;
|
||||
}
|
||||
|
||||
XrVector3f XrVector3f_GetAnglesFromVectors(const XrVector3f forward, const XrVector3f right, const XrVector3f up) {
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
|
@ -397,7 +203,7 @@ XrVector3f XrVector3f_GetAnglesFromVectors(const XrVector3f forward, const XrVec
|
|||
}
|
||||
|
||||
XrVector3f XrVector3f_Normalized(const XrVector3f v) {
|
||||
float rcpLen = 1.0f / XrVector3f_Length(v);
|
||||
float rcpLen = 1.0f / sqrtf(XrVector3f_LengthSquared(v));
|
||||
return XrVector3f_ScalarMultiply(v, rcpLen);
|
||||
}
|
||||
|
||||
|
@ -409,11 +215,14 @@ XrVector3f XrVector3f_ScalarMultiply(const XrVector3f v, float scale) {
|
|||
return u;
|
||||
}
|
||||
|
||||
XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v) {
|
||||
XrVector4f XrVector4f_MultiplyMatrix4f(const float* m, const XrVector4f* v) {
|
||||
float M[4][4];
|
||||
memcpy(&M, m, sizeof(float) * 16);
|
||||
|
||||
XrVector4f out;
|
||||
out.x = a->M[0][0] * v->x + a->M[0][1] * v->y + a->M[0][2] * v->z + a->M[0][3] * v->w;
|
||||
out.y = a->M[1][0] * v->x + a->M[1][1] * v->y + a->M[1][2] * v->z + a->M[1][3] * v->w;
|
||||
out.z = a->M[2][0] * v->x + a->M[2][1] * v->y + a->M[2][2] * v->z + a->M[2][3] * v->w;
|
||||
out.w = a->M[3][0] * v->x + a->M[3][1] * v->y + a->M[3][2] * v->z + a->M[3][3] * v->w;
|
||||
out.x = M[0][0] * v->x + M[0][1] * v->y + M[0][2] * v->z + M[0][3] * v->w;
|
||||
out.y = M[1][0] * v->x + M[1][1] * v->y + M[1][2] * v->z + M[1][3] * v->w;
|
||||
out.z = M[2][0] * v->x + M[2][1] * v->y + M[2][2] * v->z + M[2][3] * v->w;
|
||||
out.w = M[3][0] * v->x + M[3][1] * v->y + M[3][2] * v->z + M[3][3] * v->w;
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -7,27 +7,12 @@
|
|||
#define EPSILON 0.001f
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
float M[4][4];
|
||||
} ovrMatrix4f;
|
||||
|
||||
float ToDegrees(float rad);
|
||||
float ToRadians(float deg);
|
||||
|
||||
// ovrMatrix4f
|
||||
float ovrMatrix4f_Minor(const ovrMatrix4f* m, int r0, int r1, int r2, int c0, int c1, int c2);
|
||||
ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q);
|
||||
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(const float angleLeft, const float angleRight, const float angleUp, const float angleDown, const float nearZ, const float farZ);
|
||||
ovrMatrix4f ovrMatrix4f_CreateRotation(const float radiansX, const float radiansY, const float radiansZ);
|
||||
ovrMatrix4f ovrMatrix4f_Inverse(const ovrMatrix4f* m);
|
||||
ovrMatrix4f ovrMatrix4f_Multiply(const ovrMatrix4f* a, const ovrMatrix4f* b);
|
||||
XrVector3f ovrMatrix4f_ToEulerAngles(const ovrMatrix4f* m);
|
||||
|
||||
// XrPosef
|
||||
XrPosef XrPosef_Identity();
|
||||
XrPosef XrPosef_Inverse(const XrPosef a);
|
||||
XrPosef XrPosef_Multiply(const XrPosef a, const XrPosef b);
|
||||
XrVector3f XrPosef_Transform(const XrPosef a, const XrVector3f v);
|
||||
|
||||
// XrQuaternionf
|
||||
XrQuaternionf XrQuaternionf_CreateFromVectorAngle(const XrVector3f axis, const float angle);
|
||||
|
@ -35,12 +20,11 @@ XrQuaternionf XrQuaternionf_Inverse(const XrQuaternionf q);
|
|||
XrQuaternionf XrQuaternionf_Multiply(const XrQuaternionf a, const XrQuaternionf b);
|
||||
XrVector3f XrQuaternionf_Rotate(const XrQuaternionf a, const XrVector3f v);
|
||||
XrVector3f XrQuaternionf_ToEulerAngles(const XrQuaternionf q);
|
||||
void XrQuaternionf_ToMatrix4f(const XrQuaternionf* q, float* m);
|
||||
|
||||
// XrVector3f, XrVector4f
|
||||
float XrVector3f_Length(const XrVector3f v);
|
||||
float XrVector3f_LengthSquared(const XrVector3f v);
|
||||
XrVector3f XrVector3f_Add(const XrVector3f u, const XrVector3f v);
|
||||
XrVector3f XrVector3f_GetAnglesFromVectors(const XrVector3f forward, const XrVector3f right, const XrVector3f up);
|
||||
XrVector3f XrVector3f_Normalized(const XrVector3f v);
|
||||
XrVector3f XrVector3f_ScalarMultiply(const XrVector3f v, float scale);
|
||||
XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v);
|
||||
XrVector4f XrVector4f_MultiplyMatrix4f(const float* m, const XrVector4f* v);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "VRRenderer.h"
|
||||
#include "OpenXRLoader.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
|
@ -16,12 +15,10 @@ XrPosef invViewTransform[2];
|
|||
XrFrameState frameState = {};
|
||||
bool initialized = false;
|
||||
bool stageSupported = false;
|
||||
ovrMatrix4f vrMatrix[VR_MATRIX_COUNT];
|
||||
int vrConfig[VR_CONFIG_MAX] = {};
|
||||
float vrConfigFloat[VR_CONFIG_FLOAT_MAX] = {};
|
||||
|
||||
XrVector3f hmdorientation;
|
||||
XrVector3f hmdposition;
|
||||
|
||||
void VR_UpdateStageBounds(ovrApp* pappState) {
|
||||
XrExtent2Df stageBounds = {};
|
||||
|
@ -297,96 +294,10 @@ bool VR_InitFrame( engine_t* engine ) {
|
|||
|
||||
// Update HMD and controllers
|
||||
hmdorientation = XrQuaternionf_ToEulerAngles(invViewTransform[0].orientation);
|
||||
hmdposition = invViewTransform[0].position;
|
||||
IN_VRInputFrame(engine);
|
||||
|
||||
engine->appState.LayerCount = 0;
|
||||
memset(engine->appState.Layers, 0, sizeof(ovrCompositorLayer_Union) * ovrMaxLayerCount);
|
||||
|
||||
// Update matrices
|
||||
for (int matrix = 0; matrix < VR_MATRIX_COUNT; matrix++) {
|
||||
if ((matrix == VR_PROJECTION_MATRIX_LEFT_EYE) || (matrix == VR_PROJECTION_MATRIX_RIGHT_EYE)) {
|
||||
float nearPlane = VR_GetConfigFloat(VR_CONFIG_FOV_SCALE) / 200.0f;
|
||||
vrMatrix[matrix] = ovrMatrix4f_CreateProjectionFov(fov.angleLeft, fov.angleRight, fov.angleUp, fov.angleDown, nearPlane, 0.0f );
|
||||
} else if ((matrix == VR_VIEW_MATRIX_LEFT_EYE) || (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) {
|
||||
bool flatScreen = false;
|
||||
XrPosef invView = invViewTransform[0];
|
||||
int vrMode = vrConfig[VR_CONFIG_MODE];
|
||||
if ((vrMode == VR_MODE_MONO_SCREEN) || (vrMode == VR_MODE_STEREO_SCREEN)) {
|
||||
invView = XrPosef_Identity();
|
||||
flatScreen = true;
|
||||
}
|
||||
|
||||
// get axis mirroring configuration
|
||||
float mx = vrConfig[VR_CONFIG_MIRROR_PITCH] ? -1.0f : 1.0f;
|
||||
float my = vrConfig[VR_CONFIG_MIRROR_YAW] ? -1.0f : 1.0f;
|
||||
float mz = vrConfig[VR_CONFIG_MIRROR_ROLL] ? -1.0f : 1.0f;
|
||||
|
||||
// ensure there is maximally one axis to mirror rotation
|
||||
if (mx + my + mz < 0) {
|
||||
mx *= -1.0f;
|
||||
my *= -1.0f;
|
||||
mz *= -1.0f;
|
||||
} else {
|
||||
invView = XrPosef_Inverse(invView);
|
||||
}
|
||||
|
||||
// create updated quaternion
|
||||
if (mx + my + mz < 3 - EPSILON) {
|
||||
XrVector3f rotation = XrQuaternionf_ToEulerAngles(invView.orientation);
|
||||
XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mx * ToRadians(rotation.x));
|
||||
XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, my * ToRadians(rotation.y));
|
||||
XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mz * ToRadians(rotation.z));
|
||||
invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw));
|
||||
}
|
||||
|
||||
vrMatrix[matrix] = ovrMatrix4f_CreateFromQuaternion(&invView.orientation);
|
||||
float scale = VR_GetConfigFloat(VR_CONFIG_6DOF_SCALE);
|
||||
if (!flatScreen && vrConfig[VR_CONFIG_6DOF_ENABLED]) {
|
||||
vrMatrix[matrix].M[0][3] -= hmdposition.x * (vrConfig[VR_CONFIG_MIRROR_AXIS_X] ? -1.0f : 1.0f) * scale;
|
||||
vrMatrix[matrix].M[1][3] -= hmdposition.y * (vrConfig[VR_CONFIG_MIRROR_AXIS_Y] ? -1.0f : 1.0f) * scale;
|
||||
vrMatrix[matrix].M[2][3] -= hmdposition.z * (vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f) * scale;
|
||||
}
|
||||
if (fabsf(VR_GetConfigFloat(VR_CONFIG_CAMERA_DISTANCE)) > 0.0f) {
|
||||
XrVector3f forward = {0.0f, 0.0f, VR_GetConfigFloat(VR_CONFIG_CAMERA_DISTANCE) * scale};
|
||||
forward = XrQuaternionf_Rotate(invView.orientation, forward);
|
||||
forward = XrVector3f_ScalarMultiply(forward, vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f);
|
||||
vrMatrix[matrix].M[0][3] += forward.x;
|
||||
vrMatrix[matrix].M[1][3] += forward.y;
|
||||
vrMatrix[matrix].M[2][3] += forward.z;
|
||||
}
|
||||
if (fabsf(VR_GetConfigFloat(VR_CONFIG_CAMERA_HEIGHT)) > 0.0f) {
|
||||
XrVector3f up = {0.0f, -VR_GetConfigFloat(VR_CONFIG_CAMERA_HEIGHT) * scale, 0.0f};
|
||||
up = XrQuaternionf_Rotate(invView.orientation, up);
|
||||
up = XrVector3f_ScalarMultiply(up, vrConfig[VR_CONFIG_MIRROR_AXIS_Y] ? -1.0f : 1.0f);
|
||||
vrMatrix[matrix].M[0][3] += up.x;
|
||||
vrMatrix[matrix].M[1][3] += up.y;
|
||||
vrMatrix[matrix].M[2][3] += up.z;
|
||||
}
|
||||
if (fabsf(VR_GetConfigFloat(VR_CONFIG_CAMERA_SIDE)) > 0.0f) {
|
||||
XrVector3f side = {-VR_GetConfigFloat(VR_CONFIG_CAMERA_SIDE) * scale, 0.0f, 0.0f};
|
||||
side = XrQuaternionf_Rotate(invView.orientation, side);
|
||||
side = XrVector3f_ScalarMultiply(side, vrConfig[VR_CONFIG_MIRROR_AXIS_X] ? -1.0f : 1.0f);
|
||||
vrMatrix[matrix].M[0][3] += side.x;
|
||||
vrMatrix[matrix].M[1][3] += side.y;
|
||||
vrMatrix[matrix].M[2][3] += side.z;
|
||||
}
|
||||
if (vrConfig[VR_CONFIG_HAS_UNIT_SCALE] && (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) {
|
||||
float dx = fabs(invViewTransform[1].position.x - invViewTransform[0].position.x);
|
||||
float dy = fabs(invViewTransform[1].position.y - invViewTransform[0].position.y);
|
||||
float dz = fabs(invViewTransform[1].position.z - invViewTransform[0].position.z);
|
||||
float ipd = sqrt(dx * dx + dy * dy + dz * dz);
|
||||
XrVector3f separation = {ipd * scale, 0.0f, 0.0f};
|
||||
separation = XrQuaternionf_Rotate(invView.orientation, separation);
|
||||
separation = XrVector3f_ScalarMultiply(separation, vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f);
|
||||
vrMatrix[matrix].M[0][3] -= separation.x;
|
||||
vrMatrix[matrix].M[1][3] -= separation.y;
|
||||
vrMatrix[matrix].M[2][3] -= separation.z;
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -550,6 +461,6 @@ void* VR_BindFramebuffer(engine_t *engine) {
|
|||
return ovrFramebuffer_SetCurrent(&engine->appState.Renderer.FrameBuffer[fboIndex]);
|
||||
}
|
||||
|
||||
ovrMatrix4f VR_GetMatrix( VRMatrix matrix ) {
|
||||
return vrMatrix[matrix];
|
||||
XrView VR_GetView(int eye) {
|
||||
return projections[eye];
|
||||
}
|
||||
|
|
|
@ -5,14 +5,7 @@
|
|||
|
||||
enum VRConfig {
|
||||
//switching between 2D and 3D
|
||||
VR_CONFIG_MODE, VR_CONFIG_3D_GEOMETRY_COUNT, VR_CONFIG_FORCE_2D,
|
||||
//camera setup
|
||||
VR_CONFIG_CAMERA_CONTROL,
|
||||
VR_CONFIG_HAS_UNIT_SCALE,
|
||||
//6DoF
|
||||
VR_CONFIG_6DOF_ENABLED, VR_CONFIG_MIRROR_UPDATED,
|
||||
VR_CONFIG_MIRROR_AXIS_X, VR_CONFIG_MIRROR_AXIS_Y, VR_CONFIG_MIRROR_AXIS_Z,
|
||||
VR_CONFIG_MIRROR_PITCH, VR_CONFIG_MIRROR_YAW, VR_CONFIG_MIRROR_ROLL,
|
||||
VR_CONFIG_MODE,
|
||||
//mouse cursor
|
||||
VR_CONFIG_MOUSE_SIZE, VR_CONFIG_MOUSE_X, VR_CONFIG_MOUSE_Y,
|
||||
//viewport setup
|
||||
|
@ -25,25 +18,12 @@ enum VRConfig {
|
|||
};
|
||||
|
||||
enum VRConfigFloat {
|
||||
// 6dof
|
||||
VR_CONFIG_6DOF_SCALE,
|
||||
// camera setup
|
||||
VR_CONFIG_FOV_SCALE, VR_CONFIG_CAMERA_DISTANCE,
|
||||
VR_CONFIG_CAMERA_HEIGHT, VR_CONFIG_CAMERA_SIDE, VR_CONFIG_CANVAS_DISTANCE,
|
||||
// 2D canvas positioning
|
||||
VR_CONFIG_MENU_PITCH, VR_CONFIG_MENU_YAW, VR_CONFIG_RECENTER_YAW,
|
||||
VR_CONFIG_CANVAS_DISTANCE, VR_CONFIG_MENU_PITCH, VR_CONFIG_MENU_YAW, VR_CONFIG_RECENTER_YAW,
|
||||
|
||||
VR_CONFIG_FLOAT_MAX
|
||||
};
|
||||
|
||||
enum VRMatrix {
|
||||
VR_PROJECTION_MATRIX_LEFT_EYE,
|
||||
VR_PROJECTION_MATRIX_RIGHT_EYE,
|
||||
VR_VIEW_MATRIX_LEFT_EYE,
|
||||
VR_VIEW_MATRIX_RIGHT_EYE,
|
||||
VR_MATRIX_COUNT
|
||||
};
|
||||
|
||||
enum VRMode {
|
||||
VR_MODE_MONO_SCREEN,
|
||||
VR_MODE_STEREO_SCREEN,
|
||||
|
@ -62,9 +42,8 @@ void VR_FinishFrame( engine_t* engine );
|
|||
|
||||
int VR_GetConfig( VRConfig config );
|
||||
void VR_SetConfig( VRConfig config, int value);
|
||||
|
||||
float VR_GetConfigFloat( VRConfigFloat config );
|
||||
void VR_SetConfigFloat( VRConfigFloat config, float value );
|
||||
|
||||
void* VR_BindFramebuffer(engine_t *engine);
|
||||
ovrMatrix4f VR_GetMatrix( VRMatrix matrix );
|
||||
XrView VR_GetView(int eye);
|
||||
|
|
Loading…
Add table
Reference in a new issue