#include #include #include "voxel.h" #include "window.h" void camera_init(Camera *camera) { camera->fov = 70; camera->near = 0.1; camera->far = 1000; camera->look_speed = 100; camera->move_speed = 4.317 * 10; glm_vec3_zero(camera->position); glm_vec3_zero(camera->rotation); camera->frustum = camera_frustum(camera); } void camera_proj(Camera *camera, mat4 proj) { float aspect, tan_half_foxy; aspect = (float)window.width / (float)window.height; tan_half_foxy = tanf(camera->fov * (M_PI / 180)) / 2.0; glm_mat4_zero(proj); proj[0][0] = 1.0 / (aspect * tan_half_foxy); proj[1][1] = 1.0 / tan_half_foxy; proj[2][2] = camera->far / (camera->far - camera->near); proj[2][3] = 1; proj[3][2] = -(camera->far * camera->near) / (camera->far - camera->near); } void camera_view(Camera *camera, mat4 view) { float c3, s3, c2, s2, c1, s1; vec3 u, v, w; c3 = cosf(camera->rotation[2] * (M_PI / 180)); s3 = sinf(camera->rotation[2] * (M_PI / 180)); c2 = cosf(camera->rotation[0] * (M_PI / 180)); s2 = sin(camera->rotation[0] * (M_PI / 180)); c1 = cosf(camera->rotation[1] * (M_PI / 180)); s1 = sinf(camera->rotation[1] * (M_PI / 180)); u[0] = c1 * c3 + s1 * s2 * s3; u[1] = c2 * s3; u[2] = c1 * s2 * s3 - c3 * s1; v[0] = c3 * s1 * s2 - c1 * s3; v[1] = c2 * c3; v[2] = c1 * c3 * s2 + s1 * s3; w[0] = c2 * s1; w[1] = -s2; w[2] = c1 * c2; view[0][0] = u[0]; view[0][1] = v[0]; view[0][2] = w[0]; view[0][3] = 0; view[1][0] = u[1]; view[1][1] = v[1]; view[1][2] = w[1]; view[1][3] = 0; view[2][0] = u[2]; view[2][1] = v[2]; view[2][2] = w[2]; view[2][3] = 0; view[3][0] = -glm_dot(u, camera->position); view[3][1] = -glm_dot(v, camera->position); view[3][2] = -glm_dot(w, camera->position); view[3][3] = 1; } void camera_proj_view(Camera *camera, mat4 proj_view) { mat4 proj, view; camera_proj(camera, proj); camera_view(camera, view); glm_mat4_mul(proj, view, proj_view); } static void camera_update_rotation(Camera *camera) { vec3 rotate; glm_vec3_zero(rotate); if (key_down(GLFW_KEY_RIGHT)) rotate[1] += 1; if (key_down(GLFW_KEY_LEFT)) rotate[1] -= 1; if (key_down(GLFW_KEY_UP)) rotate[0] -= 1; if (key_down(GLFW_KEY_DOWN)) rotate[0] += 1; glm_normalize(rotate); camera->rotation[0] += camera->look_speed * delta_time * rotate[0]; camera->rotation[1] += camera->look_speed * delta_time * rotate[1]; camera->rotation[0] = glm_clamp(camera->rotation[0], -90, 90); //camera->rotation[1] = camera->rotation[0] % 360.0; } static void camera_update_movement(Camera *camera) { vec3 forward, left, up, move; float yaw; yaw = camera->rotation[1] * (M_PI / 180); glm_vec3_zero(forward); forward[0] = sinf(yaw); forward[2] = cosf(yaw); glm_vec3_zero(left); left[0] = -forward[2]; left[2] = forward[0]; glm_vec3_zero(up); up[1] = 1; glm_vec3_zero(move); if (key_down(GLFW_KEY_W)) glm_vec3_add(move, forward, move); if (key_down(GLFW_KEY_S)) glm_vec3_sub(move, forward, move); if (key_down(GLFW_KEY_A)) glm_vec3_add(move, left, move); if (key_down(GLFW_KEY_D)) glm_vec3_sub(move, left, move); if (key_down(GLFW_KEY_E)) glm_vec3_add(move, up, move); if (key_down(GLFW_KEY_Q)) glm_vec3_sub(move, up, move); glm_normalize(move); glm_vec3_scale(move, camera->move_speed * delta_time, move); glm_vec3_add(camera->position, move, camera->position); } void camera_update(Camera *camera) { camera_update_rotation(camera); camera_update_movement(camera); camera->frustum = camera_frustum(camera); } Frustum camera_frustum(Camera *camera) { Frustum frustum; mat4 proj_view; camera_proj_view(camera, proj_view); glm_mat4_transpose(proj_view); // left glm_vec4_add(proj_view[3], proj_view[0], frustum.left); // right glm_vec4_sub(proj_view[3], proj_view[0], frustum.right); // bottom glm_vec4_add(proj_view[3], proj_view[1], frustum.bottom); // top glm_vec4_sub(proj_view[3], proj_view[1], frustum.top); // near glm_vec4_add(proj_view[3], proj_view[2], frustum.near); // far glm_vec4_sub(proj_view[3], proj_view[2], frustum.far); return frustum; } bool aabb_in_plane(AABB *aabb, Plane plane) { vec3 p; float f; p[0] = plane[0] >= 0 ? aabb->max[0] : aabb->min[0]; p[1] = plane[1] >= 0 ? aabb->max[1] : aabb->min[1]; p[2] = plane[2] >= 0 ? aabb->max[2] : aabb->min[2]; f = glm_vec3_dot(p, plane) + plane[3]; return f >= 0.0f; } bool aabb_in_frustum(AABB *aabb, Frustum *frustum) { return aabb_in_plane(aabb, frustum->near) && aabb_in_plane(aabb, frustum->far) && aabb_in_plane(aabb, frustum->left) && aabb_in_plane(aabb, frustum->right) && aabb_in_plane(aabb, frustum->top) && aabb_in_plane(aabb, frustum->bottom); }