From 8c4b7bff183747418293a623601aeb04532c42f4 Mon Sep 17 00:00:00 2001 From: Phireh Date: Sun, 30 Apr 2023 17:18:15 +0200 Subject: [PATCH] Add ortographic camera --- Makefile | 4 +- hex_debug.h | 12 +++++ hex_math.h | 87 +++++++++++++++++++++++++++++++++++- main.c | 105 +++++++++++++++++++++++++++++++++++++++----- shaders/vertex.glsl | 8 +++- 5 files changed, 202 insertions(+), 14 deletions(-) create mode 100644 hex_debug.h diff --git a/Makefile b/Makefile index 4831437..dd539ea 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS=-Wall -Wextra -g -pedantic -fenable-matrix -Wno-gnu-zero-variadic-macro-arguments -Wno-incompatible-pointer-types-discards-qualifiers +CFLAGS=-Wall -Wextra -g3 -pedantic -fenable-matrix -Wno-gnu-zero-variadic-macro-arguments -Wno-incompatible-pointer-types-discards-qualifiers -fsanitize=undefined -fsanitize-trap -Wconversion -Wno-implicit-int-float-conversion -Wno-implicit-float-conversion -Wno-gnu-empty-initializer LIBS=`pkg-config --libs glfw3 glew opengl` -lm -hexnando: main.c Makefile +hexnando: main.c Makefile hex_math.h hex_debug.h clang ${CFLAGS} ${LIBS} main.c -o hexnando diff --git a/hex_debug.h b/hex_debug.h new file mode 100644 index 0000000..c613e96 --- /dev/null +++ b/hex_debug.h @@ -0,0 +1,12 @@ +#ifndef HEX_DEBUG_H +#include +#define DEBUG_VERBOSITY 1 + +#define log_err(str, ...) do { fprintf(stderr, "[ERROR] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0) + +#if (DEBUG_VERBOSITY > 0) +#define log_debug(str, ...) do { fprintf(stderr, "[DEBUG] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0) +#else +#define log_debug(str, ...) +#endif +#endif diff --git a/hex_math.h b/hex_math.h index 6515c53..ece882d 100644 --- a/hex_math.h +++ b/hex_math.h @@ -1,10 +1,26 @@ #define _USE_MATH_DEFINES // for finding things like M_PI in Windows build #include #include +#include "hex_debug.h" /* Types */ typedef float _v2f __attribute__((matrix_type(1,2))); typedef float _v3f __attribute__((matrix_type(1,3))); typedef float _v4f __attribute__((matrix_type(1,4))); +typedef float _mat4 __attribute__((matrix_type(4,4))); + +typedef struct { + union { + struct { + float first; + float second; + }; + _v2f v2f; + struct { + float x; + float y; + }; + }; +} vec2f; typedef struct { union { @@ -36,6 +52,37 @@ typedef struct { }; } vec4f; +/* Row-major matrix, make sure to pass it to OpenGL trasposed */ +typedef struct { + union { + _mat4 m4f; + struct { + float a0; + float a1; + float a2; + float a3; + float b0; + float b1; + float b2; + float b3; + float c0; + float c1; + float c2; + float c3; + float d0; + float d1; + float d2; + float d3; + }; + struct { + vec4f row0; + vec4f row1; + vec4f row2; + vec4f row3; + }; + }; +} mat4f; + typedef struct { vec4f position; // center pos float radius; // side length @@ -44,7 +91,6 @@ typedef struct { uint32_t vbo; float vertices[7*3]; // 7 vert per hex unsigned int indices[6*3]; // 6 triangles to render a hex - } hex_t; typedef struct { @@ -53,7 +99,17 @@ typedef struct { uint32_t columns; } hexgrid_t; +typedef struct { + float left; + float right; + float top; + float bottom; + float near; + float far; +} camera_t; + _Static_assert(sizeof(vec4f) == sizeof(float) * 4, "Bad vector size"); +_Static_assert(sizeof(mat4f) == sizeof(float) * 16, "Bad matrix size"); /* Functions */ double sint(double turns) @@ -65,3 +121,32 @@ double cost(double turns) { return cos(turns*2*M_PI); } + +mat4f ortho_matrix(float left, float right, float top, float bottom, float near, float far, float width, float height) +{ + // Invert Y coord + float aux; + aux = bottom; + bottom = top; + top = aux; + + // Scale and move to [-1,1] + left = (left*2 - width)/width; + right = (right*2 - width)/width; + + top = (top*2 - height)/height; + bottom = (bottom*2 - height)/height; + + + + mat4f matrix = {}; + matrix.a0 = 2/(right - left); + matrix.a3 = -((right + left)/(right - left)); + matrix.b1 = 2/(top - bottom); + matrix.b3 = -((top + bottom)/(top - bottom)); + matrix.c2 = -2/(far - near); + matrix.c3 = -((far + near)/(far - near)); + matrix.d3 = 1; + + return matrix; +} diff --git a/main.c b/main.c index e1fd8fc..54f0913 100644 --- a/main.c +++ b/main.c @@ -8,9 +8,8 @@ #include #include "hex_math.h" +#include "hex_debug.h" -#define log_err(str, ...) do { fprintf(stderr, "[ERROR] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0) -#define log_debug(str, ...) do { fprintf(stderr, "[DEBUG] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0) char *read_entire_file(char *path) { @@ -20,7 +19,7 @@ char *read_entire_file(char *path) if (f) { fseek(f, 0, SEEK_END); - length = ftell(f); + length = (size_t)ftell(f); fseek(f, 0, SEEK_SET); if (length) { @@ -37,12 +36,31 @@ static void glfw_error_callback(int errcode, const char *description) fprintf(stderr, "[GLFW ERROR][ERRCODE %d] %s\n", errcode, description); } -void set_uniform(GLuint program_id, const char *name, vec4f value) +void set_uniform4f(GLuint program_id, const char *name, vec4f value) { GLint location = glGetUniformLocation(program_id, name); glUniform4f(location, value.x, value.y, value.z, value.w); } +void set_uniform2f(GLuint program_id, const char *name, vec2f value) +{ + GLint location = glGetUniformLocation(program_id, name); + glUniform2f(location, value.x, value.y); +} + +void set_uniform4x4f(GLuint program_id, const char *name, mat4f value) +{ + GLint location = glGetUniformLocation(program_id, name); + glUniformMatrix4fv(location, 1, GL_TRUE, &value.a0); +} + +#define set_uniform(id, name, value) _Generic((value), \ + vec4f: set_uniform4f, \ + vec2f: set_uniform2f, \ + mat4f: set_uniform4x4f)(id, name, value) + + + int main(void) { GLFWwindow *window; @@ -112,12 +130,12 @@ int main(void) background_color.a = 1.0f; hexgrid_t grid; - grid.rows = 10; - grid.columns = 10; + grid.rows = 30; + grid.columns = 30; grid.hexes = calloc(1, sizeof(hex_t) * grid.rows * grid.columns); // Scale of hexagon relative to screen. A 1:1 hexagon would reach the entire horizontal space - float scale = 1.0f / 5.0f; + float scale = 1.0f / 1.0f; for (size_t i = 0; i < grid.columns; ++i) { @@ -126,13 +144,14 @@ int main(void) // Offset the X and Y coordinates of adjacent hexagons so they do not cut each other float offset = 0.0f; if (j % 2) - offset = sint(1.0f/6); + offset = (float)sint(1.0f/6); grid.hexes[i*grid.rows+j].position.x = (0.0f + j*(1 + cost(1.0f/6))); grid.hexes[i*grid.rows+j].position.y = (0.0f + i*(sint(1.0f/6))*2.0f) + offset; grid.hexes[i*grid.rows+j].position.z = 0.0f; + grid.hexes[i*grid.rows+j].position.w = 1.0f; - fprintf(stdout, "Position of hex %ld %ld is %f %f\n", i, j, grid.hexes[i*grid.rows+j].position.x, grid.hexes[i*grid.rows+j].position.y); + log_debug("Position of hex %ld %ld is %f %f\n", i, j, grid.hexes[i*grid.rows+j].position.x, grid.hexes[i*grid.rows+j].position.y); } } @@ -184,8 +203,63 @@ int main(void) //glBindBuffer(GL_ARRAY_BUFFER, 0); //glBindVertexArray(0); + camera_t camera = {}; + camera.near = -0.1f; + camera.far = 1.0f; + camera.left = 0.0f; + camera.right = 600.0f; + camera.top = 0.0f; + camera.bottom = 600.0f; + while (!glfwWindowShouldClose(window)) { + // Camera logic + if (glfwGetKey(window, GLFW_KEY_A)) + { + camera.right -= (camera.right - camera.left) * 0.01f; + camera.left -= (camera.right - camera.left) * 0.01f; + } + if (glfwGetKey(window, GLFW_KEY_D)) + { + camera.right += (camera.right - camera.left) * 0.01f; + camera.left += (camera.right - camera.left) * 0.01f; + } + if (glfwGetKey(window, GLFW_KEY_W)) + { + camera.top += (camera.bottom - camera.top) * 0.01f; + camera.bottom += (camera.bottom - camera.top) * 0.01f; + } + if (glfwGetKey(window, GLFW_KEY_S)) + { + camera.top -= (camera.bottom - camera.top) * 0.01f; + camera.bottom -= (camera.bottom - camera.top) * 0.01f; + } + if (glfwGetKey(window, GLFW_KEY_Q)) + { + float offset = (camera.right - camera.left)*0.02f; + camera.right -= offset; + camera.left += offset; + camera.top += offset; + camera.bottom -= offset; + } + if (glfwGetKey(window, GLFW_KEY_E)) + { + float offset = (camera.right - camera.left)*0.05f; + camera.right += offset; + camera.left -= offset; + camera.top -= offset; + camera.bottom += offset; + } + if (glfwGetKey(window, GLFW_KEY_R)) + { + camera.near = -0.1f; + camera.far = 1.0f; + camera.left = 0.0f; + camera.right = 400.0f; + camera.top = 0.0f; + camera.bottom = 400.0f; + } + int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); @@ -194,10 +268,19 @@ int main(void) glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shader_program); - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + mat4f camera_matrix = ortho_matrix(camera.left, camera.right, camera.top, camera.bottom, camera.near, camera.far, width, height); + set_uniform(shader_program, "camera", camera_matrix); + + vec2f window_size = { .x = (float)width, .y = (float)height }; + set_uniform(shader_program, "window_size", window_size); + + // For debugging + float aux; + glGetUniformfv(shader_program, glGetUniformLocation(shader_program, "window_size"), &aux); + for (size_t i = 0; i < grid.rows * grid.columns; ++i) { @@ -207,6 +290,7 @@ int main(void) hex_color.g = (float)i / (grid.rows * grid.columns); hex_color.b = (float)i / (grid.rows * grid.columns); hex_color.a = 1.0f; + set_uniform(shader_program, "uniform_color", hex_color); glBindVertexArray(grid.hexes[i].vao); @@ -215,6 +299,7 @@ int main(void) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid.hexes[i].ebo); glDrawElements(GL_TRIANGLES, 3*6, GL_UNSIGNED_INT, 0); } + glfwPollEvents(); glfwSwapBuffers(window); } diff --git a/shaders/vertex.glsl b/shaders/vertex.glsl index f8f0a7a..16a7f73 100644 --- a/shaders/vertex.glsl +++ b/shaders/vertex.glsl @@ -1,14 +1,20 @@ #version 330 core layout (location = 0) in vec3 pos; uniform vec4 uniform_color; +uniform mat4 camera; +uniform vec2 window_size; out vec4 vertex_color; const mat4 to_draw_coordinates_matrix = mat4( 1., 0., 0., 0., 0., -1., 0., 0., 0., 0., 1., 0., -1, 1, 0, 1); + void main() { - gl_Position = to_draw_coordinates_matrix*vec4(pos, 1.0f); + float aspect_ratio = window_size.x / window_size.y; + mat4 scaling_matrix = mat4(1.0); + scaling_matrix[1][1] = aspect_ratio; + gl_Position = camera*scaling_matrix*to_draw_coordinates_matrix*vec4(pos, 1.0f); vertex_color = uniform_color; }