From e02ac3c921d816945324f1a887a0ed1db12f342e Mon Sep 17 00:00:00 2001 From: sanine-a Date: Fri, 22 May 2020 15:19:55 -0500 Subject: create basic honey_camera --- CMakeLists.txt | 2 +- demo.c | 107 +++++++++++++++++++++++-------------------- demo.fs | 4 +- include/camera.h | 93 +++++++++++++++++++++++++++++++++++++ include/honey.h | 1 + include/shader.h | 2 +- src/camera.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/honey.c | 4 ++ src/shader.c | 4 +- src/texture.c | 2 +- 10 files changed, 301 insertions(+), 55 deletions(-) create mode 100644 include/camera.h create mode 100644 src/camera.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9222cc3..a0f9d68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ add_executable(honey_engine_demo demo.c) set(CMAKE_C_FLAGS "-g") -add_library(honey src/honey.c src/mesh.c src/primitives.c src/shader.c src/texture.c) +add_library(honey src/honey.c src/camera.c src/mesh.c src/primitives.c src/shader.c src/texture.c) add_library(glad src/glad.c) add_library(stb_image src/stb_image.c) diff --git a/demo.c b/demo.c index e2ef74a..d7df41b 100644 --- a/demo.c +++ b/demo.c @@ -5,14 +5,9 @@ honey_window window; unsigned int screen_width = 640; unsigned int screen_height = 480; -vec3 cameraPosition, cameraFacing, cameraUp; - -vec3 cameraPosition = { 0, 0, 3 }; -vec3 cameraFacing = { 0, 0, -1 }; -vec3 cameraUp = { 0, 1, 0 }; -float cameraSpeed = 2.0; -float cameraPitch = 0; -float cameraYaw = 0; +honey_camera camera; +float cameraSpeed = 3.0; +float camera_roll_speed = 1.0; const float cameraMouseSensitivity = 0.1; honey_mesh cube; @@ -51,24 +46,31 @@ void mouseCallback(GLFWwindow* window, double x, double y) { xOffset *= cameraMouseSensitivity; yOffset *= cameraMouseSensitivity; - cameraYaw += xOffset; - cameraPitch -= yOffset; + float yaw = glm_deg(camera.angle[1]) + xOffset; + float pitch = glm_deg(camera.angle[0]) - yOffset; - if (cameraPitch > 89) { cameraPitch = 89; } - if (cameraPitch < -89) { cameraPitch = -89; } + if (pitch > 89) { pitch = 89; } + if (pitch < -89) { pitch = -89; } - cameraFacing[0] = cos(glm_rad(cameraYaw))*cos(glm_rad(cameraPitch)); - cameraFacing[1] = sin(glm_rad(cameraPitch)); - cameraFacing[2] = sin(glm_rad(cameraYaw)) * cos(glm_rad(cameraPitch)); - glm_vec3_normalize(cameraFacing); + camera.angle[0] = glm_rad(pitch); + camera.angle[1] = glm_rad(yaw); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +void print_vec3(vec3 v) { + printf("(%f, %f, %f)\n", v[0], v[1], v[2]); +} + void update(float dt) { glfwPollEvents(); - glm_rotate_x(model, glm_rad(10*dt), model); + printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + print_vec3(camera.look_direction); + print_vec3(camera.up); + print_vec3(camera.right); + + //glm_rotate_x(model, glm_rad(10*dt), model); if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(window, true); @@ -85,28 +87,31 @@ void update(float dt) { if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { vec3 step; - glm_vec3_scale(cameraFacing, cameraSpeed*dt, step); - glm_vec3_add(cameraPosition, step, cameraPosition); + glm_vec3_scale(camera.look_direction, cameraSpeed*dt, step); + glm_vec3_add(camera.position, step, camera.position); } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { vec3 step; - glm_vec3_scale(cameraFacing, -cameraSpeed*dt, step); - glm_vec3_add(cameraPosition, step, cameraPosition); + glm_vec3_scale(camera.look_direction, -cameraSpeed*dt, step); + glm_vec3_add(camera.position, step, camera.position); } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { - vec3 direction, step; - glm_vec3_cross(cameraFacing, cameraUp, direction); - glm_vec3_normalize(direction); - glm_vec3_scale(direction, -cameraSpeed*dt, step); - glm_vec3_add(cameraPosition, step, cameraPosition); + vec3 step; + glm_vec3_scale(camera.right, cameraSpeed*dt, step); + glm_vec3_add(camera.position, step, camera.position); } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { - vec3 direction, step; - glm_vec3_cross(cameraFacing, cameraUp, direction); - glm_vec3_normalize(direction); - glm_vec3_scale(direction, cameraSpeed*dt, step); - glm_vec3_add(cameraPosition, step, cameraPosition); + vec3 step; + glm_vec3_scale(camera.right, -cameraSpeed*dt, step); + glm_vec3_add(camera.position, step, camera.position); + } + if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) { + camera.angle[2] += camera_roll_speed*dt; } + if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) { + camera.angle[2] -= camera_roll_speed*dt; + } + } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -122,19 +127,15 @@ void draw() { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } - glm_perspective_default(((float)screen_width)/screen_height, projection); - honey_shader_set_matrix_4fv(shader, "projection", (float*) projection); - - vec3 cameraDirection; - glm_vec3_add(cameraPosition, cameraFacing, cameraDirection); - glm_lookat(cameraPosition, cameraDirection, cameraUp, view); - honey_shader_set_matrix_4fv(shader, "view", (float*) view); + honey_camera_calculate_view(&camera); + honey_shader_set_mat4(shader, "view", camera.view); - honey_shader_set_matrix_4fv(shader, "model", (float*) model); + honey_shader_set_mat4(shader, "model", model); honey_texture_use(container, 0); honey_texture_use(happy_face, 1); + honey_mesh_draw(cube, shader); honey_mesh_draw(cube, shader); glfwSwapBuffers(window); @@ -171,16 +172,24 @@ int main() { honey_shader_set_int(shader, "happy_texture", 1); glm_mat4_identity(model); - glm_rotate_x(model, glm_rad(-55), model); - honey_shader_set_matrix_4fv(shader, "model", (float*) model); - - glm_lookat(cameraPosition, cameraFacing, cameraUp, view); - honey_shader_set_matrix_4fv(shader, "view", (float*) view); - - glm_mat4_identity(projection); - /* glm_perspective(glm_rad(90), float(screen_width)/screen_height, 0.1, 100); */ - glm_perspective_default(((float)screen_width)/screen_height, projection); - honey_shader_set_matrix_4fv(shader, "projection", (float*) projection); + //glm_rotate_x(model, glm_rad(-55), model); + honey_shader_set_mat4(shader, "model", model); + + vec3 camera_pos = { 4, 0, 0 }; + vec3 camera_angle = { 0, glm_rad(180), 0 }; + float camera_near = 0.1; + float camera_far = 100; + float camera_fov = glm_rad(45); + float camera_aspect_ratio = ((float) screen_width)/screen_height; + honey_camera_new_perspective(&camera, + camera_pos, + camera_angle, + camera_aspect_ratio, + camera_near, camera_far, + camera_fov); + + honey_shader_set_mat4(shader, "view", camera.view); + honey_shader_set_mat4(shader, "projection", camera.projection); glEnable(GL_DEPTH_TEST); diff --git a/demo.fs b/demo.fs index 84ed0fd..03159de 100644 --- a/demo.fs +++ b/demo.fs @@ -9,5 +9,7 @@ out vec4 FragColor; void main() { - FragColor = mix(texture(box_texture, texture_coordinate), texture(happy_texture, vec2(1,1)-texture_coordinate), 0.2); + FragColor = mix(texture(box_texture, texture_coordinate), + vec4(texture(happy_texture, texture_coordinate).xyz, 1.0), + 0.2); } diff --git a/include/camera.h b/include/camera.h new file mode 100644 index 0000000..983dae8 --- /dev/null +++ b/include/camera.h @@ -0,0 +1,93 @@ +#ifndef HONEY_CAMERA_H +#define HONEY_CAMERA_H + +/* @file camera.h + * + * @brief Define the basic honey_camera struct, associated functions, + * and common camera variants. + */ + +#include "common.h" + +enum honey_camera_projection { + HONEY_PERSPECTIVE, + HONEY_ORTHOGRAPHIC, +}; + +typedef struct { + vec3 position; + vec3 angle; /* pitch, yaw, roll */ + vec3 look_direction; + vec3 up; + vec3 right; + mat4 view; + mat4 projection; + enum honey_camera_projection projection_type; + float aspect_ratio; + float near, far; + float fov; + float ortho_left; + float ortho_right; + float ortho_top; + float ortho_bottom; +} honey_camera; + +/** @brief Create a new camera. + * + * @param[out] camera Pointer to the destination honey_camera. + * @param[in] position The position of the camera. + * @param[in] angle The Euler angles (pitch, yaw, roll) of the camera. + * @param[in] projection The type of projection to use. + * @param[in] projection_parameters The parameters to use for the projection matrix. + * Use honey_perspective_parameters for a perspective projection and + * honey_orthographic_parameters for an orthographic projection. + */ +void honey_camera_new(honey_camera* camera, + vec3 position, + vec3 angle, + enum honey_camera_projection projection_type, + float aspect_ratio, + float near, float far, + float fov, + float left, float right, float top, float bottom); + +void honey_camera_new_perspective(honey_camera* camera, + vec3 position, + vec3 angle, + float aspect_ratio, + float near, float far, + float fov); + +void honey_camera_new_orthographic(honey_camera* camera, + vec3 position, + vec3 angle, + float near, float far, + float left, float right, float top, float bottom); + +/** @brief (Re-)Calculate a camera's look_direction. + * + * @param[in] Pointer to the camera to re-calculate. + */ +void honey_camera_calculate_look_direction(honey_camera* camera); + +void honey_camera_calculate_up(honey_camera* camera); +void honey_camera_calculate_right(honey_camera* camera); + +/** @brief (Re-)Calculate a camera's view matrix. + * + * This function need only be called when the camera has been moved in some way. + * + * @param[in] camera Pointer to the camera to re-calculate. + */ +void honey_camera_calculate_view(honey_camera* camera); + +/** @brief (Re-)Calculate a camera's projection matrix. + * + * This function need only be called when the projection has changes in some way. + * Most commonly, this would be changing the FOV. + * + * @param[in] camera Pointer to the camera to re-calculate. + */ +void honey_camera_calculate_projection(honey_camera* camera); + +#endif diff --git a/include/honey.h b/include/honey.h index 3cddabc..3dbc5ab 100644 --- a/include/honey.h +++ b/include/honey.h @@ -6,6 +6,7 @@ * @brief Defines the basic loading and callback functions. */ +#include "camera.h" #include "common.h" #include "mesh.h" #include "primitives.h" diff --git a/include/shader.h b/include/shader.h index 610322e..cbef3de 100644 --- a/include/shader.h +++ b/include/shader.h @@ -52,7 +52,7 @@ void honey_shader_set_int(honey_shader shader, */ void honey_shader_set_mat4(honey_shader shader, char* matrix_name, - float* matrix); + mat4 matrix); /** @brief Use a shader. */ diff --git a/src/camera.c b/src/camera.c new file mode 100644 index 0000000..95636e9 --- /dev/null +++ b/src/camera.c @@ -0,0 +1,137 @@ +#include "include/camera.h" + +void honey_camera_new(honey_camera* camera, + vec3 position, + vec3 angle, + enum honey_camera_projection projection_type, + float aspect_ratio, + float near, float far, + float fov, + float left, float right, float top, float bottom) { + glm_vec3_copy(position, camera->position); + glm_vec3_copy(angle, camera->angle); + + camera->projection_type = projection_type; + + camera->aspect_ratio = aspect_ratio; + camera->near = near; + camera->far = far; + + if (projection_type == HONEY_PERSPECTIVE) { + camera->fov = fov; + } + else if (projection_type == HONEY_ORTHOGRAPHIC) { + camera->ortho_left = left; + camera->ortho_right = right; + camera->ortho_top = top; + camera->ortho_bottom = bottom; + } + + honey_camera_calculate_view(camera); + honey_camera_calculate_projection(camera); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_camera_new_perspective(honey_camera* camera, + vec3 position, + vec3 angle, + float aspect_ratio, + float near, float far, + float fov) { + honey_camera_new(camera, + position, angle, + HONEY_PERSPECTIVE, + aspect_ratio, near, far, fov, + 0, 0, 0, 0); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_camera_new_orthographic(honey_camera* camera, + vec3 position, + vec3 angle, + float near, float far, + float left, float right, float top, float bottom) { + honey_camera_new(camera, + position, angle, + HONEY_ORTHOGRAPHIC, + 0, + near, far, + 0, + left, right, top, bottom); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_camera_calculate_look_direction(honey_camera* camera) { + float pitch = camera->angle[0]; + float yaw = camera->angle[1]; + + float x = cos(pitch) * cos(yaw); + float y = sin(pitch); + float z = cos(pitch) * sin(yaw); + + camera->look_direction[0] = x; + camera->look_direction[1] = y; + camera->look_direction[2] = z; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_camera_calculate_up(honey_camera* camera) { + float pitch = camera->angle[0]; + float yaw = camera->angle[1]; + float roll = camera->angle[2]; + + camera->up[0] = 0; + camera->up[1] = 1; + camera->up[2] = 0; + + mat3 rot3; + mat4 rot4; + glm_mat4_identity(rot4); + glm_rotate(rot4, roll, camera->look_direction); + glm_mat4_pick3(rot4, rot3); + + glm_mat3_mulv(rot3, camera->up, camera->up); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_camera_calculate_right(honey_camera* camera) { + glm_vec3_cross(camera->up, camera->look_direction, camera->right); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_camera_calculate_view(honey_camera* camera) { + honey_camera_calculate_look_direction(camera); + honey_camera_calculate_up(camera); + honey_camera_calculate_right(camera); + + glm_look(camera->position, camera->look_direction, camera->up, camera->view); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_camera_calculate_projection(honey_camera* camera) { + if (camera->projection_type == HONEY_PERSPECTIVE) { + glm_mat4_identity(camera->projection); + glm_perspective(camera->fov, + camera->aspect_ratio, + camera->near, + camera->far, + camera->projection); + } + else if (camera->projection_type == HONEY_ORTHOGRAPHIC) { + glm_mat4_identity(camera->projection); + glm_ortho(camera->ortho_left, + camera->ortho_right, + camera->ortho_bottom, + camera->ortho_top, + camera->near, + camera->far, + camera->projection); + } +} diff --git a/src/honey.c b/src/honey.c index b6f783f..e9396f1 100644 --- a/src/honey.c +++ b/src/honey.c @@ -28,6 +28,10 @@ honey_window honey_setup(int screen_width, int screen_height, char* window_title return NULL; } + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return window; } diff --git a/src/shader.c b/src/shader.c index b9e13da..d726523 100644 --- a/src/shader.c +++ b/src/shader.c @@ -101,10 +101,10 @@ void honey_shader_set_int(honey_shader shader, void honey_shader_set_mat4(honey_shader shader, char* matrix_name, - float* matrix) { + mat4 matrix) { glUseProgram(shader); unsigned int matrix_location = glGetUniformLocation(shader, matrix_name); - glUniformMatrix4fv(matrix_location, 1, GL_FALSE, matrix); + glUniformMatrix4fv(matrix_location, 1, GL_FALSE, (float*) matrix); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/src/texture.c b/src/texture.c index c1a5843..dfdbdd2 100644 --- a/src/texture.c +++ b/src/texture.c @@ -20,7 +20,7 @@ enum honey_texture_result honey_texture_new(honey_texture* texture, } if (alpha_channel) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data); -- cgit v1.2.1