diff options
-rw-r--r-- | CMakeLists.txt | 23 | ||||
-rw-r--r-- | demo/main.lua | 16 | ||||
-rw-r--r-- | src/camera/camera.c | 137 | ||||
-rw-r--r-- | src/camera/camera.h | 132 | ||||
-rw-r--r-- | src/common.h | 77 | ||||
-rw-r--r-- | src/error/error.c | 126 | ||||
-rw-r--r-- | src/error/error.h | 7 | ||||
-rw-r--r-- | src/glad/glad.c (renamed from src/glad.c) | 0 | ||||
-rw-r--r-- | src/glad/glad.h (renamed from src/glad.h) | 0 | ||||
-rw-r--r-- | src/glad/khrplatform.h (renamed from src/khrplatform.h) | 0 | ||||
-rw-r--r-- | src/honey.c | 69 | ||||
-rw-r--r-- | src/honey.h | 52 | ||||
-rw-r--r-- | src/input.h | 376 | ||||
l--------- | src/input/.#input.h | 1 | ||||
-rw-r--r-- | src/input/input.c | 437 | ||||
-rw-r--r-- | src/input/input.h | 194 | ||||
-rw-r--r-- | src/light/light.c | 20 | ||||
-rw-r--r-- | src/light/light.h | 33 | ||||
-rw-r--r-- | src/main.c | 19 | ||||
-rw-r--r-- | src/mesh/mesh.c | 86 | ||||
-rw-r--r-- | src/mesh/mesh.h | 57 | ||||
-rw-r--r-- | src/model/model.c | 121 | ||||
-rw-r--r-- | src/model/model.h | 29 | ||||
-rw-r--r-- | src/primitives/primitives.c | 180 | ||||
-rw-r--r-- | src/primitives/primitives.h | 59 | ||||
-rw-r--r-- | src/shader/shader.c | 224 | ||||
-rw-r--r-- | src/shader/shader.h | 117 | ||||
-rw-r--r-- | src/stb_image/stb_image.c (renamed from src/stb_image.c) | 0 | ||||
-rw-r--r-- | src/stb_image/stb_image.h (renamed from src/stb_image.h) | 0 | ||||
-rw-r--r-- | src/texture/texture.c | 45 | ||||
-rw-r--r-- | src/texture/texture.h | 42 |
31 files changed, 2270 insertions, 409 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0726040..21f5467 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.2) project(honey_engine_demo) -#set(CMAKE_C_FLAGS "-Wall -Wextra -Werror -Wfatal-errors -Wpedantic") +set(CMAKE_C_FLAGS "-Wall -Wextra -Werror -Wfatal-errors -Wpedantic") find_package(OpenGL REQUIRED) find_package(Lua51 REQUIRED) @@ -10,10 +10,23 @@ include_directories(${LUA_INCLUDE_DIR}) set(CMAKE_C_FLAGS "-g") -add_library(glad src/glad.c) -add_library(stb_image src/stb_image.c) - -add_executable(honey src/main.c) +add_library(glad src/glad/glad.c) +add_library(stb_image src/stb_image/stb_image.c) + +set(SOURCE_FILES + src/main.c + src/camera/camera.c + src/error/error.c + src/honey.c + src/input/input.c + src/light/light.c + src/mesh/mesh.c + src/model/model.c + src/primitives/primitives.c + src/shader/shader.c + src/texture/texture.c) + +add_executable(honey ${SOURCE_FILES}) set(LIBRARIES ${LUA_LIBRARIES} assimp glfw GL glad stb_image dl m) target_link_libraries(honey ${LIBRARIES}) diff --git a/demo/main.lua b/demo/main.lua index afc94d2..8c0072f 100644 --- a/demo/main.lua +++ b/demo/main.lua @@ -4,11 +4,11 @@ end local total_time = 0 -function honey.update(dt) - total_time = total_time + dt - print(dt) -end - -function honey.draw() - print('draw!') -end +--function honey.update(dt) +-- total_time = total_time + dt +-- print(dt) +--end +-- +--function honey.draw() +-- print('draw!') +--end diff --git a/src/camera/camera.c b/src/camera/camera.c new file mode 100644 index 0000000..44f480d --- /dev/null +++ b/src/camera/camera.c @@ -0,0 +1,137 @@ +#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/camera/camera.h b/src/camera/camera.h new file mode 100644 index 0000000..b8d3b61 --- /dev/null +++ b/src/camera/camera.h @@ -0,0 +1,132 @@ +#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. + * + * The full camera creation function. Most of the time, you will probably use either + * honey_camera_new_perspective() or honey_camera_new_projection() instead. + * + * @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_type The type of projection to use. + * @param[in] aspect_ratio The aspect ratio of the camera. Set to zero if using orthographic projection. + * @param[in] near The distance of the near plane. + * @param[in] far The distance of the far plane. + * @param[in] fov The field of view. Set to zero if using orthographic projection. + * @param[in] left The leftmost distance. Set to zero if using perspective projection. + * @param[in] right The rightmost distance. Set to zero if using perspective projection. + * @param[in] top The uppermost distance. Set to zero if using perspective projection. + * @param[in] bottom The lowest distance. Set to zero if using perspective 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); + +/** @brief Create a camera with a perspective projection matrix. + * + * @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] aspect_ratio The aspect ratio of the camera. + * @param[in] near The distance of the near plane. + * @param[in] far The distance of the far plane. + * @param[in] fov The field of view. + */ +void honey_camera_new_perspective(honey_camera* camera, + vec3 position, + vec3 angle, + float aspect_ratio, + float near, float far, + float fov); + +/** @brief Create a camera with an orthographic projection matrix. + * + * @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] near The distance of the near plane. + * @param[in] far The distance of the far plane. + * @param[in] left The leftmost distance. + * @param[in] right The rightmost distance. + * @param[in] top The uppermost distance. + * @param[in] bottom The lowest distance. + */ +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); + +/** @brief (Re-)Calculate a camera's up vector. + * + * @param[in] Pointer to the camera to re-calculate. + */ +void honey_camera_calculate_up(honey_camera* camera); + +/** @brief (Re-)Calculate a camera's right vector. + * + * @param[in] Pointer to the camera to re-calculate. + */ +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/src/common.h b/src/common.h new file mode 100644 index 0000000..ede67cd --- /dev/null +++ b/src/common.h @@ -0,0 +1,77 @@ +#ifndef HONEY_COMMON_H +#define HONEY_COMMON_H + +// standard c libraries +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> + +// POSIX options +#include <unistd.h> + +// lua interpreter +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +// glad +#include "glad/glad.h" +#include <GLFW/glfw3.h> + +// c opengl mathematics function +#include <cglm/cglm.h> +#include <cglm/call.h> + +// assimp +#include <assimp/cimport.h> +#include <assimp/scene.h> +#include <assimp/postprocess.h> + +// stb image +#include "stb_image/stb_image.h" + +typedef GLFWwindow* honey_window; + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +typedef enum { + /* generic results */ + HONEY_OK, + HONEY_MEMORY_ALLOCATION_ERROR, + HONEY_FILE_READ_ERROR, + + /* shader errors */ + HONEY_VERTEX_SHADER_COMPILATION_ERROR, + HONEY_FRAGMENT_SHADER_COMPILATION_ERROR, + HONEY_SHADER_LINK_ERROR, + + /* mesh errors */ + HONEY_MESH_BAD_VERTEX_DATA, + HONEY_MESH_BAD_INDEX_DATA, + + /* model errors */ + HONEY_MODEL_LOAD_ERROR, + + HONEY_N_ERRORS +} honey_result; + +#define HONEY_ERROR_DATA_STRING_LENGTH 4096 + +static struct { + char string1[HONEY_ERROR_DATA_STRING_LENGTH]; + char string2[HONEY_ERROR_DATA_STRING_LENGTH]; +} honey_error_data; + +void honey_error_clear_strings(); +void honey_error_set_string1(char* string); +void honey_error_set_string2(char* string); + +/** @brief Generate a human-readable error message. + * + * @param[out] error_string A string with at least 3*HONEY_ERROR_DATA_STRING_LENGTH characters to store the result + * @param[in] error The error to generate a message for + */ +void honey_human_readable_error(char* error_string, honey_result error); + +#endif diff --git a/src/error/error.c b/src/error/error.c new file mode 100644 index 0000000..671d34e --- /dev/null +++ b/src/error/error.c @@ -0,0 +1,126 @@ +#include "../common.h" + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_error_clear_strings() { + memset(honey_error_data.string1, 0, HONEY_ERROR_DATA_STRING_LENGTH); + memset(honey_error_data.string2, 0, HONEY_ERROR_DATA_STRING_LENGTH); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_error_set_string1(char* string) { + size_t n_bytes = strlen(string) + 1; + if (n_bytes > HONEY_ERROR_DATA_STRING_LENGTH) + n_bytes = HONEY_ERROR_DATA_STRING_LENGTH; + memcpy(honey_error_data.string1, string, n_bytes); + honey_error_data.string1[HONEY_ERROR_DATA_STRING_LENGTH-1] = 0; +} + +void honey_error_set_string2(char* string) { + size_t n_bytes = strlen(string) + 1; + if (n_bytes > HONEY_ERROR_DATA_STRING_LENGTH) + n_bytes = HONEY_ERROR_DATA_STRING_LENGTH; + memcpy(honey_error_data.string2, string, n_bytes); + honey_error_data.string2[HONEY_ERROR_DATA_STRING_LENGTH-1] = 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_human_readable_error(char* error_string, honey_result error) { + size_t string_size = sizeof(char)*3*HONEY_ERROR_DATA_STRING_LENGTH; + + switch(error) { + case HONEY_OK: + snprintf(error_string, string_size, "[honey] OK"); + break; + + case HONEY_MEMORY_ALLOCATION_ERROR: + snprintf(error_string, string_size, "[honey] ERROR: failed to allocate memory"); + break; + + case HONEY_FILE_READ_ERROR: + if (honey_error_data.string1 != NULL) { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to read file '%s'", + honey_error_data.string1); + } else { + snprintf(error_string, string_size, "[honey] ERROR: failed to read file"); + } + break; + + case HONEY_VERTEX_SHADER_COMPILATION_ERROR: + if (honey_error_data.string1 != NULL) { + if (honey_error_data.string2 != NULL) { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile vertex shader '%s'\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string2, + honey_error_data.string1); + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile vertex shader\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string1); + } + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile vertex shader."); + } + break; + + + case HONEY_FRAGMENT_SHADER_COMPILATION_ERROR: + if (honey_error_data.string1 != NULL) { + if (honey_error_data.string2 != NULL) { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile fragment shader '%s'\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string2, + honey_error_data.string1); + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile fragment shader\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string1); + } + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile fragment shader."); + } + break; + + case HONEY_SHADER_LINK_ERROR: + break; + + case HONEY_MESH_BAD_VERTEX_DATA: + break; + + case HONEY_MESH_BAD_INDEX_DATA: + break; + + case HONEY_MODEL_LOAD_ERROR: + snprintf(error_string, + string_size, + "[honey] ERROR: model '%s' contains errors", + honey_error_data.string1); + break; + + default: + break; + } +} + + + + + + + diff --git a/src/error/error.h b/src/error/error.h new file mode 100644 index 0000000..e456c88 --- /dev/null +++ b/src/error/error.h @@ -0,0 +1,7 @@ +#ifndef HONEY_ERROR_H +#define HONEY_ERROR_H + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + +#endif diff --git a/src/glad.c b/src/glad/glad.c index 260f1c0..260f1c0 100644 --- a/src/glad.c +++ b/src/glad/glad.c diff --git a/src/glad.h b/src/glad/glad.h index cde8703..cde8703 100644 --- a/src/glad.h +++ b/src/glad/glad.h diff --git a/src/khrplatform.h b/src/glad/khrplatform.h index 5b55ea2..5b55ea2 100644 --- a/src/khrplatform.h +++ b/src/glad/khrplatform.h diff --git a/src/honey.c b/src/honey.c new file mode 100644 index 0000000..4d31090 --- /dev/null +++ b/src/honey.c @@ -0,0 +1,69 @@ +#include "honey.h" + +static void default_honey_update_callback(float dt) {} +static void default_honey_draw_callback() {} + +honey_window honey_setup(int screen_width, int screen_height, char* window_title) { + honey_update_callback = &default_honey_update_callback; + honey_draw_callback = &default_honey_draw_callback; + + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + honey_window window = glfwCreateWindow(screen_width, screen_height, window_title, NULL, NULL); + if (window == NULL) { + fprintf(stderr, "ERROR: failed to create window!\n"); + glfwTerminate(); + return NULL; + } + + glfwMakeContextCurrent(window); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) { + fprintf(stderr, "ERROR: failed to initialize GLAD!\n"); + glfwTerminate(); + return NULL; + } + + //honey_setup_keyboard(); + //glfwSetKeyCallback(window, default_honey_keyboard_callback); + + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + return window; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_set_update_callback(void (*update_callback)(float)) { + honey_update_callback = update_callback; +} + +void honey_set_draw_callback(void (*draw_callback)()) { + honey_draw_callback = draw_callback; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_run(honey_window window) { + float prevTime = 0; + float currentTime = 0; + float dt; + float draw_dt = 0; + + while(!glfwWindowShouldClose(window)) { + currentTime = (float) glfwGetTime(); + dt = currentTime - prevTime; + prevTime = currentTime; + + honey_update_callback(dt); + honey_draw_callback(); + } +} + + diff --git a/src/honey.h b/src/honey.h index c124903..c134894 100644 --- a/src/honey.h +++ b/src/honey.h @@ -1,6 +1,54 @@ -#ifndef HONEY_H -#define HONEY_H +#ifndef HONEY_ENGINE_H +#define HONEY_ENGINE_H +/** @file honey.h + * + * @brief Defines the basic loading and callback functions. +*/ +#include "common.h" + +#include "camera/camera.h" +#include "input/input.h" +#include "light/light.h" +#include "mesh/mesh.h" +#include "model/model.h" +#include "primitives/primitives.h" +#include "shader/shader.h" +#include "texture/texture.h" + +/** @brief Initialize Honey. + * + * @param[in] screen_width The desired width of the screen in pixels + * @param[in] screen_height The desired height of the screen in pixels + * @param[in] window_title Title to use for the window. + */ +honey_window honey_setup(int screen_width, int screen_height, char* window_title); + +static void (*honey_update_callback)(float dt); +static void (*honey_draw_callback)(); + +/** @brief Set the main update function. + * + * @param[in] update_callback The function to call every loop + */ +void honey_set_update_callback(void (*update_callback)(float)); + +/** @brief Set the main draw function + * + * @param[in] draw_callback The function to call every draw cycle + */ +void honey_set_draw_callback(void (*draw_callback)()); + +/** @brief The main game loop. + * + * @param[in] window The window the game is running in, created with honey_setup() + */ +void honey_run(honey_window window); + +#define honey_set_resize_callback glfwSetFramebufferSizeCallback +#define honey_set_mouse_move_callback glfwSetCursorPosCallback + +#define honey_quit glfwTerminate #endif diff --git a/src/input.h b/src/input.h deleted file mode 100644 index 77ff148..0000000 --- a/src/input.h +++ /dev/null @@ -1,376 +0,0 @@ -#ifndef HONEY_INPUT_H -#define HONEY_INPUT_H - -#include <lua.h> - -/* @brief Place a lua table containing the enum values for GLFW keys on the stack. */ -void honey_setup_input(lua_State* L) -{ - - lua_createtable(L, 0, 121); - - lua_pushinteger(L, 0); - lua_setfield(L, -2, "unknown"); - - lua_pushinteger(L, 1); - lua_setfield(L, -2, "space"); - - lua_pushinteger(L, 2); - lua_setfield(L, -2, "apostrophe"); - - lua_pushinteger(L, 3); - lua_setfield(L, -2, "comma"); - - lua_pushinteger(L, 4); - lua_setfield(L, -2, "minus"); - - lua_pushinteger(L, 5); - lua_setfield(L, -2, "period"); - - lua_pushinteger(L, 6); - lua_setfield(L, -2, "slash"); - - lua_pushinteger(L, 7); - lua_setfield(L, -2, "0"); - - lua_pushinteger(L, 8); - lua_setfield(L, -2, "1"); - - lua_pushinteger(L, 9); - lua_setfield(L, -2, "2"); - - lua_pushinteger(L, 10); - lua_setfield(L, -2, "3"); - - lua_pushinteger(L, 11); - lua_setfield(L, -2, "4"); - - lua_pushinteger(L, 12); - lua_setfield(L, -2, "5"); - - lua_pushinteger(L, 13); - lua_setfield(L, -2, "6"); - - lua_pushinteger(L, 14); - lua_setfield(L, -2, "7"); - - lua_pushinteger(L, 15); - lua_setfield(L, -2, "8"); - - lua_pushinteger(L, 16); - lua_setfield(L, -2, "9"); - - lua_pushinteger(L, 17); - lua_setfield(L, -2, "semicolon"); - - lua_pushinteger(L, 18); - lua_setfield(L, -2, "equal"); - - lua_pushinteger(L, 19); - lua_setfield(L, -2, "a"); - - lua_pushinteger(L, 20); - lua_setfield(L, -2, "b"); - - lua_pushinteger(L, 21); - lua_setfield(L, -2, "c"); - - lua_pushinteger(L, 22); - lua_setfield(L, -2, "d"); - - lua_pushinteger(L, 23); - lua_setfield(L, -2, "e"); - - lua_pushinteger(L, 24); - lua_setfield(L, -2, "f"); - - lua_pushinteger(L, 25); - lua_setfield(L, -2, "g"); - - lua_pushinteger(L, 26); - lua_setfield(L, -2, "h"); - - lua_pushinteger(L, 27); - lua_setfield(L, -2, "i"); - - lua_pushinteger(L, 28); - lua_setfield(L, -2, "j"); - - lua_pushinteger(L, 29); - lua_setfield(L, -2, "k"); - - lua_pushinteger(L, 30); - lua_setfield(L, -2, "l"); - - lua_pushinteger(L, 31); - lua_setfield(L, -2, "m"); - - lua_pushinteger(L, 32); - lua_setfield(L, -2, "n"); - - lua_pushinteger(L, 33); - lua_setfield(L, -2, "o"); - - lua_pushinteger(L, 34); - lua_setfield(L, -2, "p"); - - lua_pushinteger(L, 35); - lua_setfield(L, -2, "q"); - - lua_pushinteger(L, 36); - lua_setfield(L, -2, "r"); - - lua_pushinteger(L, 37); - lua_setfield(L, -2, "s"); - - lua_pushinteger(L, 38); - lua_setfield(L, -2, "t"); - - lua_pushinteger(L, 39); - lua_setfield(L, -2, "u"); - - lua_pushinteger(L, 40); - lua_setfield(L, -2, "v"); - - lua_pushinteger(L, 41); - lua_setfield(L, -2, "w"); - - lua_pushinteger(L, 42); - lua_setfield(L, -2, "x"); - - lua_pushinteger(L, 43); - lua_setfield(L, -2, "y"); - - lua_pushinteger(L, 44); - lua_setfield(L, -2, "z"); - - lua_pushinteger(L, 45); - lua_setfield(L, -2, "left_bracket"); - - lua_pushinteger(L, 46); - lua_setfield(L, -2, "backslash"); - - lua_pushinteger(L, 47); - lua_setfield(L, -2, "right_bracket"); - - lua_pushinteger(L, 48); - lua_setfield(L, -2, "grave_accent"); - - lua_pushinteger(L, 49); - lua_setfield(L, -2, "world_1"); - - lua_pushinteger(L, 50); - lua_setfield(L, -2, "world_2"); - - lua_pushinteger(L, 51); - lua_setfield(L, -2, "escape"); - - lua_pushinteger(L, 52); - lua_setfield(L, -2, "enter"); - - lua_pushinteger(L, 53); - lua_setfield(L, -2, "tab"); - - lua_pushinteger(L, 54); - lua_setfield(L, -2, "backspace"); - - lua_pushinteger(L, 55); - lua_setfield(L, -2, "insert"); - - lua_pushinteger(L, 56); - lua_setfield(L, -2, "delete"); - - lua_pushinteger(L, 57); - lua_setfield(L, -2, "right"); - - lua_pushinteger(L, 58); - lua_setfield(L, -2, "left"); - - lua_pushinteger(L, 59); - lua_setfield(L, -2, "down"); - - lua_pushinteger(L, 60); - lua_setfield(L, -2, "up"); - - lua_pushinteger(L, 61); - lua_setfield(L, -2, "page_up"); - - lua_pushinteger(L, 62); - lua_setfield(L, -2, "page_down"); - - lua_pushinteger(L, 63); - lua_setfield(L, -2, "home"); - - lua_pushinteger(L, 64); - lua_setfield(L, -2, "end"); - - lua_pushinteger(L, 65); - lua_setfield(L, -2, "caps_lock"); - - lua_pushinteger(L, 66); - lua_setfield(L, -2, "scroll_lock"); - - lua_pushinteger(L, 67); - lua_setfield(L, -2, "num_lock"); - - lua_pushinteger(L, 68); - lua_setfield(L, -2, "print_screen"); - - lua_pushinteger(L, 69); - lua_setfield(L, -2, "pause"); - - lua_pushinteger(L, 70); - lua_setfield(L, -2, "f1"); - - lua_pushinteger(L, 71); - lua_setfield(L, -2, "f2"); - - lua_pushinteger(L, 72); - lua_setfield(L, -2, "f3"); - - lua_pushinteger(L, 73); - lua_setfield(L, -2, "f4"); - - lua_pushinteger(L, 74); - lua_setfield(L, -2, "f5"); - - lua_pushinteger(L, 75); - lua_setfield(L, -2, "f6"); - - lua_pushinteger(L, 76); - lua_setfield(L, -2, "f7"); - - lua_pushinteger(L, 77); - lua_setfield(L, -2, "f8"); - - lua_pushinteger(L, 78); - lua_setfield(L, -2, "f9"); - - lua_pushinteger(L, 79); - lua_setfield(L, -2, "f10"); - - lua_pushinteger(L, 80); - lua_setfield(L, -2, "f11"); - - lua_pushinteger(L, 81); - lua_setfield(L, -2, "f12"); - - lua_pushinteger(L, 82); - lua_setfield(L, -2, "f13"); - - lua_pushinteger(L, 83); - lua_setfield(L, -2, "f14"); - - lua_pushinteger(L, 84); - lua_setfield(L, -2, "f15"); - - lua_pushinteger(L, 85); - lua_setfield(L, -2, "f16"); - - lua_pushinteger(L, 86); - lua_setfield(L, -2, "f17"); - - lua_pushinteger(L, 87); - lua_setfield(L, -2, "f18"); - - lua_pushinteger(L, 88); - lua_setfield(L, -2, "f19"); - - lua_pushinteger(L, 89); - lua_setfield(L, -2, "f20"); - - lua_pushinteger(L, 90); - lua_setfield(L, -2, "f21"); - - lua_pushinteger(L, 91); - lua_setfield(L, -2, "f22"); - - lua_pushinteger(L, 92); - lua_setfield(L, -2, "f23"); - - lua_pushinteger(L, 93); - lua_setfield(L, -2, "f24"); - - lua_pushinteger(L, 94); - lua_setfield(L, -2, "f25"); - - lua_pushinteger(L, 95); - lua_setfield(L, -2, "kp_0"); - - lua_pushinteger(L, 96); - lua_setfield(L, -2, "kp_1"); - - lua_pushinteger(L, 97); - lua_setfield(L, -2, "kp_2"); - - lua_pushinteger(L, 98); - lua_setfield(L, -2, "kp_3"); - - lua_pushinteger(L, 99); - lua_setfield(L, -2, "kp_4"); - - lua_pushinteger(L, 100); - lua_setfield(L, -2, "kp_5"); - - lua_pushinteger(L, 101); - lua_setfield(L, -2, "kp_6"); - - lua_pushinteger(L, 102); - lua_setfield(L, -2, "kp_7"); - - lua_pushinteger(L, 103); - lua_setfield(L, -2, "kp_8"); - - lua_pushinteger(L, 104); - lua_setfield(L, -2, "kp_9"); - - lua_pushinteger(L, 105); - lua_setfield(L, -2, "kp_decimal"); - - lua_pushinteger(L, 106); - lua_setfield(L, -2, "kp_divide"); - - lua_pushinteger(L, 107); - lua_setfield(L, -2, "kp_multiply"); - - lua_pushinteger(L, 108); - lua_setfield(L, -2, "kp_subtract"); - - lua_pushinteger(L, 109); - lua_setfield(L, -2, "kp_add"); - - lua_pushinteger(L, 110); - lua_setfield(L, -2, "kp_enter"); - - lua_pushinteger(L, 111); - lua_setfield(L, -2, "kp_equal"); - - lua_pushinteger(L, 112); - lua_setfield(L, -2, "left_shift"); - - lua_pushinteger(L, 113); - lua_setfield(L, -2, "left_control"); - - lua_pushinteger(L, 114); - lua_setfield(L, -2, "left_alt"); - - lua_pushinteger(L, 115); - lua_setfield(L, -2, "left_super"); - - lua_pushinteger(L, 116); - lua_setfield(L, -2, "right_shift"); - - lua_pushinteger(L, 117); - lua_setfield(L, -2, "right_control"); - - lua_pushinteger(L, 118); - lua_setfield(L, -2, "right_alt"); - - lua_pushinteger(L, 119); - lua_setfield(L, -2, "right_super"); - - lua_pushinteger(L, 120); - lua_setfield(L, -2, "menu"); -} - -#endif diff --git a/src/input/.#input.h b/src/input/.#input.h new file mode 120000 index 0000000..4ad0568 --- /dev/null +++ b/src/input/.#input.h @@ -0,0 +1 @@ +kate@ophelia.6336:1602737412
\ No newline at end of file diff --git a/src/input/input.c b/src/input/input.c new file mode 100644 index 0000000..31375cc --- /dev/null +++ b/src/input/input.c @@ -0,0 +1,437 @@ +#include "input.h" + +void honey_setup_keyboard() +{ + memset(honey_key_states, 0, sizeof(honey_key_states)); + memset(honey_key_callbacks, 0, sizeof(honey_key_callbacks)); + memset(honey_key_callbacks_data, 0, sizeof(honey_key_callbacks_data)); + + honey_keyboard_callback = &default_honey_keyboard_callback; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_setup_input(lua_State* L) +{ + lua_createtable(L, 0, 121); + + lua_pushinteger(L, HONEY_KEY_UNKNOWN); + lua_setfield(L, -2, "honey_key_unknown"); + + lua_pushinteger(L, HONEY_KEY_SPACE); + lua_setfield(L, -2, "honey_key_space"); + + lua_pushinteger(L, HONEY_KEY_APOSTROPHE); + lua_setfield(L, -2, "honey_key_apostrophe"); + + lua_pushinteger(L, HONEY_KEY_COMMA); + lua_setfield(L, -2, "honey_key_comma"); + + lua_pushinteger(L, HONEY_KEY_MINUS); + lua_setfield(L, -2, "honey_key_minus"); + + lua_pushinteger(L, HONEY_KEY_PERIOD); + lua_setfield(L, -2, "honey_key_period"); + + lua_pushinteger(L, HONEY_KEY_SLASH); + lua_setfield(L, -2, "honey_key_slash"); + + lua_pushinteger(L, HONEY_KEY_0); + lua_setfield(L, -2, "honey_key_0"); + + lua_pushinteger(L, HONEY_KEY_1); + lua_setfield(L, -2, "honey_key_1"); + + lua_pushinteger(L, HONEY_KEY_2); + lua_setfield(L, -2, "honey_key_2"); + + lua_pushinteger(L, HONEY_KEY_3); + lua_setfield(L, -2, "honey_key_3"); + + lua_pushinteger(L, HONEY_KEY_4); + lua_setfield(L, -2, "honey_key_4"); + + lua_pushinteger(L, HONEY_KEY_5); + lua_setfield(L, -2, "honey_key_5"); + + lua_pushinteger(L, HONEY_KEY_6); + lua_setfield(L, -2, "honey_key_6"); + + lua_pushinteger(L, HONEY_KEY_7); + lua_setfield(L, -2, "honey_key_7"); + + lua_pushinteger(L, HONEY_KEY_8); + lua_setfield(L, -2, "honey_key_8"); + + lua_pushinteger(L, HONEY_KEY_9); + lua_setfield(L, -2, "honey_key_9"); + + lua_pushinteger(L, HONEY_KEY_SEMICOLON); + lua_setfield(L, -2, "honey_key_semicolon"); + + lua_pushinteger(L, HONEY_KEY_EQUAL); + lua_setfield(L, -2, "honey_key_equal"); + + lua_pushinteger(L, HONEY_KEY_A); + lua_setfield(L, -2, "honey_key_a"); + + lua_pushinteger(L, HONEY_KEY_B); + lua_setfield(L, -2, "honey_key_b"); + + lua_pushinteger(L, HONEY_KEY_C); + lua_setfield(L, -2, "honey_key_c"); + + lua_pushinteger(L, HONEY_KEY_D); + lua_setfield(L, -2, "honey_key_d"); + + lua_pushinteger(L, HONEY_KEY_E); + lua_setfield(L, -2, "honey_key_e"); + + lua_pushinteger(L, HONEY_KEY_F); + lua_setfield(L, -2, "honey_key_f"); + + lua_pushinteger(L, HONEY_KEY_G); + lua_setfield(L, -2, "honey_key_g"); + + lua_pushinteger(L, HONEY_KEY_H); + lua_setfield(L, -2, "honey_key_h"); + + lua_pushinteger(L, HONEY_KEY_I); + lua_setfield(L, -2, "honey_key_i"); + + lua_pushinteger(L, HONEY_KEY_J); + lua_setfield(L, -2, "honey_key_j"); + + lua_pushinteger(L, HONEY_KEY_K); + lua_setfield(L, -2, "honey_key_k"); + + lua_pushinteger(L, HONEY_KEY_L); + lua_setfield(L, -2, "honey_key_l"); + + lua_pushinteger(L, HONEY_KEY_M); + lua_setfield(L, -2, "honey_key_m"); + + lua_pushinteger(L, HONEY_KEY_N); + lua_setfield(L, -2, "honey_key_n"); + + lua_pushinteger(L, HONEY_KEY_O); + lua_setfield(L, -2, "honey_key_o"); + + lua_pushinteger(L, HONEY_KEY_P); + lua_setfield(L, -2, "honey_key_p"); + + lua_pushinteger(L, HONEY_KEY_Q); + lua_setfield(L, -2, "honey_key_q"); + + lua_pushinteger(L, HONEY_KEY_R); + lua_setfield(L, -2, "honey_key_r"); + + lua_pushinteger(L, HONEY_KEY_S); + lua_setfield(L, -2, "honey_key_s"); + + lua_pushinteger(L, HONEY_KEY_T); + lua_setfield(L, -2, "honey_key_t"); + + lua_pushinteger(L, HONEY_KEY_U); + lua_setfield(L, -2, "honey_key_u"); + + lua_pushinteger(L, HONEY_KEY_V); + lua_setfield(L, -2, "honey_key_v"); + + lua_pushinteger(L, HONEY_KEY_W); + lua_setfield(L, -2, "honey_key_w"); + + lua_pushinteger(L, HONEY_KEY_X); + lua_setfield(L, -2, "honey_key_x"); + + lua_pushinteger(L, HONEY_KEY_Y); + lua_setfield(L, -2, "honey_key_y"); + + lua_pushinteger(L, HONEY_KEY_Z); + lua_setfield(L, -2, "honey_key_z"); + + lua_pushinteger(L, HONEY_KEY_LEFT_BRACKET); + lua_setfield(L, -2, "honey_key_left_bracket"); + + lua_pushinteger(L, HONEY_KEY_BACKSLASH); + lua_setfield(L, -2, "honey_key_backslash"); + + lua_pushinteger(L, HONEY_KEY_RIGHT_BRACKET); + lua_setfield(L, -2, "honey_key_right_bracket"); + + lua_pushinteger(L, HONEY_KEY_GRAVE_ACCENT); + lua_setfield(L, -2, "honey_key_grave_accent"); + + lua_pushinteger(L, HONEY_KEY_WORLD_1); + lua_setfield(L, -2, "honey_key_world_1"); + + lua_pushinteger(L, HONEY_KEY_WORLD_2); + lua_setfield(L, -2, "honey_key_world_2"); + + lua_pushinteger(L, HONEY_KEY_ESCAPE); + lua_setfield(L, -2, "honey_key_escape"); + + lua_pushinteger(L, HONEY_KEY_ENTER); + lua_setfield(L, -2, "honey_key_enter"); + + lua_pushinteger(L, HONEY_KEY_TAB); + lua_setfield(L, -2, "honey_key_tab"); + + lua_pushinteger(L, HONEY_KEY_BACKSPACE); + lua_setfield(L, -2, "honey_key_backspace"); + + lua_pushinteger(L, HONEY_KEY_INSERT); + lua_setfield(L, -2, "honey_key_insert"); + + lua_pushinteger(L, HONEY_KEY_DELETE); + lua_setfield(L, -2, "honey_key_delete"); + + lua_pushinteger(L, HONEY_KEY_RIGHT); + lua_setfield(L, -2, "honey_key_right"); + + lua_pushinteger(L, HONEY_KEY_LEFT); + lua_setfield(L, -2, "honey_key_left"); + + lua_pushinteger(L, HONEY_KEY_DOWN); + lua_setfield(L, -2, "honey_key_down"); + + lua_pushinteger(L, HONEY_KEY_UP); + lua_setfield(L, -2, "honey_key_up"); + + lua_pushinteger(L, HONEY_KEY_PAGE_UP); + lua_setfield(L, -2, "honey_key_page_up"); + + lua_pushinteger(L, HONEY_KEY_PAGE_DOWN); + lua_setfield(L, -2, "honey_key_page_down"); + + lua_pushinteger(L, HONEY_KEY_HOME); + lua_setfield(L, -2, "honey_key_home"); + + lua_pushinteger(L, HONEY_KEY_END); + lua_setfield(L, -2, "honey_key_end"); + + lua_pushinteger(L, HONEY_KEY_CAPS_LOCK); + lua_setfield(L, -2, "honey_key_caps_lock"); + + lua_pushinteger(L, HONEY_KEY_SCROLL_LOCK); + lua_setfield(L, -2, "honey_key_scroll_lock"); + + lua_pushinteger(L, HONEY_KEY_NUM_LOCK); + lua_setfield(L, -2, "honey_key_num_lock"); + + lua_pushinteger(L, HONEY_KEY_PRINT_SCREEN); + lua_setfield(L, -2, "honey_key_print_screen"); + + lua_pushinteger(L, HONEY_KEY_PAUSE); + lua_setfield(L, -2, "honey_key_pause"); + + lua_pushinteger(L, HONEY_KEY_F1); + lua_setfield(L, -2, "honey_key_f1"); + + lua_pushinteger(L, HONEY_KEY_F2); + lua_setfield(L, -2, "honey_key_f2"); + + lua_pushinteger(L, HONEY_KEY_F3); + lua_setfield(L, -2, "honey_key_f3"); + + lua_pushinteger(L, HONEY_KEY_F4); + lua_setfield(L, -2, "honey_key_f4"); + + lua_pushinteger(L, HONEY_KEY_F5); + lua_setfield(L, -2, "honey_key_f5"); + + lua_pushinteger(L, HONEY_KEY_F6); + lua_setfield(L, -2, "honey_key_f6"); + + lua_pushinteger(L, HONEY_KEY_F7); + lua_setfield(L, -2, "honey_key_f7"); + + lua_pushinteger(L, HONEY_KEY_F8); + lua_setfield(L, -2, "honey_key_f8"); + + lua_pushinteger(L, HONEY_KEY_F9); + lua_setfield(L, -2, "honey_key_f9"); + + lua_pushinteger(L, HONEY_KEY_F10); + lua_setfield(L, -2, "honey_key_f10"); + + lua_pushinteger(L, HONEY_KEY_F11); + lua_setfield(L, -2, "honey_key_f11"); + + lua_pushinteger(L, HONEY_KEY_F12); + lua_setfield(L, -2, "honey_key_f12"); + + lua_pushinteger(L, HONEY_KEY_F13); + lua_setfield(L, -2, "honey_key_f13"); + + lua_pushinteger(L, HONEY_KEY_F14); + lua_setfield(L, -2, "honey_key_f14"); + + lua_pushinteger(L, HONEY_KEY_F15); + lua_setfield(L, -2, "honey_key_f15"); + + lua_pushinteger(L, HONEY_KEY_F16); + lua_setfield(L, -2, "honey_key_f16"); + + lua_pushinteger(L, HONEY_KEY_F17); + lua_setfield(L, -2, "honey_key_f17"); + + lua_pushinteger(L, HONEY_KEY_F18); + lua_setfield(L, -2, "honey_key_f18"); + + lua_pushinteger(L, HONEY_KEY_F19); + lua_setfield(L, -2, "honey_key_f19"); + + lua_pushinteger(L, HONEY_KEY_F20); + lua_setfield(L, -2, "honey_key_f20"); + + lua_pushinteger(L, HONEY_KEY_F21); + lua_setfield(L, -2, "honey_key_f21"); + + lua_pushinteger(L, HONEY_KEY_F22); + lua_setfield(L, -2, "honey_key_f22"); + + lua_pushinteger(L, HONEY_KEY_F23); + lua_setfield(L, -2, "honey_key_f23"); + + lua_pushinteger(L, HONEY_KEY_F24); + lua_setfield(L, -2, "honey_key_f24"); + + lua_pushinteger(L, HONEY_KEY_F25); + lua_setfield(L, -2, "honey_key_f25"); + + lua_pushinteger(L, HONEY_KEY_KP_0); + lua_setfield(L, -2, "honey_key_kp_0"); + + lua_pushinteger(L, HONEY_KEY_KP_1); + lua_setfield(L, -2, "honey_key_kp_1"); + + lua_pushinteger(L, HONEY_KEY_KP_2); + lua_setfield(L, -2, "honey_key_kp_2"); + + lua_pushinteger(L, HONEY_KEY_KP_3); + lua_setfield(L, -2, "honey_key_kp_3"); + + lua_pushinteger(L, HONEY_KEY_KP_4); + lua_setfield(L, -2, "honey_key_kp_4"); + + lua_pushinteger(L, HONEY_KEY_KP_5); + lua_setfield(L, -2, "honey_key_kp_5"); + + lua_pushinteger(L, HONEY_KEY_KP_6); + lua_setfield(L, -2, "honey_key_kp_6"); + + lua_pushinteger(L, HONEY_KEY_KP_7); + lua_setfield(L, -2, "honey_key_kp_7"); + + lua_pushinteger(L, HONEY_KEY_KP_8); + lua_setfield(L, -2, "honey_key_kp_8"); + + lua_pushinteger(L, HONEY_KEY_KP_9); + lua_setfield(L, -2, "honey_key_kp_9"); + + lua_pushinteger(L, HONEY_KEY_KP_DECIMAL); + lua_setfield(L, -2, "honey_key_kp_decimal"); + + lua_pushinteger(L, HONEY_KEY_KP_DIVIDE); + lua_setfield(L, -2, "honey_key_kp_divide"); + + lua_pushinteger(L, HONEY_KEY_KP_MULTIPLY); + lua_setfield(L, -2, "honey_key_kp_multiply"); + + lua_pushinteger(L, HONEY_KEY_KP_SUBTRACT); + lua_setfield(L, -2, "honey_key_kp_subtract"); + + lua_pushinteger(L, HONEY_KEY_KP_ADD); + lua_setfield(L, -2, "honey_key_kp_add"); + + lua_pushinteger(L, HONEY_KEY_KP_ENTER); + lua_setfield(L, -2, "honey_key_kp_enter"); + + lua_pushinteger(L, HONEY_KEY_KP_EQUAL); + lua_setfield(L, -2, "honey_key_kp_equal"); + + lua_pushinteger(L, HONEY_KEY_LEFT_SHIFT); + lua_setfield(L, -2, "honey_key_left_shift"); + + lua_pushinteger(L, HONEY_KEY_LEFT_CONTROL); + lua_setfield(L, -2, "honey_key_left_control"); + + lua_pushinteger(L, HONEY_KEY_LEFT_ALT); + lua_setfield(L, -2, "honey_key_left_alt"); + + lua_pushinteger(L, HONEY_KEY_LEFT_SUPER); + lua_setfield(L, -2, "honey_key_left_super"); + + lua_pushinteger(L, HONEY_KEY_RIGHT_SHIFT); + lua_setfield(L, -2, "honey_key_right_shift"); + + lua_pushinteger(L, HONEY_KEY_RIGHT_CONTROL); + lua_setfield(L, -2, "honey_key_right_control"); + + lua_pushinteger(L, HONEY_KEY_RIGHT_ALT); + lua_setfield(L, -2, "honey_key_right_alt"); + + lua_pushinteger(L, HONEY_KEY_RIGHT_SUPER); + lua_setfield(L, -2, "honey_key_right_super"); + + lua_pushinteger(L, HONEY_KEY_MENU); + lua_setfield(L, -2, "honey_key_menu"); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +bool honey_key_down(int key) +{ + if (key < 0 || key >= HONEY_N_KEYS) { + return false; + } + return (bool) honey_key_states[key]; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_key_bind(int key, + void (*callback)(void*, int), + void* data) +{ + if (key >= 0 && key < HONEY_N_KEYS) { + honey_key_callbacks[key] = callback; + honey_key_callbacks_data[key] = data; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_key_unbind(int key) +{ + if (key >=0 && key < HONEY_N_KEYS) { + honey_key_callbacks[key] = NULL; + honey_key_callbacks_data[key] = NULL; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_key_unbind_all() +{ + for (int i=0; i<HONEY_N_KEYS; i++) { + honey_key_callbacks[i] = NULL; + honey_key_callbacks_data[i] = NULL; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void default_honey_keyboard_callback(honey_window window, int key, int scancode, int action, int mods) +{ + if (key >= 0 && key < HONEY_N_KEYS) { + if (action == HONEY_KEY_PRESS) { honey_key_states[key] = 1; } + if (action == HONEY_KEY_RELEASE) { honey_key_states[key] = 0; } + if (honey_key_callbacks[key] != NULL) { + honey_key_callbacks[key](honey_key_callbacks_data[key], action); + } + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/src/input/input.h b/src/input/input.h new file mode 100644 index 0000000..a8ae206 --- /dev/null +++ b/src/input/input.h @@ -0,0 +1,194 @@ +#ifndef HONEY_INPUT_H +#define HONEY_INPUT_H + +/** @file input.h + * + * @brief Wrap GLFW input functions for honey. + */ + +#include "../common.h" + +#define HONEY_KEY_UNKNOWN 0 +#define HONEY_KEY_SPACE 1 +#define HONEY_KEY_APOSTROPHE 2 +#define HONEY_KEY_COMMA 3 +#define HONEY_KEY_MINUS 4 +#define HONEY_KEY_PERIOD 5 +#define HONEY_KEY_SLASH 6 +#define HONEY_KEY_0 7 +#define HONEY_KEY_1 8 +#define HONEY_KEY_2 9 +#define HONEY_KEY_3 10 +#define HONEY_KEY_4 11 +#define HONEY_KEY_5 12 +#define HONEY_KEY_6 13 +#define HONEY_KEY_7 14 +#define HONEY_KEY_8 15 +#define HONEY_KEY_9 16 +#define HONEY_KEY_SEMICOLON 17 +#define HONEY_KEY_EQUAL 18 +#define HONEY_KEY_A 19 +#define HONEY_KEY_B 20 +#define HONEY_KEY_C 21 +#define HONEY_KEY_D 22 +#define HONEY_KEY_E 23 +#define HONEY_KEY_F 24 +#define HONEY_KEY_G 25 +#define HONEY_KEY_H 26 +#define HONEY_KEY_I 27 +#define HONEY_KEY_J 28 +#define HONEY_KEY_K 29 +#define HONEY_KEY_L 30 +#define HONEY_KEY_M 31 +#define HONEY_KEY_N 32 +#define HONEY_KEY_O 33 +#define HONEY_KEY_P 34 +#define HONEY_KEY_Q 35 +#define HONEY_KEY_R 36 +#define HONEY_KEY_S 37 +#define HONEY_KEY_T 38 +#define HONEY_KEY_U 39 +#define HONEY_KEY_V 40 +#define HONEY_KEY_W 41 +#define HONEY_KEY_X 42 +#define HONEY_KEY_Y 43 +#define HONEY_KEY_Z 44 +#define HONEY_KEY_LEFT_BRACKET 45 +#define HONEY_KEY_BACKSLASH 46 +#define HONEY_KEY_RIGHT_BRACKET 47 +#define HONEY_KEY_GRAVE_ACCENT 48 +#define HONEY_KEY_WORLD_1 49 +#define HONEY_KEY_WORLD_2 50 +#define HONEY_KEY_ESCAPE 51 +#define HONEY_KEY_ENTER 52 +#define HONEY_KEY_TAB 53 +#define HONEY_KEY_BACKSPACE 54 +#define HONEY_KEY_INSERT 55 +#define HONEY_KEY_DELETE 56 +#define HONEY_KEY_RIGHT 57 +#define HONEY_KEY_LEFT 58 +#define HONEY_KEY_DOWN 59 +#define HONEY_KEY_UP 60 +#define HONEY_KEY_PAGE_UP 61 +#define HONEY_KEY_PAGE_DOWN 62 +#define HONEY_KEY_HOME 63 +#define HONEY_KEY_END 64 +#define HONEY_KEY_CAPS_LOCK 65 +#define HONEY_KEY_SCROLL_LOCK 66 +#define HONEY_KEY_NUM_LOCK 67 +#define HONEY_KEY_PRINT_SCREEN 68 +#define HONEY_KEY_PAUSE 69 +#define HONEY_KEY_F1 70 +#define HONEY_KEY_F2 71 +#define HONEY_KEY_F3 72 +#define HONEY_KEY_F4 73 +#define HONEY_KEY_F5 74 +#define HONEY_KEY_F6 75 +#define HONEY_KEY_F7 76 +#define HONEY_KEY_F8 77 +#define HONEY_KEY_F9 78 +#define HONEY_KEY_F10 79 +#define HONEY_KEY_F11 80 +#define HONEY_KEY_F12 81 +#define HONEY_KEY_F13 82 +#define HONEY_KEY_F14 83 +#define HONEY_KEY_F15 84 +#define HONEY_KEY_F16 85 +#define HONEY_KEY_F17 86 +#define HONEY_KEY_F18 87 +#define HONEY_KEY_F19 88 +#define HONEY_KEY_F20 89 +#define HONEY_KEY_F21 90 +#define HONEY_KEY_F22 91 +#define HONEY_KEY_F23 92 +#define HONEY_KEY_F24 93 +#define HONEY_KEY_F25 94 +#define HONEY_KEY_KP_0 95 +#define HONEY_KEY_KP_1 96 +#define HONEY_KEY_KP_2 97 +#define HONEY_KEY_KP_3 98 +#define HONEY_KEY_KP_4 99 +#define HONEY_KEY_KP_5 100 +#define HONEY_KEY_KP_6 101 +#define HONEY_KEY_KP_7 102 +#define HONEY_KEY_KP_8 103 +#define HONEY_KEY_KP_9 104 +#define HONEY_KEY_KP_DECIMAL 105 +#define HONEY_KEY_KP_DIVIDE 106 +#define HONEY_KEY_KP_MULTIPLY 107 +#define HONEY_KEY_KP_SUBTRACT 108 +#define HONEY_KEY_KP_ADD 109 +#define HONEY_KEY_KP_ENTER 110 +#define HONEY_KEY_KP_EQUAL 111 +#define HONEY_KEY_LEFT_SHIFT 112 +#define HONEY_KEY_LEFT_CONTROL 113 +#define HONEY_KEY_LEFT_ALT 114 +#define HONEY_KEY_LEFT_SUPER 115 +#define HONEY_KEY_RIGHT_SHIFT 116 +#define HONEY_KEY_RIGHT_CONTROL 117 +#define HONEY_KEY_RIGHT_ALT 118 +#define HONEY_KEY_RIGHT_SUPER 119 +#define HONEY_KEY_MENU 120 + +#define HONEY_N_KEYS 121 + +#define HONEY_KEY_PRESS GLFW_PRESS +#define HONEY_KEY_RELEASE GLFW_RELEASE + +unsigned int honey_key_states[HONEY_N_KEYS]; +static void (*honey_key_callbacks[HONEY_N_KEYS])(void*, int); +static void* honey_key_callbacks_data[HONEY_N_KEYS]; +static void (*honey_keyboard_callback)(honey_window window, int key, int scancode, int action, int mods); + +/** @brief Initializes Honey's internal keyboard states. + * + * This function is called by honey_setup, so you shouldn't need + * to manually call it in most cases. + */ +void honey_setup_keyboard(); + +/* @brief Place a lua table containing the enum values for GLFW keys on the stack. + * + * @param L The lua state to place the table on the top of the stack. + * + * @returns Nothing. + */ +void honey_setup_input(lua_State* L); + +/** @brief Check if a key is down. + * + * @param[in] key The key to query. + * + * @return TRUE if the key is presently held down; FALSE if it is not, or if the keycode was out of bounds. + */ +bool honey_key_down(int key); + +/** @brief Bind a callback to a key. + * + * The callback must have signature (void*, int), where the first argument is supplied by the + * void* supplied with this function, and the int is one of HONEY_KEY_PRESS or HONEY_KEY_RELEASE, + * depending on the action that triggered the callback. + * + * @param[in] key The key to bind the callback to. + * @param[in] callback The callback function to bind. + * @param[in] data Data to pass to the callback function upon triggering. + */ +void honey_key_bind(int key, void (*callback)(void*, int), void* data); + +/** @brief Unbind a key callback. + * + * THIS FUNCTION DOES NOT FREE MEMORY! If you allocated any, be sure to free it yourself! + * + * @param[in] key The key to unbind a callback from. + */ +void honey_key_unbind(int key); + +/** @brief Unbind all key callbacks. + * + * THIS FUNCTION DOES NOT FREE MEMORY! If you allocated any, be sure to free it yourself! + */ +void honey_key_unbind_all(); + +void default_honey_keyboard_callback(honey_window window, int key, int scancode, int action, int mods); + +#endif diff --git a/src/light/light.c b/src/light/light.c new file mode 100644 index 0000000..839d747 --- /dev/null +++ b/src/light/light.c @@ -0,0 +1,20 @@ +#include "light.h" + +void honey_point_light_new(honey_point_light* light, + float x, float y, float z, + float r, float g, float b, + float constant, + float linear, + float quadratic) { + light->position[0] = x; + light->position[1] = y; + light->position[2] = z; + + light->color[0] = r; + light->color[1] = g; + light->color[2] = b; + + light->constant = constant; + light->linear = linear; + light->quadratic = quadratic; +} diff --git a/src/light/light.h b/src/light/light.h new file mode 100644 index 0000000..dfb6979 --- /dev/null +++ b/src/light/light.h @@ -0,0 +1,33 @@ +#ifndef HONEY_LIGHT_H +#define HONEY_LIGHT_H + +#include "../common.h" + +#define HONEY_MAX_LIGHT_NAME_LENGTH 64 + +typedef struct { + vec3 position; + vec3 color; + + float constant; + float linear; + float quadratic; +} honey_point_light; + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +typedef struct { + vec3 direction; + vec3 color; +} honey_directional_light; + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_point_light_new(honey_point_light* light, + float x, float y, float z, + float r, float g, float b, + float constant, + float linear, + float quadratic); + +#endif @@ -1,21 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> - -#include <unistd.h> - -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> - -#include "glad.h" -#include <GLFW/glfw3.h> - -#include <cglm/cglm.h> -#include <cglm/call.h> - -#include "input.h" +#include "honey.h" struct options { bool verbose; diff --git a/src/mesh/mesh.c b/src/mesh/mesh.c new file mode 100644 index 0000000..231fcc9 --- /dev/null +++ b/src/mesh/mesh.c @@ -0,0 +1,86 @@ +#include "mesh.h" + +honey_result honey_mesh_new(honey_mesh* mesh, + float* vertices, + unsigned int n_vertices, + unsigned int n_attributes, + unsigned int* attribute_sizes, + unsigned int* indices, + unsigned int n_indices) { + if (vertices == NULL || n_vertices == 0) { + return HONEY_MESH_BAD_VERTEX_DATA; + } + if (indices == NULL || n_indices == 0) { + return HONEY_MESH_BAD_INDEX_DATA; + } + + unsigned int vertex_size = 0; + for (int i=0; i<n_attributes; i++) { + vertex_size += attribute_sizes[i]; + } + + (*mesh).vertices = malloc(vertex_size*n_vertices * sizeof(float)); + if ((*mesh).vertices == NULL) { + return HONEY_MEMORY_ALLOCATION_ERROR; + } + memcpy((*mesh).vertices, vertices, vertex_size*n_vertices*sizeof(float)); + + (*mesh).indices = malloc(n_indices * sizeof(unsigned int)); + if ((*mesh).indices == NULL) { + return HONEY_MEMORY_ALLOCATION_ERROR; + } + memcpy((*mesh).indices, indices, n_indices * sizeof(unsigned int)); + + (*mesh).n_vertices = n_vertices; + (*mesh).n_indices = n_indices; + + glGenVertexArrays(1, &((*mesh).vertex_array)); + glGenBuffers(1, &((*mesh).vertex_buffer)); + glGenBuffers(1, &((*mesh).element_buffer)); + + glBindVertexArray((*mesh).vertex_array); + + glBindBuffer(GL_ARRAY_BUFFER, (*mesh).vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, vertex_size*n_vertices*sizeof(float), (*mesh).vertices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (*mesh).element_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, n_indices * sizeof(unsigned int), (*mesh).indices, GL_STATIC_DRAW); + + /* set up vertex attributes */ + unsigned int offset = 0; + for (int i=0; i<n_attributes; i++) { + glEnableVertexAttribArray(i); + glVertexAttribPointer(i, + attribute_sizes[i], + GL_FLOAT, + GL_FALSE, + vertex_size*sizeof(float), + (void*) (offset*sizeof(float))); + offset += attribute_sizes[i]; + } + + glBindVertexArray(0); + + return HONEY_OK; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_mesh_draw(honey_mesh mesh, honey_shader shader) { + honey_shader_use(shader); + + glBindVertexArray(mesh.vertex_array); + glDrawElements(GL_TRIANGLES, mesh.n_indices, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_mesh_delete(honey_mesh mesh) { + free(mesh.vertices); + free(mesh.indices); + + glDeleteVertexArrays(1, &(mesh.vertex_array)); + glDeleteBuffers(1, &(mesh.vertex_buffer)); + glDeleteBuffers(1, &(mesh.element_buffer)); +} diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h new file mode 100644 index 0000000..a3e1e2a --- /dev/null +++ b/src/mesh/mesh.h @@ -0,0 +1,57 @@ +#ifndef HONEY_MESH_H +#define HONEY_MESH_H + +/** @file mesh.h + * + * @brief Defines the honey_mesh struct and related basic mesh functions. +*/ + + + +#include "../common.h" +#include "../shader/shader.h" + +typedef struct { + float* vertices; + unsigned int n_vertices; + unsigned int* indices; + unsigned int n_indices; + unsigned int vertex_array, vertex_buffer, element_buffer; +} honey_mesh; + +/** @brief Create a new mesh from vertex and index arrays. + * + * Note that this function creates copies of the vertex and index arrays, + * so you can deallocate those immediately. + * + * @param[out] mesh Pointer to the destination honey_mesh struct + * @param[in] vertices Array of floats representing the vertices + * @param[in] n_attributes The number of attributes per vertex + * @param[in] attribute_sizes An array containing for each attribute how many floats it contains + * @param[in] n_vertices The number of vertices (NOT the number of floats in the vertex array) + * @param[in] indices Array of vertex indices + * @param[in] n_indices The number of elements in the index array + */ +honey_result honey_mesh_new(honey_mesh* mesh, + float* vertices, + unsigned int n_vertices, + unsigned int n_attributes, + unsigned int* attribute_sizes, + unsigned int* indices, + unsigned int n_indices); + +/** @brief Draw a mesh on screen. + * + * @param[in] mesh The mesh to draw + * @param[in] shader The shader to use when drawing the mesh + */ +void honey_mesh_draw(honey_mesh mesh, + honey_shader shader); + +/** @brief Delete a mesh. + * + * @param[in] mesh The mesh to delete + */ +void honey_mesh_delete(honey_mesh mesh); + +#endif diff --git a/src/model/model.c b/src/model/model.c new file mode 100644 index 0000000..b317f15 --- /dev/null +++ b/src/model/model.c @@ -0,0 +1,121 @@ +#include "model.h" + +static honey_mesh assimp_to_honey_mesh(struct aiMesh* mesh, struct aiScene* scene) { + unsigned int vertex_step = 6; + bool mesh_has_uvs = false; + unsigned int n_vertices = mesh->mNumVertices; + + if (mesh->mTextureCoords[0]) { + mesh_has_uvs = true; + vertex_step = 8; + } + + float* vertices = malloc(sizeof(float) * vertex_step * n_vertices); + for (int i=0; i<n_vertices; i++) { + int j = i*vertex_step; + /* positions */ + vertices[j+0] = mesh->mVertices[i].x; + vertices[j+1] = mesh->mVertices[i].y; + vertices[j+2] = mesh->mVertices[i].z; + + /* normals */ + vertices[j+3] = mesh->mNormals[i].x; + vertices[j+4] = mesh->mNormals[i].y; + vertices[j+5] = mesh->mNormals[i].z; + + /* uvs? */ + if (mesh_has_uvs) { + vertices[j+6] = mesh->mTextureCoords[0][i].x; + vertices[j+7] = mesh->mTextureCoords[0][i].y; + } + } + + unsigned int n_indices = mesh->mNumFaces*3; + unsigned int* indices = malloc(sizeof(unsigned int) * n_indices); + for (int i=0; i<mesh->mNumFaces; i++) { + int j = 3*i; + struct aiFace face = mesh->mFaces[i]; + indices[j+0] = face.mIndices[0]; + indices[j+1] = face.mIndices[1]; + indices[j+2] = face.mIndices[2]; + } + + honey_mesh result; + + if (mesh_has_uvs) { + unsigned int n_attributes = 3; + unsigned int attribute_sizes[] = { 3, 3, 2 }; + honey_mesh_new(&result, + vertices, n_vertices, + n_attributes, attribute_sizes, + indices, n_indices); + } + else { + unsigned int n_attributes = 2; + unsigned int attribute_sizes[] = { 3, 3 }; + honey_mesh_new(&result, + vertices, n_vertices, + n_attributes, attribute_sizes, + indices, n_indices); + } + + free(vertices); + free(indices); + + return result; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +static void process_assimp_node(honey_model* model, struct aiNode* node, struct aiScene* scene) { + for (int i=0; i<node->mNumMeshes; i++) { + struct aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + model->meshes[model->n_meshes] = assimp_to_honey_mesh(mesh, scene); + model->n_meshes++; + } + + for (int i=0; i<node->mNumChildren; i++) { + process_assimp_node(model, node->mChildren[i], scene); + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +honey_result honey_model_load(honey_model* model, + char* path) { + model->n_meshes = 0; + + struct aiScene* scene = aiImportFile(path, + aiProcess_Triangulate | + aiProcess_FlipUVs); + if (scene == NULL) { + honey_error_set_string1(path); + return HONEY_FILE_READ_ERROR; + } + + if (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || + scene->mRootNode == NULL) { + honey_error_set_string1(path); + return HONEY_MODEL_LOAD_ERROR; + } + + process_assimp_node(model, scene->mRootNode, scene); + + return HONEY_OK; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_model_draw(honey_model* model, honey_shader shader) { + for (int i=0; i<model->n_meshes; i++) { + honey_mesh_draw(model->meshes[i], shader); + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_model_delete(honey_model* model) { + for (int i=0; i<model->n_meshes; i++) { + honey_mesh_delete(model->meshes[i]); + } +} diff --git a/src/model/model.h b/src/model/model.h new file mode 100644 index 0000000..3672a44 --- /dev/null +++ b/src/model/model.h @@ -0,0 +1,29 @@ +#ifndef HONEY_MODEL_H +#define HONEY_MODEL_H + +#include "../common.h" +#include "../mesh/mesh.h" +#include "../shader/shader.h" + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#define HONEY_MODEL_MAX_MESHES 32 + +typedef struct { + mat4 model_matrix; + honey_mesh meshes[HONEY_MODEL_MAX_MESHES]; + unsigned int n_meshes; +} honey_model; + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/** @brief Load a model. + * + * @param[out] model Pointer to the destination honey_model struct. + * @param[in] path Path of the model to be loaded. + */ +honey_result honey_model_load(honey_model* model, char* path); +void honey_model_draw(honey_model* model, honey_shader shader); +void honey_model_delete(honey_model* model); + +#endif diff --git a/src/primitives/primitives.c b/src/primitives/primitives.c new file mode 100644 index 0000000..efc4a0f --- /dev/null +++ b/src/primitives/primitives.c @@ -0,0 +1,180 @@ +#include "primitives.h" + +honey_result honey_mesh_new_textured_plane(honey_mesh* mesh, + float width, + float height) { + float x0 = 0; + float y0 = 0; + float x1 = width; + float y1 = height; + + float vertices[] = { + /* position normal uv */ + x0, y0, 0, 0, 0, 1, 0, 0, + x1, y0, 0, 0, 0, 1, 1, 0, + x0, y1, 0, 0, 0, 1, 0, 1, + x1, y1, 0, 0, 0, 1, 1, 1 }; + + unsigned int indices[] = { + 0, 1, 2, + 1, 2, 3 }; + + unsigned int attrib_sizes[] = { 3, 3, 2 }; + + honey_result result = honey_mesh_new(mesh, + vertices, 4, + 3, attrib_sizes, + indices, 6); + return result; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +honey_result honey_mesh_new_cube(honey_mesh* mesh, + float width, + float height, + float depth) { + float x0 = 0; + float y0 = 0; + float z0 = 0; + + float x1 = width; + float y1 = height; + float z1 = depth; + + float vertices[] = { + /* position normal tex coord */ + /* back face */ + x0, y0, z0, 0, 0, -1, + x1, y0, z0, 0, 0, -1, + x0, y1, z0, 0, 0, -1, + x1, y1, z0, 0, 0, -1, + + /* front face */ + x0, y0, z1, 0, 0, 1, + x1, y0, z1, 0, 0, 1, + x0, y1, z1, 0, 0, 1, + x1, y1, z1, 0, 0, 1, + + /* left face */ + x0, y0, z0, -1, 0, 0, + x0, y1, z0, -1, 0, 0, + x0, y0, z1, -1, 0, 0, + x0, y1, z1, -1, 0, 0, + + /* right face */ + x1, y0, z0, 1, 0, 0, + x1, y1, z0, 1, 0, 0, + x1, y0, z1, 1, 0, 0, + x1, y1, z1, 1, 0, 0, + + /* bottom face */ + x0, y0, z0, 0, -1, 0, + x1, y0, z0, 0, -1, 0, + x0, y0, z1, 0, -1, 0, + x1, y0, z1, 0, -1, 0, + + /* top face */ + x0, y1, z0, 0, 1, 0, + x1, y1, z0, 0, 1, 0, + x0, y1, z1, 0, 1, 0, + x1, y1, z1, 0, 1, 0 }; + + unsigned int indices[] = { + 0, 1, 2, + 1, 2, 3, + 4, 5, 6, + 5, 6, 7, + 8, 9, 10, + 9, 10, 11, + 12, 13, 14, + 13, 14, 15, + 16, 17, 18, + 17, 18, 19, + 20, 21, 22, + 21, 22, 23 }; + + unsigned int attrib_sizes[] = { 3, 3 }; + + honey_result result = honey_mesh_new(mesh, + vertices, 24, + 2, attrib_sizes, + indices, 36); + + return result; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +honey_result honey_mesh_new_textured_cube(honey_mesh* mesh, + float width, + float height, + float depth) { + float x0 = 0; + float y0 = 0; + float z0 = 0; + + float x1 = width; + float y1 = height; + float z1 = depth; + + float vertices[] = { + /* position normal tex coord */ + /* back face */ + x0, y0, z0, 0, 0, -1, 0, 0, + x1, y0, z0, 0, 0, -1, 1, 0, + x0, y1, z0, 0, 0, -1, 0, 1, + x1, y1, z0, 0, 0, -1, 1, 1, + + /* front face */ + x0, y0, z1, 0, 0, 1, 0, 0, + x1, y0, z1, 0, 0, 1, 1, 0, + x0, y1, z1, 0, 0, 1, 0, 1, + x1, y1, z1, 0, 0, 1, 1, 1, + + /* left face */ + x0, y0, z0, -1, 0, 0, 0, 0, + x0, y1, z0, -1, 0, 0, 1, 0, + x0, y0, z1, -1, 0, 0, 0, 1, + x0, y1, z1, -1, 0, 0, 1, 1, + + /* right face */ + x1, y0, z0, 1, 0, 0, 0, 0, + x1, y1, z0, 1, 0, 0, 1, 0, + x1, y0, z1, 1, 0, 0, 0, 1, + x1, y1, z1, 1, 0, 0, 1, 1, + + /* bottom face */ + x0, y0, z0, 0, -1, 0, 0, 0, + x1, y0, z0, 0, -1, 0, 1, 0, + x0, y0, z1, 0, -1, 0, 0, 1, + x1, y0, z1, 0, -1, 0, 1, 1, + + /* top face */ + x0, y1, z0, 0, 1, 0, 0, 0, + x1, y1, z0, 0, 1, 0, 1, 0, + x0, y1, z1, 0, 1, 0, 0, 1, + x1, y1, z1, 0, 1, 0, 1, 1 }; + + unsigned int indices[] = { + 0, 1, 2, + 1, 2, 3, + 4, 5, 6, + 5, 6, 7, + 8, 9, 10, + 9, 10, 11, + 12, 13, 14, + 13, 14, 15, + 16, 17, 18, + 17, 18, 19, + 20, 21, 22, + 21, 22, 23 }; + + unsigned int attrib_sizes[] = { 3, 3, 2 }; + + honey_result result; + result = honey_mesh_new(mesh, vertices, 24, + 3, attrib_sizes, + indices, 36); + return result; +} diff --git a/src/primitives/primitives.h b/src/primitives/primitives.h new file mode 100644 index 0000000..fbf7753 --- /dev/null +++ b/src/primitives/primitives.h @@ -0,0 +1,59 @@ +#ifndef HONEY_PRIMITIVES_H +#define HONEY_PRIMITIVES H + +/** @file primitives.h + * + * @brief Define various common primitive objects. + */ + +#include "../common.h" +#include "../mesh/mesh.h" + +/** @brief Create a textured plane. + * + * This function creates a plane with vertex positions in attribute 0, + * vertex normals in attribute 1, and UV coordinates in attribute 2. + * + * @param[out] mesh Pointer to the destination mesh + * @param[in] width Desired width of the plane (x-axis) + * @param[in] height Desired height of the plane (y-axis) + * + * @return 0 (HONEY_OK) on success, and an error code otherwise. + */ +honey_result honey_mesh_new_textured_plane(honey_mesh* mesh, + float width, + float height); + +/** @brief Create a cube. + * + * This function creates a cube with vertex positions in attribute 0. + * + * @param[out] mesh Pointer to the destination mesh + * @param[in] width Desired width of the cube (x-axis) + * @param[in] height Desired height of the cube (y-axis) + * @param[in] depth Desired depth of the cube (z-axis) + * + * @return Success or failure code + */ +honey_result honey_mesh_new_cube(honey_mesh* mesh, + float width, + float height, + float depth); +/** @brief Create a textured cube. + * + * This function creates a cube with vertex positions in attribute 0, + * and texture coordinates in attribute 1. + * + * @param[out] mesh Pointer to the destination mesh + * @param[in] width Desired width of the cube (x-axis) + * @param[in] height Desired height of the cube (y-axis) + * @param[in] depth Desired depth of the cube (z-axis) + * + * @return Success or failure code + */ +honey_result honey_mesh_new_textured_cube(honey_mesh* mesh, + float width, + float height, + float depth); + +#endif diff --git a/src/shader/shader.c b/src/shader/shader.c new file mode 100644 index 0000000..817d451 --- /dev/null +++ b/src/shader/shader.c @@ -0,0 +1,224 @@ +#include "shader.h" + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +static honey_result read_file(char** destination, char* file_path) { + FILE* f = fopen(file_path, "r"); + if (f == NULL) { + honey_error_set_string1(file_path); + return HONEY_FILE_READ_ERROR; + } + + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + *destination = malloc(fsize + 1); + if (*destination == NULL) { + return HONEY_MEMORY_ALLOCATION_ERROR; + } + fread(*destination, 1, fsize, f); + fclose(f); + + (*destination)[fsize] = 0; + + return HONEY_OK; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +honey_result honey_shader_load(honey_shader* shader, + char* vertex_shader_path, + char* fragment_shader_path) { + /* load vertex shader code */ + char* vertex_shader_code; + honey_result result = read_file(&vertex_shader_code, + vertex_shader_path); + if (result != HONEY_OK) + return result; + + /* load fragment shader code */ + char* fragment_shader_code; + result = read_file(&fragment_shader_code, + fragment_shader_path); + if (result != HONEY_OK) + return result; + + result = honey_shader_new(shader, + vertex_shader_code, + fragment_shader_code); + + if (result == HONEY_VERTEX_SHADER_COMPILATION_ERROR) + honey_error_set_string2(vertex_shader_path); + + if (result == HONEY_FRAGMENT_SHADER_COMPILATION_ERROR) + honey_error_set_string2(fragment_shader_path); + + free(vertex_shader_code); + free(fragment_shader_code); + + return result; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +honey_result honey_shader_new(honey_shader* shader, + char* vertex_shader_code, + char* fragment_shader_code) { + /* compile shaders */ + int success; + char error[512]; + + int vertex_shader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex_shader, 1, ((const char**)&vertex_shader_code), NULL); + glCompileShader(vertex_shader); + glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); + if (!success) { + honey_error_clear_strings(); + char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; + glGetShaderInfoLog(vertex_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); + honey_error_set_string1(compiler_error); + return HONEY_VERTEX_SHADER_COMPILATION_ERROR; + } + + int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment_shader, 1, ((const char**)&fragment_shader_code), NULL); + glCompileShader(fragment_shader); + glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success); + if (!success) { + honey_error_clear_strings(); + char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; + glGetShaderInfoLog(fragment_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); + honey_error_set_string1(compiler_error); + return HONEY_FRAGMENT_SHADER_COMPILATION_ERROR; + } + + /* link shaders */ + *shader = glCreateProgram(); + glAttachShader(*shader, vertex_shader); + glAttachShader(*shader, fragment_shader); + glLinkProgram(*shader); + glGetShaderiv(*shader, GL_LINK_STATUS, &success); + if (!success) { + honey_error_clear_strings(); + char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; + glGetShaderInfoLog(vertex_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); + honey_error_set_string1(compiler_error); + return HONEY_SHADER_LINK_ERROR; + } + + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + + return HONEY_OK; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_int(honey_shader shader, + char* int_name, + int value) { + honey_shader_use(shader); + unsigned int int_location = glGetUniformLocation(shader, int_name); + glUniform1i(int_location, value); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_float(honey_shader shader, + char* float_name, + float value) { + honey_shader_use(shader); + unsigned int float_location = glGetUniformLocation(shader, float_name); + glUniform1f(float_location, value); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_vec3(honey_shader shader, + char* vector_name, + vec3 value) { + honey_shader_use(shader); + unsigned int vector_location = glGetUniformLocation(shader, vector_name); + glUniform3fv(vector_location, 1, (float*) value); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_mat3(honey_shader shader, + char* matrix_name, + mat3 value) { + glUseProgram(shader); + unsigned int matrix_location = glGetUniformLocation(shader, matrix_name); + glUniformMatrix3fv(matrix_location, 1, GL_FALSE, (float*) value); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_mat4(honey_shader shader, + char* matrix_name, + mat4 value) { + glUseProgram(shader); + unsigned int matrix_location = glGetUniformLocation(shader, matrix_name); + glUniformMatrix4fv(matrix_location, 1, GL_FALSE, (float*) value); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_point_light(honey_shader shader, + int point_light_index, + honey_point_light light) { + char name[HONEY_MAX_LIGHT_NAME_LENGTH]; + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].position", + point_light_index); + honey_shader_set_vec3(shader, name, light.position); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].color", + point_light_index); + honey_shader_set_vec3(shader, name, light.color); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].constant", + point_light_index); + honey_shader_set_float(shader, name, light.constant); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].linear", + point_light_index); + honey_shader_set_float(shader, name, light.linear); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].quadratic", + point_light_index); + honey_shader_set_float(shader, name, light.quadratic); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_directional_light(honey_shader shader, + int directional_light_index, + honey_directional_light light) { + char name[HONEY_MAX_LIGHT_NAME_LENGTH]; + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "directional_lights[%d].direction", + directional_light_index); + honey_shader_set_vec3(shader, name, light.direction); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "directional_lights[%d].color", + directional_light_index); + honey_shader_set_vec3(shader, name, light.color); +} + + diff --git a/src/shader/shader.h b/src/shader/shader.h new file mode 100644 index 0000000..07cc22d --- /dev/null +++ b/src/shader/shader.h @@ -0,0 +1,117 @@ +/** @file shader.h + * + * @brief Functions to create, manipulate, and destroy GLSL shaders. + */ + +#ifndef HONEY_SHADER_H +#define HONEY_SHADER_H + +#include "../common.h" +#include "../light/light.h" + +typedef int honey_shader; + +/** @brief Load a shader. + * + * @param[out] shader Pointer to the shader destination + * + * @param[in] vertex_shader_path The path to the vertex shader source code + * @param[in] fragment_shader_path The path to the fragment shader source code + * + * @return The result of the shader load. + */ +honey_result honey_shader_load(honey_shader* shader, + char* vertex_shader_path, + char* fragment_shader_path); + +/** @brief Create a shader from code strings. + * + * @param[out] shader Pointer to the shader destination. + * @param[in] vertex_shader_code Zero-terminated string containing the vertex shader code to compile + * @param[in] fragment_shader_code Zero-terminated string containing the fragment shader code to compile + * + * @return The result of the shader creation. + */ +honey_result honey_shader_new(honey_shader* shader, + char* vertex_shader_code, + char* fragment_shader_code); + +/** @brief Set an integer uniform. + * + * @param[in] shader The shader to which the uniform belongs + * @param[in] int_name The name of the integer uniform + * @param[in] value The value of the integer uniform + */ +void honey_shader_set_int(honey_shader shader, + char* int_name, + int value); + +/** @brief Set a float uniform. + * + * @param[in] shader The shader to which the uniform belongs + * @param[in] float_name The name of the float uniform + * @param[in] value The value of the float uniform + */ +void honey_shader_set_float(honey_shader shader, + char* float_name, + float value); + +/** @brief Set a vec3 uniform. + * @param[in] shader The shader to which the uniform belongs + * @param[in] vector_name The name of the vec3 uniform + * @param[in] value The value of the vector uniform + */ +void honey_shader_set_vec3(honey_shader shader, + char* vector_name, + vec3 value); + + +/** @brief Set a mat3 uniform. + * + * @param[in] shader The shader to which the uniform belongs + * @param[in] matrix_name The name of the matrix uniform + * @param[in] value The value of the matrix uniform + */ +void honey_shader_set_mat3(honey_shader shader, + char* matrix_name, + mat3 value); + +/** @brief Set a mat4 uniform. + * + * @param[in] shader The shader to which the uniform belongs + * @param[in] matrix_name The name of the matrix uniform + * @param[in] value The value of the matrix uniform + */ +void honey_shader_set_mat4(honey_shader shader, + char* matrix_name, + mat4 value); + +/** @brief Set a point_light uniform. + * + * @param[in] shader The shader to which the uniform belongs + * @param[in] point_light_index The index of the light to set + * @param[in] light The honey_point_light to set + */ +void honey_shader_set_point_light(honey_shader shader, + int point_light_index, + honey_point_light light); + +/** @brief Set a directional_light uniform. + * + * @param[in] shader The shader to which the uniform belongs + * @param[in] directional_light_index The index of the light to set + * @param[in] light The honey_directional_light to set + */ +void honey_shader_set_directional_light(honey_shader shader, + int directional_light_index, + honey_directional_light light); + +/** @brief Use a shader. + */ +#define honey_shader_use glUseProgram + +/** @brief delete a shader. + */ +#define honey_shader_delete glDeleteProgram + +#endif diff --git a/src/stb_image.c b/src/stb_image/stb_image.c index 6e5aa1c..6e5aa1c 100644 --- a/src/stb_image.c +++ b/src/stb_image/stb_image.c diff --git a/src/stb_image.h b/src/stb_image/stb_image.h index 2857f05..2857f05 100644 --- a/src/stb_image.h +++ b/src/stb_image/stb_image.h diff --git a/src/texture/texture.c b/src/texture/texture.c new file mode 100644 index 0000000..591ee11 --- /dev/null +++ b/src/texture/texture.c @@ -0,0 +1,45 @@ +#include "texture.h" + +enum honey_texture_result honey_texture_new(honey_texture* texture, + char* texture_path, + bool alpha_channel) { + unsigned int texture_id; + glGenTextures(1, &texture_id); + glBindTexture(GL_TEXTURE_2D, texture_id); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + int width, height, channels; + unsigned char* image_data = stbi_load(texture_path, &width, &height, &channels, 0); + if (image_data == NULL) { + fprintf(stderr, "ERROR: failed to load '%s'\n", texture_path); + return TEXTURE_FAILED; + } + + if (alpha_channel) { + 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); + } + + glGenerateMipmap(GL_TEXTURE_2D); + stbi_image_free(image_data); + + (*texture).texture_id = texture_id; + (*texture).width = width; + (*texture).height = height; + (*texture).channels = channels; + + return TEXTURE_OK; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_texture_use(honey_texture texture, int texture_unit) { + glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(GL_TEXTURE_2D, texture.texture_id); +} diff --git a/src/texture/texture.h b/src/texture/texture.h new file mode 100644 index 0000000..037d3d0 --- /dev/null +++ b/src/texture/texture.h @@ -0,0 +1,42 @@ +#ifndef HONEY_TEXTURE_H +#define HONEY_TEXTURE_H + +/** @file texture.h + * + *@brief Defines the honey_texture struct and associated functions. +*/ + +#include "../common.h" + +enum honey_texture_result { + TEXTURE_OK, + TEXTURE_FAILED, + N_TEXTURE_RESULTS }; + +typedef struct { + unsigned int texture_id; + int width; + int height; + int channels; +} honey_texture; + +/** @brief Load a texture from disk. + * + * @param[out] texture Pointer to the destination texture + * @param[in] texture_path Path to the location of the texture + * @param[in] alpha_channel Set to true if the target image contains an alpha channel + * + * @return Success or failure type + */ +enum honey_texture_result honey_texture_new(honey_texture* texture, + char* texture_path, + bool alpha_channel); + +/** @brief Load a texture into a texture unit. + * + * @param[in] texture The texture to use + * @param[in] texture_unit The texture unit to put the texture in + */ +void honey_texture_use(honey_texture texture, int texture_unit); + +#endif |