From 4c66d285ae50b01cf67a9d489c46a7dd41cadb7a Mon Sep 17 00:00:00 2001 From: matthew Date: Sat, 3 Nov 2018 16:21:43 +0000 Subject: [PATCH] Reworked camera --- gl/camera.c | 185 ++++++++++++++++++++++++++++------------------------ gl/camera.h | 13 ++-- 2 files changed, 106 insertions(+), 92 deletions(-) diff --git a/gl/camera.c b/gl/camera.c index 980c143..fc6c456 100644 --- a/gl/camera.c +++ b/gl/camera.c @@ -1,50 +1,98 @@ -#include "camera.h" -#include #include +#include +#include "camera.h" #include "input.h" -static vec3_t worldSpaceVec; -static float aspectRatio = 16.f/9.f; // sane default for the aspect ratio +static const float YAW = -90.f; +static const float PITCH = 0.0f; +static const float SPEED = 2.5f; +static const float SENSITIVITY = 0.1f; +static const float ZOOM = 45.0f; typedef struct { - vec3_t from, to, up; - mat4_t camera, perspective, worldToScreen; - float speed; + vec3_t position; + vec3_t front; + vec3_t up; + vec3_t right; + vec3_t worldUp; + + /* euler angles */ + float yaw; + float pitch; + + /* camera options */ + float movementSpeed; + float mouseSensitivity; + float zoom; + float aspectRatio; + float near; + float far; + + /* storing the final matrix to prevent multiple calculations/frame */ + mat4_t matrix; +} crpgCamera_t; + +double toRadians(double degrees) +{ + return degrees * (M_PI / 180.f); +} - // Axis' to manouver across. If 0, no movement is occuring - vec3_t pan, yaw, roll; -} Camera_t; +double toDegrees(double radians) +{ + return radians * (180.f / M_PI); +} -///TODO: figure out why this is failing -mat4_t recalcPerspective(float hFovDeg, float near, float far) +void updateMatrix(crpgCamera_t *ct) { - float vFovDeg = 2 * atan( tan(hFovDeg/2) * aspectRatio ); - float vFovRad = vFovDeg * (M_PI/180.f); + vec3_t to = v3_add(ct->position, ct->front); - return m4_perspective(vFovRad, aspectRatio, near, far); + mat4_t lookat = m4_look_at(ct->position, to, ct->up); + mat4_t perspective = m4_perspective(60, ct->aspectRatio, ct->near, ct->far); + ct->matrix = m4_mul(perspective, lookat); } -void crpgCameraSetAR(float ar) +void updateVectors(crpgCamera_t *ct) { - aspectRatio = ar; + /* calculate the new front vector */ + ct->front.x = cos(toRadians(ct->yaw)) * cos(toRadians(ct->pitch)); + ct->front.y = sin(toRadians(ct->pitch)); + ct->front.z = sin(toRadians(ct->yaw)) * cos(toRadians(ct->pitch)); + ct->front = v3_norm(ct->front); + + /* calculating the new right and up vectors */ + ct->right = v3_norm(v3_cross(ct->position, ct->worldUp)); + ct->up = v3_norm(v3_cross(ct->right, ct->front)); } -crpgCamera *crpgCameraNew(vec3_t from, vec3_t to, vec3_t up) +mat4_t *crpgCameraGetMat(crpgCamera *c) { - // ensuring that the world doesn't go mental - worldSpaceVec = vec3(1, 1, -1); - Camera_t *ct = malloc(sizeof(Camera_t)); - ct->from = from; - ct->to = to; - ct->up = up; - ct->camera = m4_look_at(from, to, up); - //ct->perspective = recalcPerspective(90.f, 1, 10); - ct->perspective = m4_perspective(60, aspectRatio, 1, 10); - ct->worldToScreen = m4_mul(ct->perspective, ct->camera); - ct->speed = 1.0f; + crpgCamera_t *ct = (crpgCamera_t *)c; + updateMatrix(ct); + return &(ct->matrix); +} - crpgCamera *c = (crpgCamera *) ct; +crpgCamera *crpgCameraNew(vec3_t position, vec3_t up) +{ + crpgCamera_t *ct = malloc(sizeof(crpgCamera_t)); + ct->position = position; + ct->up = up; + ct->worldUp = vec3(0,1,0); + + /* using some sane defaults */ + ct->front = vec3(0.0f, 0.0f, -1.0f); + ct->yaw = YAW; + ct->pitch = PITCH; + ct->zoom = ZOOM; + ct->movementSpeed = SPEED; + ct->mouseSensitivity = SENSITIVITY; + ct->aspectRatio = 16.f/9.f; + ct->near = 1.f; + ct->far = 10.f; + + updateVectors(ct); + + crpgCamera *c = (crpgCamera *)ct; return c; } @@ -57,74 +105,39 @@ void crpgCameraFree(crpgCamera *c) } } -void crpgCameraSetSpeed(crpgCamera *c, float speedPerSecond) +void crpgCameraSetZoom(crpgCamera *c, float zoom) { - if(c == NULL) return; - - Camera_t *ct = (Camera_t *) c; - ct->speed = speedPerSecond; + crpgCamera_t *ct = (crpgCamera_t *)c; + ct->zoom = zoom; } -// This function expects a vec3_t formatted with values of 1, 0 or -1. -// to represent if the axis should be panned across and the direction -void crpgCameraPan(crpgCamera *c, vec3_t panAxis) +void crpgCameraSetSpeed(crpgCamera *c, float speed) { - if(c == NULL) - return; - - Camera_t *ct = (Camera_t *) c; - ct->pan = panAxis; - + crpgCamera_t *ct = (crpgCamera_t *)c; + ct->movementSpeed = speed; } -mat4_t *crpgCameraGetMat(crpgCamera *c) +void crpgCameraSetSensitivity(crpgCamera *c, float sensitivity) { - Camera_t *ct = (Camera_t *)c; - return &(ct->worldToScreen); + crpgCamera_t *ct = (crpgCamera_t *)c; + ct->mouseSensitivity = sensitivity; } -// expecting components as {from, to, up} -void updatePan(vec3_t panAxis, vec3_t *components[3], float speed, float dtms) +void crpgCameraRender(crpgCamera *c, float dtms) { - int axis[] = { panAxis.x, panAxis.y, panAxis.z }; - float* fromArr[] = { &components[0]->x, &components[0]->y, &components[0]->z }; - float* toArr[] = { &components[1]->x, &components[1]->y, &components[1]->z }; - - for(int i = 0; i < 3; ++i){ - if(axis[i] != 0){ // if we should pan on this axis - int sign = 0; - sign = (axis[i] > 0) ? 1 : -1; - *fromArr[i] += sign * (speed/1000.f); - *toArr[i] += sign * (speed/1000.f); - } - } } -void crpgCameraUpdate(crpgCamera *c) +void crpgCameraUpdate(crpgCamera *c, float dtms) { - vec3_t panAxis = (vec3_t){0.f,0.f,0.f}; + /* + crpgCamera_t *ct = (crpgCamera_t *)c; + float velocity = ct->movementSpeed * dtms; - panAxis.x = crpgInputHeld(INPUT_CAMERA_PAN_RIGHT) ? 1 : 0; - panAxis.x = crpgInputHeld(INPUT_CAMERA_PAN_LEFT) ? -1 : panAxis.x; - - panAxis.y = crpgInputHeld(INPUT_CAMERA_PAN_UP) ? 1 : 0; - panAxis.y = crpgInputHeld(INPUT_CAMERA_PAN_DOWN) ? -1 : panAxis.y; - - panAxis.z = crpgInputHeld(INPUT_CAMERA_PAN_IN) ? 1 : 0; - panAxis.z = crpgInputHeld(INPUT_CAMERA_PAN_OUT) ? -1 : panAxis.z; - - Camera_t *ct = (Camera_t *)c; - ct->pan = panAxis; -} - -void crpgCameraRender(crpgCamera *c, float dtms) -{ - Camera_t *ct = (Camera_t *)c; - vec3_t *components[] = { &(ct->from), &(ct->to), &(ct->up) }; - - updatePan(ct->pan, components, ct->speed, dtms); - - // recalc camera matrices - ct->camera = m4_look_at(ct->from, ct->to, ct->up); - ct->worldToScreen = m4_mul(ct->perspective, ct->camera); + if(crpgInputHeld(INPUT_CAMERA_PAN_IN)){ + ct->position = v3_add(ct->position, v3_muls(ct->front, velocity)); + } + if(crpgInputHeld(INPUT_CAMERA_PAN_OUT)){ + ct->position = v3_sub(ct->position, v3_muls(ct->front, velocity)); + } + */ } diff --git a/gl/camera.h b/gl/camera.h index 030cc82..fbede13 100644 --- a/gl/camera.h +++ b/gl/camera.h @@ -1,15 +1,16 @@ #ifndef CAMERA_H #define CAMERA_H #include "math_3d.h" -#include + typedef struct {} crpgCamera; -crpgCamera *crpgCameraNew(vec3_t from, vec3_t to, vec3_t up); +crpgCamera *crpgCameraNew(vec3_t position, vec3_t up); void crpgCameraFree(crpgCamera *c); -void crpgCameraPan(crpgCamera *c, vec3_t panAxis); -void crpgCameraSetAR(float ar); mat4_t *crpgCameraGetMat(crpgCamera *c); -void crpgCameraSetSpeed(crpgCamera *c, float speedPerSecond); +void crpgCameraSetZoom(crpgCamera *c, float zoom); +void crpgCameraSetSpeed(crpgCamera *c, float speed); +void crpgCameraSetSensitivity(crpgCamera *c, float sensitivity); + void crpgCameraRender(crpgCamera *c, float dtms); -void crpgCameraUpdate(crpgCamera *c); +void crpgCameraUpdate(crpgCamera *c, float dtms); #endif//CAMERA_H -- 2.20.1