engine

game engine on C
git clone git://git.evenfri.pw/engine.git
Log | Files | Refs | README

camera.c (4525B)


      1 #include <math.h>
      2 #include "engine.h"
      3 
      4 static editor_camera_t editor_storage;
      5 
      6 /* editor backend */
      7 static void editor_update_vectors(editor_camera_t *c) {
      8   float yr = c->yaw * PI / 180.0f;
      9   float pr = c->pitch * PI / 180.0f;
     10   vec3 front;
     11   front.x = cosf(yr) * cosf(pr);
     12   front.y = sinf(pr);
     13   front.z = sinf(yr) * cosf(pr);
     14   c->front = vec3_norm(front);
     15   c->right = vec3_norm(vec3_cross(c->front, c->scene_up));
     16   c->up = vec3_norm(vec3_cross(c->right, c->front));
     17 }
     18 
     19 static mat4 editor_view(editor_camera_t *c) {
     20   vec3 f = vec3_norm(c->front);
     21   vec3 s = vec3_norm(vec3_cross(f, c->up));
     22   vec3 u = vec3_cross(s, f);
     23   vec3 e = c->position;
     24   mat4 v;
     25   v.m[0] = s.x; v.m[4] = s.y; v.m[8]  = s.z; v.m[12] = -vec3_dot(s, e);
     26   v.m[1] = u.x; v.m[5] = u.y; v.m[9]  = u.z; v.m[13] = -vec3_dot(u, e);
     27   v.m[2] = -f.x; v.m[6] = -f.y; v.m[10] = -f.z; v.m[14] = vec3_dot(f, e);
     28   v.m[3] = 0.0f; v.m[7] = 0.0f; v.m[11] = 0.0f; v.m[15] = 1.0f;
     29   return v;
     30 }
     31 
     32 /* game backend */
     33 static mat4 game_view(game_obj_t *obj) {
     34   transform_t *t = game_obj_get_component(obj, COMP_TRANSFORM);
     35   if (!t) return mat4_identity();
     36   mat4 R  = mat4_mul(
     37   mat4_rotate_y(t->rot.y * PI / 180.0f),
     38   mat4_rotate_x(t->rot.x * PI / 180.0f));
     39   mat4 Rt;
     40   Rt.m[0] = R.m[0]; Rt.m[1] = R.m[4]; Rt.m[2]  = R.m[8];  Rt.m[3]  = 0;
     41   Rt.m[4] = R.m[1]; Rt.m[5] = R.m[5]; Rt.m[6]  = R.m[9];  Rt.m[7]  = 0;
     42   Rt.m[8] = R.m[2]; Rt.m[9] = R.m[6]; Rt.m[10] = R.m[10]; Rt.m[11] = 0;
     43   Rt.m[12] = 0; Rt.m[13] = 0; Rt.m[14] = 0; Rt.m[15] = 1;
     44   mat4 T = mat4_translate(-t->pos.x, -t->pos.y, -t->pos.z);
     45   return mat4_mul(Rt, T);
     46 }
     47 
     48 /* unified interface */
     49 
     50 void camera_init(vec3 position) {
     51   editor_camera_t *c = &editor_storage;
     52   c->position = position;
     53   c->scene_up = vec3_make(0.0f, 1.0f, 0.0f);
     54   c->yaw = c->pitch = 0.0f;
     55   c->speed = CAMERA_SPEED;
     56   c->sensitivity = CAMERA_SENSITIVITY;
     57   c->fov = CAMERA_FOV;
     58   c->near_plane = 0.1f;
     59   c->far_plane = 100.0f;
     60   editor_update_vectors(c);
     61 
     62   active_camera.kind = CAMERA_EDITOR;
     63   active_camera.impl.editor = c;
     64 }
     65 
     66 void camera_set_editor(void) {
     67   active_camera.kind = CAMERA_EDITOR;
     68   active_camera.impl.editor = &editor_storage;
     69 }
     70 
     71 void camera_set_game(game_obj_t *obj, camera_comp_t *comp) {
     72   active_camera.kind = CAMERA_GAME;
     73   active_camera.impl.game.obj = obj;
     74   active_camera.impl.game.comp = comp;
     75 }
     76 
     77 editor_camera_t *camera_editor(void) {
     78   return active_camera.kind == CAMERA_EDITOR ? active_camera.impl.editor : NULL;
     79 }
     80 
     81 mat4 camera_get_view(void) {
     82   switch (active_camera.kind) {
     83   case CAMERA_EDITOR: return editor_view(active_camera.impl.editor);
     84   case CAMERA_GAME: return game_view(active_camera.impl.game.obj);
     85   }
     86   return mat4_identity();
     87 }
     88 
     89 float camera_get_fov(void) {
     90   if (active_camera.kind == CAMERA_EDITOR)
     91   return active_camera.impl.editor->fov;
     92   return active_camera.impl.game.comp->fov;
     93 }
     94 
     95 float camera_get_near(void) {
     96   if (active_camera.kind == CAMERA_EDITOR)
     97   return active_camera.impl.editor->near_plane;
     98   return active_camera.impl.game.comp->near_plane;
     99 }
    100 
    101 float camera_get_far(void) {
    102   if (active_camera.kind == CAMERA_EDITOR)
    103   return active_camera.impl.editor->far_plane;
    104   return active_camera.impl.game.comp->far_plane;
    105 }
    106 
    107 void camera_process_keyboard(float dt) {
    108   editor_camera_t *c = camera_editor();
    109   if (!c) return;
    110   float v = c->speed * dt;
    111   if (glfwGetKey(Window, GLFW_KEY_E) == GLFW_PRESS) {
    112   c->position.x += c->front.x * v;
    113   c->position.y += c->front.y * v;
    114   c->position.z += c->front.z * v;
    115   }
    116   if (glfwGetKey(Window, GLFW_KEY_D) == GLFW_PRESS) {
    117   c->position.x -= c->front.x * v;
    118   c->position.y -= c->front.y * v;
    119   c->position.z -= c->front.z * v;
    120   }
    121   if (glfwGetKey(Window, GLFW_KEY_S) == GLFW_PRESS) {
    122   c->position.x -= c->right.x * v;
    123   c->position.y -= c->right.y * v;
    124   c->position.z -= c->right.z * v;
    125   }
    126   if (glfwGetKey(Window, GLFW_KEY_F) == GLFW_PRESS) {
    127   c->position.x += c->right.x * v;
    128   c->position.y += c->right.y * v;
    129   c->position.z += c->right.z * v;
    130   }
    131   if (glfwGetKey(Window, GLFW_KEY_SPACE) == GLFW_PRESS) c->position.y += v;
    132   if (glfwGetKey(Window, GLFW_KEY_Z)   == GLFW_PRESS) c->position.y -= v;
    133 }
    134 
    135 void camera_process_mouse(float dx, float dy) {
    136   editor_camera_t *c = camera_editor();
    137   if (!c) return;
    138   c->yaw += dx * c->sensitivity;
    139   c->pitch += dy * c->sensitivity;
    140   if (c->pitch >  89.0f) c->pitch =  89.0f;
    141   if (c->pitch < -89.0f) c->pitch = -89.0f;
    142   editor_update_vectors(c);
    143 }
    144 
    145 void camera_update_vectors(void) {
    146   editor_camera_t *c = camera_editor();
    147   if (c) editor_update_vectors(c);
    148 }