Projection matrices;

This commit is contained in:
bjorn 2016-09-26 23:48:09 -07:00
parent f531be3fc5
commit 435d7a9cf8
12 changed files with 183 additions and 75 deletions

View File

@ -10,24 +10,21 @@
#include <assimp/postprocess.h>
#include "../headset/headset.h"
typedef struct {
Shader* activeShader;
vec_mat4_t transforms;
mat4 lastTransform;
mat4 projection;
mat4 lastProjection;
} GraphicsState;
static GraphicsState graphicsState;
static GraphicsState state;
void lovrGraphicsInit() {
vec_init(&graphicsState.transforms);
vec_push(&graphicsState.transforms, mat4_init());
graphicsState.lastTransform = mat4_init();
memset(graphicsState.lastTransform, 0, 16);
graphicsState.projection = mat4_init();
graphicsState.lastProjection = mat4_init();
memset(graphicsState.lastProjection, 0, 16);
vec_init(&state.transforms);
vec_push(&state.transforms, mat4_init());
state.projection = mat4_init();
state.lastTransform = mat4_init();
state.lastProjection = mat4_init();
memset(state.lastTransform, 0, 16);
memset(state.lastProjection, 0, 16);
// TODO customize via lovr.conf
lovrGraphicsSetProjection(.1f, 100.f, 67 * M_PI / 180);
}
void lovrGraphicsClear(int color, int depth) {
@ -55,8 +52,8 @@ void lovrGraphicsPrepare() {
return;
}
mat4 transform = vec_last(&graphicsState.transforms);
mat4 lastTransform = graphicsState.lastTransform;
mat4 transform = vec_last(&state.transforms);
mat4 lastTransform = state.lastTransform;
if (memcmp(transform, lastTransform, 16 * sizeof(float))) {
int uniformId = lovrShaderGetUniformId(shader, "lovrTransform");
@ -64,8 +61,8 @@ void lovrGraphicsPrepare() {
memcpy(lastTransform, transform, 16 * sizeof(float));
}
mat4 projection = graphicsState.projection;
mat4 lastProjection = graphicsState.lastProjection;
mat4 projection = state.projection;
mat4 lastProjection = state.lastProjection;
if (memcmp(projection, lastProjection, 16 * sizeof(float))) {
int uniformId = lovrShaderGetUniformId(shader, "lovrProjection");
@ -88,48 +85,55 @@ void lovrGraphicsSetClearColor(float r, float g, float b, float a) {
}
Shader* lovrGraphicsGetShader() {
return graphicsState.activeShader;
return state.activeShader;
}
// TODO default shader
void lovrGraphicsSetShader(Shader* shader) {
graphicsState.activeShader = shader;
state.activeShader = shader;
glUseProgram(shader->id);
}
void lovrGraphicsSetProjection(float near, float far, float fov, float aspect) {
mat4_setProjection(graphicsState.projection, near, far, fov, aspect);
void lovrGraphicsGetProjection(float* near, float* far, float* fov) {
float aspect;
mat4_getProjection(state.projection, near, far, fov, &aspect);
}
void lovrGraphicsSetProjection(float near, float far, float fov) {
int width, height;
glfwGetWindowSize(window, &width, &height);
mat4_setProjection(state.projection, near, far, fov, (float) width / height);
}
int lovrGraphicsPush() {
vec_mat4_t* transforms = &graphicsState.transforms;
vec_mat4_t* transforms = &state.transforms;
if (transforms->length >= 64) { return 1; }
vec_push(transforms, mat4_copy(vec_last(transforms)));
return 0;
}
int lovrGraphicsPop() {
vec_mat4_t* transforms = &graphicsState.transforms;
vec_mat4_t* transforms = &state.transforms;
if (transforms->length <= 1) { return 1; }
mat4_deinit(vec_pop(transforms));
return 0;
}
void lovrGraphicsOrigin() {
vec_mat4_t* transforms = &graphicsState.transforms;
vec_mat4_t* transforms = &state.transforms;
mat4_setIdentity(vec_last(transforms));
}
void lovrGraphicsTranslate(float x, float y, float z) {
mat4_translate(vec_last(&graphicsState.transforms), x, y, z);
mat4_translate(vec_last(&state.transforms), x, y, z);
}
void lovrGraphicsRotate(float w, float x, float y, float z) {
mat4_rotate(vec_last(&graphicsState.transforms), w, x, y, z);
mat4_rotate(vec_last(&state.transforms), w, x, y, z);
}
void lovrGraphicsScale(float x, float y, float z) {
mat4_scale(vec_last(&graphicsState.transforms), x, y, z);
mat4_scale(vec_last(&state.transforms), x, y, z);
}
Buffer* lovrGraphicsNewBuffer(int size, BufferDrawMode drawMode, BufferUsage usage) {

View File

@ -6,6 +6,14 @@
#ifndef LOVR_GRAPHICS_TYPES
#define LOVR_GRAPHICS_TYPES
typedef vec_t(mat4) vec_mat4_t;
typedef struct {
Shader* activeShader;
vec_mat4_t transforms;
mat4 lastTransform;
mat4 projection;
mat4 lastProjection;
} GraphicsState;
#endif
void lovrGraphicsInit();
@ -16,7 +24,8 @@ void lovrGraphicsGetClearColor(float* r, float* g, float* b, float* a);
void lovrGraphicsSetClearColor(float r, float g, float b, float a);
Shader* lovrGraphicsGetShader();
void lovrGraphicsSetShader(Shader* shader);
void lovrGraphicsSetProjection(float near, float far, float fov, float aspect);
void lovrGraphicsGetProjection(float* near, float* far, float* fov);
void lovrGraphicsSetProjection(float near, float far, float fov);
int lovrGraphicsPush();
int lovrGraphicsPop();
void lovrGraphicsOrigin();

View File

@ -7,20 +7,24 @@ void lovrHeadsetInit() {
headset = viveInit();
}
void lovrHeadsetGetPosition(float* x, float* y, float* z) {
headset->interface->getPosition(headset, x, y, z);
void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
headset->interface->getAngularVelocity(headset, x, y, z);
}
void lovrHeadsetGetClipDistance(float* near, float* far) {
headset->interface->getClipDistance(headset, near, far);
}
void lovrHeadsetGetOrientation(float* x, float* y, float* z, float* w) {
headset->interface->getOrientation(headset, x, y, z, w);
}
void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
headset->interface->getVelocity(headset, x, y, z);
void lovrHeadsetGetPosition(float* x, float* y, float* z) {
headset->interface->getPosition(headset, x, y, z);
}
void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
headset->interface->getAngularVelocity(headset, x, y, z);
void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
headset->interface->getVelocity(headset, x, y, z);
}
int lovrHeadsetIsPresent() {
@ -30,3 +34,7 @@ int lovrHeadsetIsPresent() {
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata) {
headset->interface->renderTo(headset, callback, userdata);
}
void lovrHeadsetSetClipDistance(float near, float far) {
headset->interface->setClipDistance(headset, near, far);
}

View File

@ -4,12 +4,14 @@ typedef void (*headsetRenderCallback)(int eyeIndex, void* userdata);
typedef struct {
void (*getAngularVelocity)(void* headset, float* x, float* y, float* z);
void (*getClipDistance)(void* headset, float* near, float* far);
void (*getOrientation)(void* headset, float* x, float* y, float* z, float* w);
void (*getPosition)(void* headset, float* x, float* y, float* z);
const char* (*getType)(void* headset);
void (*getVelocity)(void* headset, float* x, float* y, float* z);
int (*isPresent)(void* headset);
void (*renderTo)(void* headset, headsetRenderCallback callback, void* userdata);
void (*setClipDistance)(void* headset, float near, float far);
} HeadsetInterface;
typedef struct {
@ -20,9 +22,11 @@ typedef struct {
void lovrHeadsetInit();
void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z);
void lovrHeadsetGetClipDistance(float* near, float* far);
void lovrHeadsetGetOrientation(float* x, float* y, float* z, float* w);
void lovrHeadsetGetPosition(float* x, float* y, float* z);
const char* lovrHeadsetGetType();
void lovrHeadsetGetVelocity(float* x, float* y, float* z);
int lovrHeadsetIsPresent();
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata);
void lovrHeadsetSetClipDistance(float near, float far);

View File

@ -10,6 +10,9 @@ typedef struct {
unsigned int deviceIndex;
float clipNear;
float clipFar;
uint32_t renderWidth;
uint32_t renderHeight;
@ -44,7 +47,7 @@ Headset* viveInit() {
}
EVRInitError vrError;
uint32_t vrHandle = VR_InitInternal(&vrError, EVRApplicationType_VRApplication_Scene);
VR_InitInternal(&vrError, EVRApplicationType_VRApplication_Scene);
if (vrError != EVRInitError_VRInitError_None) {
error("Problem initializing OpenVR");
@ -127,6 +130,13 @@ void viveGetAngularVelocity(void* headset, float* x, float* y, float* z) {
*z = pose.vAngularVelocity.v[2];
}
void viveGetClipDistance(void* headset, float* near, float* far) {
Headset* this = (Headset*) headset;
ViveState* state = this->state;
*near = state->clipNear;
*far = state->clipFar;
}
// TODO convert matrix to quaternion!
void viveGetOrientation(void* headset, float* x, float* y, float *z, float* w) {
*x = *y = *z = *w = 0.f;
@ -184,46 +194,32 @@ int viveIsPresent(void* headset) {
void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata) {
Headset* this = headset;
ViveState* state = this->state;
float headMatrix[16], eyeMatrix[16], projectionMatrix[16];
float (*matrix)[4];
EGraphicsAPIConvention graphicsConvention = EGraphicsAPIConvention_API_OpenGL;
TrackedDevicePose_t pose;
state->vrCompositor->WaitGetPoses(&pose, 1, NULL, 0);
float (*m)[4];
m = pose.mDeviceToAbsoluteTracking.m;
float headMatrix[16] = {
m[0][0], m[1][0], m[2][0], 0.0,
m[0][1], m[1][1], m[2][1], 0.0,
m[0][2], m[1][2], m[2][2], 0.0,
m[0][3], m[1][3], m[2][3], 1.0
};
mat4_invert(headMatrix);
matrix = pose.mDeviceToAbsoluteTracking.m;
mat4_invert(mat4_fromMat34(headMatrix, matrix));
for (int i = 0; i < 2; i++) {
EVREye eye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;
m = state->vrSystem->GetEyeToHeadTransform(eye).m;
float eyeMatrix[16] = {
m[0][0], m[1][0], m[2][0], 0.0,
m[0][1], m[1][1], m[2][1], 0.0,
m[0][2], m[1][2], m[2][2], 0.0,
m[0][3], m[1][3], m[2][3], 1.0
};
matrix = state->vrSystem->GetEyeToHeadTransform(eye).m;
mat4_invert(mat4_fromMat34(eyeMatrix, matrix));
m = state->vrSystem->GetProjectionMatrix(eye, 0.1f, 30.0f, EGraphicsAPIConvention_API_OpenGL).m;
float projectionMatrix[16] = {
m[0][0], m[1][0], m[2][0], m[3][0],
m[0][1], m[1][1], m[2][1], m[3][1],
m[0][2], m[1][2], m[2][2], m[3][2],
m[0][3], m[1][3], m[2][3], m[3][3]
};
float near = state->clipNear;
float far = state->clipFar;
matrix = state->vrSystem->GetProjectionMatrix(eye, near, far, graphicsConvention).m;
mat4_fromMat44(projectionMatrix, matrix);
Shader* shader = lovrGraphicsGetShader();
if (shader) {
int lovrTransformId = lovrShaderGetUniformId(shader, "lovrTransform");
int lovrProjectionId = lovrShaderGetUniformId(shader, "lovrProjection");
mat4 m = mat4_multiply(mat4_multiply(projectionMatrix, mat4_invert(eyeMatrix)), headMatrix);
lovrShaderSendFloatMat4(shader, lovrTransformId, m);
mat4 transformMatrix = mat4_multiply(eyeMatrix, headMatrix);
lovrShaderSendFloatMat4(shader, lovrTransformId, transformMatrix);
lovrShaderSendFloatMat4(shader, lovrProjectionId, projectionMatrix);
}
@ -243,8 +239,16 @@ void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata)
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
Texture_t eyeTexture = { (void*) state->resolveTexture, EGraphicsAPIConvention_API_OpenGL, EColorSpace_ColorSpace_Gamma };
Texture_t eyeTexture = { (void*) state->resolveTexture, graphicsConvention, EColorSpace_ColorSpace_Gamma };
EVRSubmitFlags flags = EVRSubmitFlags_Submit_Default;
state->vrCompositor->Submit(eye, &eyeTexture, NULL, flags);
}
}
void viveSetClipDistance(void* headset, float near, float far) {
Headset* this = (Headset*) headset;
ViveState* state = this->state;
state->clipNear = near;
state->clipFar = far;
// TODO recompute matrix (only if we're rendering?)
}

View File

@ -4,9 +4,11 @@ typedef char bool;
Headset* viveInit();
void viveGetAngularVelocity(void* headset, float* x, float* y, float* z);
void viveGetClipDistance(void* headset, float* near, float* far);
void viveGetOrientation(void* headset, float* x, float* y, float* z, float* w);
void viveGetPosition(void* headset, float* x, float* y, float* z);
const char* viveGetType(void* headset);
void viveGetVelocity(void* headset, float* x, float* y, float* z);
int viveIsPresent(void* headset);
void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata);
void viveSetClipDistance(void* headset, float near, float far);

View File

@ -11,6 +11,7 @@ const luaL_Reg lovrGraphics[] = {
{ "getClearColor", l_lovrGraphicsGetClearColor },
{ "setClearColor", l_lovrGraphicsSetClearColor },
{ "setShader", l_lovrGraphicsSetShader },
{ "getProjection", l_lovrGraphicsGetProjection },
{ "setProjection", l_lovrGraphicsSetProjection },
{ "push", l_lovrGraphicsPush },
{ "pop", l_lovrGraphicsPop },
@ -91,12 +92,20 @@ int l_lovrGraphicsSetShader(lua_State* L) {
return 0;
}
int l_lovrGraphicsGetProjection(lua_State* L) {
float near, far, fov;
lovrGraphicsGetProjection(&near, &far, &fov);
lua_pushnumber(L, near);
lua_pushnumber(L, far);
lua_pushnumber(L, fov);
return 3;
}
int l_lovrGraphicsSetProjection(lua_State* L) {
float near = luaL_checknumber(L, 1);
float far = luaL_checknumber(L, 2);
float fov = luaL_checknumber(L, 3);
float aspect = luaL_checknumber(L, 4);
lovrGraphicsSetProjection(near, far, fov, aspect);
lovrGraphicsSetProjection(near, far, fov);
return 0;
}

View File

@ -14,6 +14,7 @@ int l_lovrGraphicsGetClearColor(lua_State* L);
int l_lovrGraphicsSetClearColor(lua_State* L);
int l_lovrGraphicsGetShader(lua_State* L);
int l_lovrGraphicsSetShader(lua_State* L);
int l_lovrGraphicsGetProjection(lua_State* L);
int l_lovrGraphicsSetProjection(lua_State* L);
int l_lovrGraphicsPush(lua_State* L);
int l_lovrGraphicsPop(lua_State* L);

View File

@ -10,12 +10,14 @@ void renderHelper(int eyeIndex, void* userdata) {
}
const luaL_Reg lovrHeadset[] = {
{ "getPosition", l_lovrHeadsetGetPosition },
{ "getOrientation", l_lovrHeadsetGetPosition },
{ "getVelocity", l_lovrHeadsetGetVelocity },
{ "getAngularVelocity", l_lovrHeadsetGetAngularVelocity },
{ "getClipDistance", l_lovrHeadsetGetClipDistance },
{ "getOrientation", l_lovrHeadsetGetPosition },
{ "getPosition", l_lovrHeadsetGetPosition },
{ "getVelocity", l_lovrHeadsetGetVelocity },
{ "isPresent", l_lovrHeadsetIsPresent },
{ "renderTo", l_lovrHeadsetRenderTo },
{ "setClipDistance", l_lovrHeadsetSetClipDistance },
{ NULL, NULL }
};
@ -35,6 +37,14 @@ int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
return 3;
}
int l_lovrHeadsetGetClipDistance(lua_State* L) {
float near, far;
lovrHeadsetGetClipDistance(&near, &far);
lua_pushnumber(L, near);
lua_pushnumber(L, far);
return 2;
}
int l_lovrHeadsetGetOrientation(lua_State* L) {
float x, y, z, w;
lovrHeadsetGetOrientation(&x, &y, &z, &w);
@ -73,3 +83,11 @@ int l_lovrHeadsetRenderTo(lua_State* L) {
lovrHeadsetRenderTo(renderHelper, L);
return 0;
}
int l_lovrHeadsetSetClipDistance(lua_State* L) {
float near = luaL_checknumber(L, 1);
float far = luaL_checknumber(L, 2);
lovrHeadsetSetClipDistance(near, far);
return 0;
}

View File

@ -4,9 +4,11 @@
extern const luaL_Reg lovrHeadset[];
int l_lovrHeadsetInit(lua_State* L);
int l_lovrHeadsetGetPosition(lua_State* L);
int l_lovrHeadsetGetOrientation(lua_State* L);
int l_lovrHeadsetGetVelocity(lua_State* L);
int l_lovrHeadsetGetAngularVelocity(lua_State* L);
int l_lovrHeadsetGetClipDistance(lua_State* L);
int l_lovrHeadsetGetOrientation(lua_State* L);
int l_lovrHeadsetGetPosition(lua_State* L);
int l_lovrHeadsetGetVelocity(lua_State* L);
int l_lovrHeadsetIsPresent(lua_State* L);
int l_lovrHeadsetRenderTo(lua_State* L);
int l_lovrHeadsetSetClipDistance(lua_State* L);

View File

@ -21,6 +21,46 @@ mat4 mat4_copy(mat4 source) {
return matrix;
}
mat4 mat4_fromMat34(mat4 matrix, float (*source)[4]) {
matrix[0] = source[0][0];
matrix[1] = source[1][0];
matrix[2] = source[2][0];
matrix[3] = 0.f;
matrix[4] = source[0][1];
matrix[5] = source[1][1];
matrix[6] = source[2][1];
matrix[7] = 0.f;
matrix[8] = source[0][2];
matrix[9] = source[1][2];
matrix[10] = source[2][2];
matrix[11] = 0.f;
matrix[12] = source[0][3];
matrix[13] = source[1][3];
matrix[14] = source[2][3];
matrix[15] = 1.f;
return matrix;
}
mat4 mat4_fromMat44(mat4 matrix, float (*source)[4]) {
matrix[0] = source[0][0];
matrix[1] = source[1][0];
matrix[2] = source[2][0];
matrix[3] = source[3][0];
matrix[4] = source[0][1];
matrix[5] = source[1][1];
matrix[6] = source[2][1];
matrix[7] = source[3][1];
matrix[8] = source[0][2];
matrix[9] = source[1][2];
matrix[10] = source[2][2];
matrix[11] = source[3][2];
matrix[12] = source[0][3];
matrix[13] = source[1][3];
matrix[14] = source[2][3];
matrix[15] = source[3][3];
return matrix;
}
void mat4_deinit(mat4 matrix) {
free(matrix);
}
@ -77,6 +117,10 @@ mat4 mat4_setProjection(mat4 matrix, float near, float far, float fov, float asp
return matrix;
}
void mat4_getProjection(mat4 matrix, float* near, float* far, float* fov, float* aspect) {
*near = *far = *fov = *aspect = 0.f;
}
mat4 mat4_translate(mat4 matrix, float x, float y, float z) {
float translation[16];
mat4_setTranslation(translation, x, y, z);

View File

@ -3,11 +3,14 @@ typedef float* mat4;
mat4 mat4_init();
void mat4_deinit(mat4 matrix);
mat4 mat4_copy(mat4 source);
mat4 mat4_fromMat34(mat4 matrix, float (*source)[4]);
mat4 mat4_fromMat44(mat4 matrix, float (*source)[4]);
mat4 mat4_setIdentity(mat4 matrix);
mat4 mat4_setTranslation(mat4 matrix, float x, float y, float z);
mat4 mat4_setRotation(mat4 matrix, float w, float x, float y, float z);
mat4 mat4_setScale(mat4 matrix, float x, float y, float z);
mat4 mat4_setProjection(mat4 matrix, float near, float far, float fov, float aspect);
void mat4_getProjection(mat4 matrix, float* near, float* far, float* fov, float* aspect);
mat4 mat4_translate(mat4 matrix, float x, float y, float z);
mat4 mat4_rotate(mat4 matrix, float w, float x, float y, float z);
mat4 mat4_scale(mat4 matrix, float x, float y, float z);