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 }