From: Brendan Hansen Date: Mon, 19 Oct 2020 13:50:29 +0000 (-0500) Subject: using c++ now for SOME of its features X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=cd0b56692e2c6042ad56f7c21607e88c7bbace57;p=csc718.git using c++ now for SOME of its features --- diff --git a/Makefile b/Makefile index 717f3ed..4cc4e74 100644 --- a/Makefile +++ b/Makefile @@ -7,26 +7,30 @@ OBJ_FILES=\ build/physics.o \ build/sim.o -ifeq (, $(shell which tcc)) - CC=gcc -else -ifeq ($(RELEASE), 0) - CC=gcc -else - CC=tcc -endif -endif - +# ifeq (, $(shell which tcc)) +# CC=gcc +# else +# ifeq ($(RELEASE), 0) +# CC=gcc +# else +# CC=tcc +# endif +# endif + +CC=g++ INCLUDES=-I./include LIBS=-lGL -lglfw -lm TARGET=./sim ifeq ($(RELEASE), 1) - FLAGS=-O3 + FLAGS=-O2 else FLAGS=-g3 endif +build/%.o: src/%.cpp + $(CC) $(TIMEFLAG) $(FLAGS) -c $< -o $@ $(INCLUDES) + build/%.o: src/%.c $(CC) $(TIMEFLAG) $(FLAGS) -c $< -o $@ $(INCLUDES) diff --git a/include/log.h b/include/log.h index 9f29b7b..f23d3e8 100644 --- a/include/log.h +++ b/include/log.h @@ -1,14 +1,17 @@ #ifndef LOG_H #define LOG_H -typedef enum LogLevel { +enum LogLevel +{ LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR, LOG_LEVEL_COUNT, -} LogLevel; +}; +// NOTE(Brendan): The minimum log level that will be printed out. +// Useful for hiding a bunch of INFO logs. extern LogLevel LOG_LEVEL_MINIMUM; void logprint(LogLevel level, const char* format, ...); diff --git a/include/physics.h b/include/physics.h index f79b9ba..2210594 100644 --- a/include/physics.h +++ b/include/physics.h @@ -3,11 +3,12 @@ #include -typedef struct Body { +struct Body +{ V2f pos; V2f vel; f32 mass; -} Body; +}; #endif //PHYSICS_H diff --git a/include/utils.h b/include/utils.h index a0263a2..4c1584e 100644 --- a/include/utils.h +++ b/include/utils.h @@ -14,6 +14,29 @@ // NOTE(Brendan): This is useful in many situations and I believe it cleans up the code by making simple, counter based for loops easier to recognize at a glance. #define foreach(var, lo, hi) for (i32 var = lo; var < hi; var++) -void _Noreturn panic_and_die(const char* msg, ...); +[[noreturn]] void panic_and_die(const char* msg, ...); + +#ifndef defer +struct defer_dummy {}; + +template +struct deferrer +{ + F f; + ~deferrer() { f(); } +}; + +template +deferrer +operator*(defer_dummy, F f) +{ + return { f }; +} + +#define DEFER_(LINE) zz_defer##LINE +#define DEFER(LINE_) DEFER_(LINE) +#define defer auto DEFER(__LINE__) = defer_dummy{} * [&]() + +#endif // defer #endif //UTILS_H \ No newline at end of file diff --git a/include/vecmath.h b/include/vecmath.h index 0916674..e3be4c3 100644 --- a/include/vecmath.h +++ b/include/vecmath.h @@ -3,7 +3,10 @@ #include "types.h" -typedef struct V2f { f32 x, y; } V2f; +struct V2f +{ + f32 x, y; +}; V2f v2f_add (V2f a, V2f b); V2f v2f_sub (V2f a, V2f b); @@ -14,6 +17,8 @@ f32 v2f_mag (V2f a); V2f v2f_norm(V2f a); V2f v2f_proj(V2f a, V2f onto); + + typedef float mat4[16]; void mat4_identity(mat4 *mat); diff --git a/project.4coder b/project.4coder index fa79a8e..30def96 100644 --- a/project.4coder +++ b/project.4coder @@ -4,6 +4,7 @@ project_name = "CSC718_Project"; patterns = { "*.c", +"*.cpp", "*.h", "*.sh", "*.glsl", diff --git a/src/log.c b/src/log.c deleted file mode 100644 index 01256d3..0000000 --- a/src/log.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -#include "log.h" -#include "utils.h" - -LogLevel LOG_LEVEL_MINIMUM = LOG_LEVEL_INFO; - -internal const char* log_level_strs[LOG_LEVEL_COUNT] = { - "INFO", - "WARN", - "ERROR", -}; - -void -logprint(LogLevel level, const char *format, ...) -{ - va_list va; - va_start(va, format); - logvprint(level, format, va); - va_end(va); -} - -// NOTE(Brendan): This always prints a newline. -void -logvprint(LogLevel level, const char* format, va_list va) -{ - if (level < LOG_LEVEL_MINIMUM) return; - - printf("[%s] ", log_level_strs[level]); - vprintf(format, va); - printf("\n"); -} \ No newline at end of file diff --git a/src/log.cpp b/src/log.cpp new file mode 100644 index 0000000..6fd9486 --- /dev/null +++ b/src/log.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include "log.h" +#include "utils.h" + +LogLevel LOG_LEVEL_MINIMUM = LOG_LEVEL_INFO; + +internal const char* log_level_strs[LOG_LEVEL_COUNT] = { + "INFO", + "WARN", + "ERROR", +}; + +void +logprint(LogLevel level, const char *format, ...) +{ + va_list va; + va_start(va, format); + logvprint(level, format, va); + va_end(va); +} + +// NOTE(Brendan): This always prints a newline. +void +logvprint(LogLevel level, const char* format, va_list va) +{ + if (level < LOG_LEVEL_MINIMUM) return; + + printf("[%s] ", log_level_strs[level]); + vprintf(format, va); + printf("\n"); +} diff --git a/src/physics.c b/src/physics.c deleted file mode 100644 index 5f4f488..0000000 --- a/src/physics.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "physics.h" - diff --git a/src/physics.cpp b/src/physics.cpp new file mode 100644 index 0000000..5f4f488 --- /dev/null +++ b/src/physics.cpp @@ -0,0 +1,2 @@ +#include "physics.h" + diff --git a/src/sim.c b/src/sim.c deleted file mode 100644 index 36e8f50..0000000 --- a/src/sim.c +++ /dev/null @@ -1,252 +0,0 @@ -#define DEBUG - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "types.h" -#include "utils.h" -#include "physics.h" - -#include "log.h" - -#define PI 3.141592653589793238462643383 - -#define WINDOW_WIDTH 1600 -#define WINDOW_HEIGHT 900 -#define WINDOW_TITLE "N-Body Simulation" - -internal void -glfw_key_handler(GLFWwindow* window, i32 key, i32 scancode, i32 action, i32 mods) -{ - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, 1); -} - -internal void -glfw_resize_handler(GLFWwindow* window, i32 width, i32 height) -{ - glViewport(0, 0, width, height); -} - -internal void -glfw_error_handler(i32 error, const char* desc) -{ - panic_and_die("GLFW Error (%d): %s\n", error, desc); -} - -GLFWwindow* window; -internal void -init_glfw() -{ - logprint(LOG_LEVEL_INFO, "Initializing GLFW"); - - if (!glfwInit()) panic_and_die("Failed to initalize GLFW."); - glfwSetErrorCallback(glfw_error_handler); - - window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); - glfwMakeContextCurrent(window); - - glfwSwapInterval(1); - glfwSetKeyCallback(window, glfw_key_handler); - glfwSetFramebufferSizeCallback(window, glfw_resize_handler); - - // NOTE(Brendan): This may need to be changed if the screen orientation changes. - //glEnable(GL_CULL_FACE); - //glFrontFace(GL_CW); - //glCullFace(GL_BACK); -} - -internal void -deinit_glfw() -{ - glfwDestroyWindow(window); - glfwTerminate(); -} - -internal GLuint -load_shader(GLenum shader_type, const char* shader_loc) -{ - logprint(LOG_LEVEL_INFO, "Loading shader: %s", shader_loc); - - GLuint shader = glCreateShader(shader_type); - - FILE* shader_file = fopen(shader_loc, "rb"); - if (shader_file == NULL) panic_and_die("Shader file not found: %s\n", shader_loc); - - fseek(shader_file, 0, SEEK_END); - i32 shader_file_size = ftell(shader_file); - fseek(shader_file, 0, SEEK_SET); - - char* shader_buffer = malloc(shader_file_size + 1); - fread(shader_buffer, 1, shader_file_size, shader_file); - fclose(shader_file); - - shader_buffer[shader_file_size] = 0; - - glShaderSource(shader, 1, (const char* const*) &shader_buffer, NULL); - glCompileShader(shader); - - GLint successful; - glGetShaderiv(shader, GL_COMPILE_STATUS, &successful); - if (successful != GL_TRUE) { - GLsizei log_length = 0; - GLchar shader_log[1024]; - glGetShaderInfoLog(shader, 1023, &log_length, shader_log); - shader_log[log_length] = 0; - - panic_and_die("Error compiling shader %s:\n%s\n", - shader_loc, - shader_log); - } - - free(shader_buffer); - - return shader; -} - -internal GLuint -create_program(GLuint vertex_shader, GLuint fragment_shader) -{ - logprint(LOG_LEVEL_INFO, "Linking GL program"); - - GLuint program = glCreateProgram(); - glAttachShader(program, vertex_shader); - glAttachShader(program, fragment_shader); - glLinkProgram(program); - - GLint successful; - glGetProgramiv(program, GL_LINK_STATUS, &successful); - if (successful != GL_TRUE) { - GLsizei log_length = 0; - GLchar program_log[1024]; - glGetProgramInfoLog(program, 1023, &log_length, program_log); - program_log[log_length] = 0; - - panic_and_die("Error linking program:\n%s", program_log); - } - - return program; -} - - - - - - - -#define CIRCLE_POINT_COUNT 36 // NOTE(Brendan): Treat a circle as a many-sided polygon. - -// NOTE(Brendan): Returns the VAO where the mesh data was bound. -internal GLsizei -create_circle_mesh() -{ - logprint(LOG_LEVEL_INFO, "Generating circle mesh"); - - GLsizei vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - V2f circle_points[CIRCLE_POINT_COUNT] = {}; - foreach (i, 0, CIRCLE_POINT_COUNT) { - f32 t = (f32) i / (f32) CIRCLE_POINT_COUNT; - circle_points[i].x = cos(t * 2 * PI) * 40.0f + 400.0f; - circle_points[i].y = sin(t * 2 * PI) * 40.0f + 200.0f; - } - - GLsizei vertex_buffer; - glGenBuffers(1, &vertex_buffer); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(circle_points), &circle_points, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(V2f), (void *) offset_of(V2f, x)); - glBindBuffer(GL_ARRAY_BUFFER, -1); - - u8 circle_indicies[CIRCLE_POINT_COUNT] = {}; - foreach(i, 0, CIRCLE_POINT_COUNT) circle_indicies[i] = i; - - GLsizei index_buffer; - glGenBuffers(1, &index_buffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(circle_indicies), &circle_indicies, GL_STATIC_DRAW); - - glBindVertexArray(-1); - - return vao; -} - - - -// NOTE(Brendan): dt is expected to be in units of "per second". -internal void -update(f64 dt) -{ -} - -internal GLsizei circle_mesh; -internal void -draw() -{ - glClearColor(0.1, 0.1, 0.1, 1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArray(circle_mesh); - glDrawElements(GL_TRIANGLE_FAN, CIRCLE_POINT_COUNT, GL_UNSIGNED_BYTE, 0); - glBindVertexArray(-1); - - glfwSwapBuffers(window); -} - -internal void -loop() -{ - f64 last_time = glfwGetTime(); - f64 curr_time = last_time; - f64 delta; - - while (!glfwWindowShouldClose(window)) { - glfwPollEvents(); - - curr_time = glfwGetTime(); - delta = curr_time - last_time; - last_time = curr_time; - - if (delta > 0.0) { - update(delta); - draw(); - } - } -} - -i32 -main(i32 argc, char* argv[]) -{ - init_glfw(); - circle_mesh = create_circle_mesh(NULL); - - GLuint v_shader = load_shader(GL_VERTEX_SHADER, "res/shaders/planet_vert.glsl"); - GLuint f_shader = load_shader(GL_FRAGMENT_SHADER, "res/shaders/planet_frag.glsl"); - GLuint program = create_program(v_shader, f_shader); - glUseProgram(program); - - mat4 ortho_mat; - mat4_ortho(&ortho_mat, 0, 800, 0, 800, 0.0f, 100.0f); - - GLuint ortho_mat_loc = glGetUniformLocation(program, "u_proj"); - glUniformMatrix4fv(ortho_mat_loc, 1, false, (f32 *) ortho_mat); - - loop(); - - deinit_glfw(); - - return 0; -} \ No newline at end of file diff --git a/src/sim.cpp b/src/sim.cpp new file mode 100644 index 0000000..769b65d --- /dev/null +++ b/src/sim.cpp @@ -0,0 +1,252 @@ +#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "types.h" +#include "utils.h" +#include "physics.h" + +#include "log.h" + +#define PI 3.141592653589793238462643383 + +#define WINDOW_WIDTH 1600 +#define WINDOW_HEIGHT 900 +#define WINDOW_TITLE "N-Body Simulation" + +internal void +glfw_key_handler(GLFWwindow* window, i32 key, i32 scancode, i32 action, i32 mods) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + glfwSetWindowShouldClose(window, 1); +} + +internal void +glfw_resize_handler(GLFWwindow* window, i32 width, i32 height) +{ + glViewport(0, 0, width, height); +} + +internal void +glfw_error_handler(i32 error, const char* desc) +{ + panic_and_die("GLFW Error (%d): %s\n", error, desc); +} + +GLFWwindow* window; +internal void +init_glfw() +{ + logprint(LOG_LEVEL_INFO, "Initializing GLFW"); + + if (!glfwInit()) panic_and_die("Failed to initalize GLFW."); + glfwSetErrorCallback(glfw_error_handler); + + window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); + glfwMakeContextCurrent(window); + + glfwSwapInterval(1); + glfwSetKeyCallback(window, glfw_key_handler); + glfwSetFramebufferSizeCallback(window, glfw_resize_handler); + + // NOTE(Brendan): This may need to be changed if the screen orientation changes. + glEnable(GL_CULL_FACE); + glFrontFace(GL_CW); + glCullFace(GL_BACK); +} + +internal void +deinit_glfw() +{ + glfwDestroyWindow(window); + glfwTerminate(); +} + +internal GLuint +load_shader(GLenum shader_type, const char* shader_loc) +{ + logprint(LOG_LEVEL_INFO, "Loading shader: %s", shader_loc); + + GLuint shader = glCreateShader(shader_type); + + FILE* shader_file = fopen(shader_loc, "rb"); + if (shader_file == NULL) panic_and_die("Shader file not found: %s\n", shader_loc); + + fseek(shader_file, 0, SEEK_END); + i32 shader_file_size = ftell(shader_file); + fseek(shader_file, 0, SEEK_SET); + + char* shader_buffer = (char *) malloc(shader_file_size + 1); + fread(shader_buffer, 1, shader_file_size, shader_file); + fclose(shader_file); + + shader_buffer[shader_file_size] = 0; + + glShaderSource(shader, 1, (const char* const*) &shader_buffer, NULL); + glCompileShader(shader); + + GLint successful; + glGetShaderiv(shader, GL_COMPILE_STATUS, &successful); + if (successful != GL_TRUE) { + GLsizei log_length = 0; + GLchar shader_log[1024]; + glGetShaderInfoLog(shader, 1023, &log_length, shader_log); + shader_log[log_length] = 0; + + panic_and_die("Error compiling shader %s:\n%s\n", + shader_loc, + shader_log); + } + + free(shader_buffer); + + return shader; +} + +internal GLuint +create_program(GLuint vertex_shader, GLuint fragment_shader) +{ + logprint(LOG_LEVEL_INFO, "Linking GL program"); + + GLuint program = glCreateProgram(); + glAttachShader(program, vertex_shader); + glAttachShader(program, fragment_shader); + glLinkProgram(program); + + GLint successful; + glGetProgramiv(program, GL_LINK_STATUS, &successful); + if (successful != GL_TRUE) { + GLsizei log_length = 0; + GLchar program_log[1024]; + glGetProgramInfoLog(program, 1023, &log_length, program_log); + program_log[log_length] = 0; + + panic_and_die("Error linking program:\n%s", program_log); + } + + return program; +} + + + + + + + +#define CIRCLE_POINT_COUNT 36 // NOTE(Brendan): Treat a circle as a many-sided polygon. + +// NOTE(Brendan): Returns the VAO where the mesh data was bound. +internal GLuint +create_circle_mesh() +{ + logprint(LOG_LEVEL_INFO, "Generating circle mesh"); + + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + V2f circle_points[CIRCLE_POINT_COUNT] = {}; + foreach (i, 0, CIRCLE_POINT_COUNT) { + f32 t = (f32) i / (f32) CIRCLE_POINT_COUNT; + circle_points[i].x = cos(t * 2 * PI) * 40.0f + 400.0f; + circle_points[i].y = sin(t * 2 * PI) * 40.0f + 200.0f; + } + + GLuint vertex_buffer; + glGenBuffers(1, &vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(circle_points), &circle_points, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(V2f), (void *) offset_of(V2f, x)); + glBindBuffer(GL_ARRAY_BUFFER, -1); + + u8 circle_indicies[CIRCLE_POINT_COUNT] = {}; + foreach(i, 0, CIRCLE_POINT_COUNT) circle_indicies[i] = i; + + GLuint index_buffer; + glGenBuffers(1, &index_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(circle_indicies), &circle_indicies, GL_STATIC_DRAW); + + glBindVertexArray(-1); + + return vao; +} + + + +// NOTE(Brendan): dt is expected to be in units of "per second". +internal void +update(f64 dt) +{ +} + +internal GLsizei circle_mesh; +internal void +draw() +{ + glClearColor(0.1, 0.1, 0.1, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArray(circle_mesh); + glDrawElements(GL_TRIANGLE_FAN, CIRCLE_POINT_COUNT, GL_UNSIGNED_BYTE, 0); + glBindVertexArray(-1); + + glfwSwapBuffers(window); +} + +internal void +loop() +{ + f64 last_time = glfwGetTime(); + f64 curr_time = last_time; + f64 delta; + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + curr_time = glfwGetTime(); + delta = curr_time - last_time; + last_time = curr_time; + + if (delta > 0.0) { + update(delta); + draw(); + } + } +} + +i32 +main(i32 argc, char* argv[]) +{ + init_glfw(); + defer { deinit_glfw(); }; + + circle_mesh = create_circle_mesh(); + + GLuint v_shader = load_shader(GL_VERTEX_SHADER, "res/shaders/planet_vert.glsl"); + GLuint f_shader = load_shader(GL_FRAGMENT_SHADER, "res/shaders/planet_frag.glsl"); + GLuint program = create_program(v_shader, f_shader); + glUseProgram(program); + + mat4 ortho_mat; + mat4_ortho(&ortho_mat, 0, 800, 0, 800, 0.0f, 100.0f); + + GLuint ortho_mat_loc = glGetUniformLocation(program, "u_proj"); + glUniformMatrix4fv(ortho_mat_loc, 1, false, (f32 *) ortho_mat); + + loop(); + + return 0; +} diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index 13d5ca2..0000000 --- a/src/utils.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include - -#include "log.h" - -void -panic_and_die(const char* msg, ...) -{ - puts("************ PANIC ************"); - - va_list va; - va_start(va, msg); - logvprint(LOG_LEVEL_ERROR, msg, va); - va_end(va); - -#ifdef DEBUG - // NOTE: This allows for a debugger to stop here. - __asm("int $3"); -#endif - - exit(1); -} \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..141f25b --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +#include "log.h" + +void +panic_and_die(const char* msg, ...) +{ + puts("************ PANIC ************"); + + va_list va; + va_start(va, msg); + logvprint(LOG_LEVEL_ERROR, msg, va); + va_end(va); + +#ifdef DEBUG + // NOTE: This allows for a debugger to stop here. + __asm("int $3"); +#endif + + exit(1); +} diff --git a/src/vecmath.c b/src/vecmath.c deleted file mode 100644 index 6f61dde..0000000 --- a/src/vecmath.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "vecmath.h" -#include - -#include "utils.h" - -V2f -v2f_add(V2f a, V2f b) -{ - return (V2f) { .x = a.x + b.x, .y = a.y + b.y }; -} - -V2f -v2f_sub(V2f a, V2f b) -{ - return (V2f) { .x = a.x - b.x, .y = a.y - b.y }; -} - -V2f -v2f_mul(V2f a, f32 scalar) -{ - return (V2f) { .x = a.x * scalar, .y = a.y * scalar }; -} - -f32 -v2f_dot(V2f a, V2f b) -{ - return a.x * b.x + a.y * b.y; -} - -f32 -v2f_smag(V2f a) -{ - return v2f_dot(a, a); -} - -f32 -v2f_mag(V2f a) -{ - return sqrt(v2f_smag(a)); -} - -V2f -v2f_norm(V2f a) -{ - const f32 mag = v2f_mag(a); - return v2f_mul(a, 1.0f / mag); -} - -V2f -v2f_proj(V2f a, V2f onto) -{ - const f32 dp = v2f_dot(a, onto) / v2f_mag(onto); - return v2f_mul(onto, dp); -} - - - -void -mat4_identity(mat4 *mat) -{ - foreach(i, 0, 16) (*mat)[i] = 0.0f; - (*mat)[0 * 4 + 0] = 1.0f; - (*mat)[1 * 4 + 1] = 1.0f; - (*mat)[2 * 4 + 2] = 1.0f; - (*mat)[3 * 4 + 3] = 1.0f; -} - -void -mat4_ortho(mat4 *mat, - f32 left, f32 right, - f32 top, f32 bottom, - f32 near, f32 far) -{ - foreach(i, 0, 16) (*mat)[i] = 0.0; - - (*mat)[0 * 4 + 0] = 2.0f / (right - left); - (*mat)[1 * 4 + 1] = 2.0f / (top - bottom); - (*mat)[2 * 4 + 2] = -2.0f / (far - near); - (*mat)[3 * 4 + 3] = 1.0f; - - (*mat)[3 * 4 + 0] = -(right + left) / (right - left); - (*mat)[3 * 4 + 1] = -(top + bottom) / (top - bottom); - (*mat)[3 * 4 + 2] = -(far + near) / (far - near); -} - - -void -mat4_mul(mat4 a, mat4 b, mat4* out) -{ - foreach(row, 0, 4) { - foreach(col, 0, 4) { - (*out)[row * 4 + col] = 0.0f; - - foreach(i, 0, 4) { - (*out)[row * 4 + col] += a[row * 4 + i] + b[i * 4 + col]; - } - } - } -} \ No newline at end of file diff --git a/src/vecmath.cpp b/src/vecmath.cpp new file mode 100644 index 0000000..985da6a --- /dev/null +++ b/src/vecmath.cpp @@ -0,0 +1,99 @@ +#include "vecmath.h" +#include + +#include "utils.h" + +V2f +v2f_add(V2f a, V2f b) +{ + return (V2f) { .x = a.x + b.x, .y = a.y + b.y }; +} + +V2f +v2f_sub(V2f a, V2f b) +{ + return (V2f) { .x = a.x - b.x, .y = a.y - b.y }; +} + +V2f +v2f_mul(V2f a, f32 scalar) +{ + return (V2f) { .x = a.x * scalar, .y = a.y * scalar }; +} + +f32 +v2f_dot(V2f a, V2f b) +{ + return a.x * b.x + a.y * b.y; +} + +f32 +v2f_smag(V2f a) +{ + return v2f_dot(a, a); +} + +f32 +v2f_mag(V2f a) +{ + return sqrt(v2f_smag(a)); +} + +V2f +v2f_norm(V2f a) +{ + const f32 mag = v2f_mag(a); + return v2f_mul(a, 1.0f / mag); +} + +V2f +v2f_proj(V2f a, V2f onto) +{ + const f32 dp = v2f_dot(a, onto) / v2f_mag(onto); + return v2f_mul(onto, dp); +} + + + +void +mat4_identity(mat4 *mat) +{ + foreach(i, 0, 16) (*mat)[i] = 0.0f; + (*mat)[0 * 4 + 0] = 1.0f; + (*mat)[1 * 4 + 1] = 1.0f; + (*mat)[2 * 4 + 2] = 1.0f; + (*mat)[3 * 4 + 3] = 1.0f; +} + +void +mat4_ortho(mat4 *mat, + f32 left, f32 right, + f32 top, f32 bottom, + f32 near, f32 far) +{ + foreach(i, 0, 16) (*mat)[i] = 0.0; + + (*mat)[0 * 4 + 0] = 2.0f / (right - left); + (*mat)[1 * 4 + 1] = 2.0f / (top - bottom); + (*mat)[2 * 4 + 2] = -2.0f / (far - near); + (*mat)[3 * 4 + 3] = 1.0f; + + (*mat)[3 * 4 + 0] = -(right + left) / (right - left); + (*mat)[3 * 4 + 1] = -(top + bottom) / (top - bottom); + (*mat)[3 * 4 + 2] = -(far + near) / (far - near); +} + + +void +mat4_mul(mat4 a, mat4 b, mat4* out) +{ + foreach(row, 0, 4) { + foreach(col, 0, 4) { + (*out)[row * 4 + col] = 0.0f; + + foreach(i, 0, 4) { + (*out)[row * 4 + col] += a[row * 4 + i] + b[i * 4 + col]; + } + } + } +}