diff options
Diffstat (limited to 'src')
| -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 | 
29 files changed, 2244 insertions, 396 deletions
| 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 | 
