From 3dcaf6df818225585d576529ce5d3634e553074e Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Wed, 1 Dec 2021 03:29:18 +0000 Subject: [PATCH] Initial commit --- Makefile | 126 + source/editor/debug.c | 8 + source/editor/debug.h | 9 + source/editor/debugdraw.c | 154 + source/editor/debugdraw.h | 16 + source/editor/editor.cpp | 1432 ++++++ source/editor/editor.h | 98 + source/editor/editorstate.c | 19 + source/editor/editorstate.h | 10 + source/engine/2dcamera.h | 4 + source/engine/2dphysics.c | 385 ++ source/engine/2dphysics.h | 90 + source/engine/3dphysics.c | 47 + source/engine/3dphysics.h | 4 + source/engine/billboard.h | 4 + source/engine/camera.c | 137 + source/engine/camera.h | 24 + source/engine/component.h | 1 + source/engine/config.h | 18 + source/engine/datastream.c | 173 + source/engine/datastream.h | 30 + source/engine/engine.c | 122 + source/engine/font.c | 240 + source/engine/font.h | 29 + source/engine/gameobject.c | 200 + source/engine/gameobject.h | 73 + source/engine/gizmo.c | 1 + source/engine/gizmo.h | 4 + source/engine/input.c | 33 + source/engine/input.h | 18 + source/engine/level.c | 50 + source/engine/level.h | 17 + source/engine/light.c | 160 + source/engine/light.h | 58 + source/engine/log.c | 56 + source/engine/log.h | 17 + source/engine/mathc.c | 7545 +++++++++++++++++++++++++++++ source/engine/mathc.h | 1659 +++++++ source/engine/mesh.c | 132 + source/engine/mesh.h | 41 + source/engine/model.c | 281 ++ source/engine/model.h | 26 + source/engine/openglrender.c | 695 +++ source/engine/openglrender.h | 54 + source/engine/pinball.c | 25 + source/engine/pinball.h | 18 + source/engine/registry.c | 53 + source/engine/registry.h | 35 + source/engine/render.c | 0 source/engine/render.h | 9 + source/engine/resources.c | 112 + source/engine/resources.h | 27 + source/engine/script.c | 54 + source/engine/script.h | 10 + source/engine/shader.c | 176 + source/engine/shader.h | 37 + source/engine/skybox.c | 123 + source/engine/skybox.h | 17 + source/engine/sprite.c | 206 + source/engine/sprite.h | 47 + source/engine/static_actor.c | 77 + source/engine/static_actor.h | 24 + source/engine/texture.c | 265 + source/engine/texture.h | 73 + source/engine/thirdpersonfollow.c | 226 + source/engine/thirdpersonfollow.h | 190 + source/engine/transform.c | 44 + source/engine/transform.h | 27 + source/engine/vec.c | 132 + source/engine/vec.h | 32 + source/engine/window.c | 157 + source/engine/window.h | 34 + 72 files changed, 16530 insertions(+) create mode 100644 Makefile create mode 100644 source/editor/debug.c create mode 100644 source/editor/debug.h create mode 100644 source/editor/debugdraw.c create mode 100644 source/editor/debugdraw.h create mode 100644 source/editor/editor.cpp create mode 100644 source/editor/editor.h create mode 100644 source/editor/editorstate.c create mode 100644 source/editor/editorstate.h create mode 100644 source/engine/2dcamera.h create mode 100644 source/engine/2dphysics.c create mode 100644 source/engine/2dphysics.h create mode 100644 source/engine/3dphysics.c create mode 100644 source/engine/3dphysics.h create mode 100644 source/engine/billboard.h create mode 100644 source/engine/camera.c create mode 100644 source/engine/camera.h create mode 100644 source/engine/component.h create mode 100644 source/engine/config.h create mode 100644 source/engine/datastream.c create mode 100644 source/engine/datastream.h create mode 100644 source/engine/engine.c create mode 100644 source/engine/font.c create mode 100644 source/engine/font.h create mode 100644 source/engine/gameobject.c create mode 100644 source/engine/gameobject.h create mode 100644 source/engine/gizmo.c create mode 100644 source/engine/gizmo.h create mode 100644 source/engine/input.c create mode 100644 source/engine/input.h create mode 100644 source/engine/level.c create mode 100644 source/engine/level.h create mode 100644 source/engine/light.c create mode 100644 source/engine/light.h create mode 100644 source/engine/log.c create mode 100644 source/engine/log.h create mode 100644 source/engine/mathc.c create mode 100644 source/engine/mathc.h create mode 100644 source/engine/mesh.c create mode 100644 source/engine/mesh.h create mode 100644 source/engine/model.c create mode 100644 source/engine/model.h create mode 100644 source/engine/openglrender.c create mode 100644 source/engine/openglrender.h create mode 100644 source/engine/pinball.c create mode 100644 source/engine/pinball.h create mode 100644 source/engine/registry.c create mode 100644 source/engine/registry.h create mode 100644 source/engine/render.c create mode 100644 source/engine/render.h create mode 100644 source/engine/resources.c create mode 100644 source/engine/resources.h create mode 100644 source/engine/script.c create mode 100644 source/engine/script.h create mode 100644 source/engine/shader.c create mode 100644 source/engine/shader.h create mode 100644 source/engine/skybox.c create mode 100644 source/engine/skybox.h create mode 100644 source/engine/sprite.c create mode 100644 source/engine/sprite.h create mode 100644 source/engine/static_actor.c create mode 100644 source/engine/static_actor.h create mode 100644 source/engine/texture.c create mode 100644 source/engine/texture.h create mode 100644 source/engine/thirdpersonfollow.c create mode 100644 source/engine/thirdpersonfollow.h create mode 100644 source/engine/transform.c create mode 100644 source/engine/transform.h create mode 100644 source/engine/vec.c create mode 100644 source/engine/vec.h create mode 100644 source/engine/window.c create mode 100644 source/engine/window.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..058c893 --- /dev/null +++ b/Makefile @@ -0,0 +1,126 @@ +MAKEFLAGS := --jobs=$(shell nproc) + +TARGET := game +INFO := + +EDITOR := 1 +DEBUG := 1 + +UNAME := $(shell uname) + +ifeq ($(OS),Windows_NT) + UNAME := Windows_NT +endif + +UNAME_P := $(shell uname -m) + +#CC specifies which compiler we're using +CC = clang -x c --std=c99 +CXX = clang++ + +DEFFLAGS := + +ifeq ($(EDITOR), 1) + DEFFLAGS += -DEDITOR + TARGET = editor +endif + +ifeq ($(DEBUG), 1) + DEFFALGS += -DDEBUG + INFO = dbg +endif + +BINDIR := ./bin +BUILDDIR := ./obj + +THIRDPARTY_DIR := ./source/thirdparty +THIRDPARTY_DIRS := ${sort ${dir ${wildcard ${THIRDPARTY_DIR}/*/}}} +THIRDPARTY_I := $(addsuffix include, ${THIRDPARTY_DIRS}) $(addsuffix src, $(THIRDPARTY_DIRS)) $(THIRDPARTY_DIRS) $(addsuffix build/include, $(THIRDPARTY_DIRS)) $(addsuffix include/chipmunk, $(THIRDPARTY_DIRS)) +THIRDPARTY_L := $(addsuffix build/lib, $(THIRDPARTY_DIRS)) $(addsuffix build, ${THIRDPARTY_DIRS}) $(addsuffix build/bin, $(THIRDPARTY_DIRS) $(addsuffix build/src, $(THIRDPARTY_DIRS))) + +# imgui sources +IMGUI_DIR := ${THIRDPARTY_DIR}/imgui +imgui = $(addprefix ${IMGUI_DIR}/, imgui imgui_draw imgui_widgets imgui_tables) +imguibackends = $(addprefix ${IMGUI_DIR}/backends/, imgui_impl_sdl imgui_impl_opengl3) +imguiobjs := $(addsuffix .cpp, $(imgui) $(imguibackends)) + +plmpeg_objs := ${THIRDPARTY_DIR}/pl_mpeg/pl_mpeg_extract_frames.c +cpobjs := $(wildcard ${THIRDPARTY_DIR}/Chipmunk2D/src/*.c) +s7objs := ${THIRDPARTY_DIR}/s7/s7.c + +includeflag := $(addprefix -I, $(THIRDPARTY_I) ./source/engine ./source/editor $(IMGUI_DIR) $(IMGUI_DIR)/backends) + +#LIBRARY_PATHS specifies the additional library paths we'll need +LIB_PATHS := $(addprefix -L, $(THIRDPARTY_L)) + +# Engine sources +sources := $(wildcard ./source/engine/*.cpp ./source/engine/*.c ./source/editor/*.c ./source/editor/*.cpp) $(imguiobjs) $(s7objs) $(cpobjs) + +#COMPILER_FLAGS specifies the additional compilation options we're using +WARNING_FLAGS := -w #-pedantic -Wall -Wextra -Wwrite-strings +COMPILER_FLAGS := -g -O0 $(WARNING_FLAGS) + + +ifeq ($(UNAME), Windows_NT) + LINKER_FLAGS:= -static + # DYNAMIC LIBS: SDL2 opengl32 + ELIBS := glew32 mingw32 SDL2main SDL2 m dinput8 dxguid dxerr8 user32 gdi32 winmm imm32 ole32 oleaut32 shell32 version uuid setupapi opengl32 stdc++ winpthread + CLIBS := + EXT := .exe +else + LINKER_FLAGS := + ELIBS := + CLIBS := SDL2 GLEW GL dl pthread + EXT := +endif + +LELIBS := -Wl,-Bstatic $(addprefix -l, ${ELIBS}) -Wl,-Bdynamic $(addprefix -l, $(CLIBS)) + +BUILDD = -DGLEW_STATIC + +dir_guard = @mkdir -p $(@D) + +objprefix = ./obj/$(UNAME)/$(UNAME_P)/$(TARGET)$(INFO) + +objects := $(patsubst .%.cpp, $(objprefix)%.o, $(filter %.cpp, $(sources))) $(patsubst .%.c, $(objprefix)%.o, $(filter %.c, $(sources))) +objects := $(sort $(objects)) +depends := $(patsubst %.o, %.d, $(objects)) + +FILENAME = $(TARGET)$(INFO)_$(UNAME_P)$(EXT) + +all: install + +$(TARGET): $(objects) + @echo Linking $(TARGET) + @$(CXX) $^ -DGLEW_STATIC $(LINKER_FLAGS) $(LIB_PATHS) $(LELIBS) -o $@ + +install: $(TARGET) + mkdir -p bin/$(UNAME) && cp $(TARGET) bin/$(UNAME)/$(FILENAME) + cp $(TARGET) yugine/$(FILENAME) + rm $(TARGET) + +-include $(depends) + +$(objprefix)/%.o:%.cpp + $(dir_guard) + @echo Making C++ object $(notdir $@) + -@$(CXX) $(BUILDD) $(DEFFLAGS) $(includeflag) $(COMPILER_FLAGS) -MD -c $< -o $@ + +$(objprefix)/%.o:%.c + $(dir_guard) + @echo Making C object $(notdir $@) + -@$(CC) $(BUILDD) $(DEFFLAGS) $(includeflag) $(COMPILER_FLAGS) -MD -c $< -o $@ + +clean: + @echo Cleaning project + @rm -f $(objects) $(depends) + +bsclean: + rm -f $(bsobjects) + +gameclean: + rm -f $(gameobjects) + +TAGS: $(sources) $(edsources) + @echo Generating TAGS file + @ctags -eR $^ diff --git a/source/editor/debug.c b/source/editor/debug.c new file mode 100644 index 0000000..efccac7 --- /dev/null +++ b/source/editor/debug.c @@ -0,0 +1,8 @@ +#include "debug.h" + +unsigned long long triCount = 0; + +void resetTriangles() +{ + triCount = 0; +} \ No newline at end of file diff --git a/source/editor/debug.h b/source/editor/debug.h new file mode 100644 index 0000000..53ee327 --- /dev/null +++ b/source/editor/debug.h @@ -0,0 +1,9 @@ +#ifndef DEBUG_GUI_H +#define DEBUG_GUI_H + +extern unsigned long long triCount; + +void resetTriangles(); + + +#endif diff --git a/source/editor/debugdraw.c b/source/editor/debugdraw.c new file mode 100644 index 0000000..608109b --- /dev/null +++ b/source/editor/debugdraw.c @@ -0,0 +1,154 @@ +#include "debugdraw.h" + +#include "openglrender.h" + +#include "shader.h" + +static uint32_t circleVBO; +static uint32_t circleVAO; +static struct mShader *circleShader; + +static uint32_t gridVBO; +static uint32_t gridVAO; +static struct mShader *gridShader; + +static uint32_t rectVBO; +static uint32_t rectVAO; +static struct mShader *rectShader; + +void debugdraw_init() +{ + circleShader = MakeShader("circlevert.glsl", "circlefrag.glsl"); + shader_setUBO(circleShader, "Projection", 0); + glGenBuffers(1, &circleVBO); + glGenVertexArrays(1, &circleVAO); + + + float gridverts[] = { + -1.f, -1.f, + 1.f, -1.f, + -1.f, 1.f, + 1.f, 1.f + }; + + gridShader = MakeShader("gridvert.glsl", "gridfrag.glsl"); + shader_setUBO(gridShader, "Projection", 0); + glGenBuffers(1, &gridVBO); + glGenVertexArrays(1, &gridVAO); + glBindVertexArray(gridVAO); + glBindBuffer(GL_ARRAY_BUFFER, gridVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(gridverts), &gridverts, + GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); + + rectShader = MakeShader("linevert.glsl", "linefrag.glsl"); + shader_setUBO(rectShader, "Projection", 0); + glGenBuffers(1, &rectVBO); + glGenVertexArrays(1, &rectVAO); +} + +void draw_line(int x1, int y1, int x2, int y2) +{ + shader_use(rectShader); + float verts[] = { + x1, y1, + x2, y2 + }; + + glBindBuffer(GL_ARRAY_BUFFER, rectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_DYNAMIC_DRAW); + glBindVertexArray(rectVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glDrawArrays(GL_LINE_STRIP, 0, 2); +} + +void draw_edge(float *points, int n) +{ + shader_use(rectShader); + glBindBuffer(GL_ARRAY_BUFFER, rectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * n * 2, points, + GL_DYNAMIC_DRAW); + glBindVertexArray(rectVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glDrawArrays(GL_LINE_STRIP, 0, n); +} + +void draw_circle(int x, int y, float radius, int pixels) +{ + shader_use(circleShader); + + float verts[] = { + x - radius, y - radius, -1.f, -1.f, + x + radius, y - radius, 1.f, -1.f, + x - radius, y + radius, -1.f, 1.f, + x + radius, y + radius, 1.f, 1.f + }; + + glBindBuffer(GL_ARRAY_BUFFER, circleVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_DYNAMIC_DRAW); + + shader_setfloat(circleShader, "radius", radius); + shader_setint(circleShader, "thickness", pixels); + + glBindVertexArray(circleVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +void draw_rect(int x, int y, int w, int h) +{ + float hw = w / 2.f; + float hh = h / 2.f; + + float verts[] = { + x - hw, y - hh, + x + hw, y - hh, + x + hw, y + hh, + x - hw, y + hh + }; + + shader_use(rectShader); + glBindBuffer(GL_ARRAY_BUFFER, rectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_DYNAMIC_DRAW); + glBindVertexArray(rectVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glDrawArrays(GL_LINE_LOOP, 0, 4); +} + +void draw_grid(int width, int span) +{ + shader_use(gridShader); + shader_setint(gridShader, "thickness", width); + shader_setint(gridShader, "span", span); + glBindVertexArray(gridVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + +} + +void draw_point(int x, int y, float r) +{ + draw_circle(x, y, r, r); +} + +void draw_poly(float *points, int n) +{ + shader_use(rectShader); + glBindBuffer(GL_ARRAY_BUFFER, rectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * n * 2, points, + GL_DYNAMIC_DRAW); + glBindVertexArray(rectVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glDrawArrays(GL_LINE_LOOP, 0, n); +} + +void debugdraw_flush() +{ + +} diff --git a/source/editor/debugdraw.h b/source/editor/debugdraw.h new file mode 100644 index 0000000..14b0723 --- /dev/null +++ b/source/editor/debugdraw.h @@ -0,0 +1,16 @@ +#ifndef DEBUGDRAW_H +#define DEBUGDRAW_H + +void debugdraw_init(); +void draw_line(int x1, int y1, int x2, int y2); +void draw_edge(float *points, int n); +void draw_circle(int x, int y, float radius, int pixels); +void draw_grid(int width, int span); +void draw_rect(int x, int y, int w, int h); +void draw_point(int x, int y, float r); +void draw_poly(float *points, int n); + +void debugdraw_flush(); /* This is called once per frame to draw all queued elements */ + + +#endif diff --git a/source/editor/editor.cpp b/source/editor/editor.cpp new file mode 100644 index 0000000..3b3a5ef --- /dev/null +++ b/source/editor/editor.cpp @@ -0,0 +1,1432 @@ +extern "C" { +#include "editor.h" +#include "window.h" +#include "resources.h" +#include "registry.h" +#include "datastream.h" +#include "gameobject.h" +#include "camera.h" +#include "shader.h" +#include +#include +#include "editorstate.h" +#include +#include "input.h" +#include "openglrender.h" +#include "2dphysics.h" +#include "debugdraw.h" +#include "level.h" +#include "texture.h" +#include "sprite.h" +#include +#include "math.h" +#include +#include +#include +#include "pinball.h" +#include "config.h" +#include "vec.h" +#include "debug.h" +#include "script.h" +} +#include +#define ASSET_TEXT_BUF 1024*1024 /* 1 MB buffer for editing text files */ +#include +#include +#include +struct gameproject *cur_project; +struct vec *projects; +static char setpath[MAXPATH]; + + + + + + + + + +// Menus +// TODO: Pack this into a bitfield +static struct editorVars editor = { 0 }; + +bool flashlightOn = false; + +// Lighting effect flags +static bool renderAO = true; +static bool renderDynamicShadows = true; +static bool renderRefraction = true; +static bool renderReflection = true; + +// Debug render modes +static bool renderGizmos = false; +static bool showGrid = true; +static bool debugDrawPhysics = false; +static bool renderNav = false; + +const char *allowed_extensions[] = { "jpg", "png", "gltf", "glsl" }; + +static const char *editor_filename = "editor.ini"; + +static ImGuiIO *io = NULL; +static struct { + char *key; + struct fileasset *value; +} *assets = NULL; +static char asset_search_buffer[100] = { 0 }; + +struct fileasset *selected_asset; + +static int selected_index = -1; + +static struct mCamera camera = { 0 }; + +static int tex_view = 0; + +static int grid1_width = 1; +static int grid1_span = 100; +static int grid2_width = 3; +static int grid2_span = 1000; +static bool grid1_draw = true; +static bool grid2_draw = true; + +static float tex_scale = 1.f; +static struct TexAnimation tex_gui_anim = { 0 }; + +char current_level[MAXNAME] = { '\0' }; +char levelname[MAXNAME] = { '\0' }; + +static struct vec *levels = NULL; + +static const int ASSET_WIN_SIZE = 512; + +static const char *get_extension(const char *filepath) +{ + return strrchr(filepath, '.'); +} + +static int +check_if_resource(const char *fpath, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) +{ + if (typeflag == FTW_F) { + const char *ext = get_extension(fpath); + if (ext && is_allowed_extension(ext)) { + struct fileasset *newasset = + (struct fileasset *) calloc(1, sizeof(struct fileasset)); + newasset->filename = + (char *) malloc(sizeof(char) * strlen(fpath) + 1); + strcpy(newasset->filename, fpath); + newasset->extension_len = strlen(ext); + newasset->searched = true; + shput(assets, newasset->filename, newasset); + } + } + + return 0; +} + +static void print_files_in_directory(const char *dirpath) +{ + int nflags = 0; + shfree(assets); + nftw(dirpath, &check_if_resource, 10, nflags); +} + +static void get_all_files() +{ + print_files_in_directory(DATA_PATH); +} + +static int *compute_prefix_function(const char *str) +{ + int str_len = strlen(str); + int *pi = (int *) malloc(sizeof(int) * str_len); + pi[0] = 0; + int k = 0; + + for (int q = 2; q < str_len; q++) { + while (k > 0 && str[k + 1] != str[q]) + k = pi[k]; + + if (str[k + 1] == str[q]) + k += 1; + + pi[q] = k; + } + + return pi; +} + +static bool kmp_match(const char *search, const char *text, int *pi) +{ + int s_len = strlen(search); + int t_len = strlen(text); + // int *pi = compute_prefix_function(search); + int q = 0; + bool found = false; + + for (int i = 0; i < t_len; i++) { + while (q > 0 && search[q + 1] != text[i]) + q = pi[q]; + + if (search[q + 1] == text[i]) + q += 1; + + if (q == s_len) { + q = pi[q]; + found = true; + goto end; + } + } + + end: + return found; +} + + +static int MyCallback(ImGuiInputTextCallbackData * data) +{ + if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion) { + data->InsertChars(data->CursorPos, ".."); + } else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory) { + if (data->EventKey == ImGuiKey_UpArrow) { + data->DeleteChars(0, data->BufTextLen); + data->InsertChars(0, "Pressed Up!"); + data->SelectAll(); + } else if (data->EventKey == ImGuiKey_DownArrow) { + data->DeleteChars(0, data->BufTextLen); + data->InsertChars(0, "Pressed Down!"); + data->SelectAll(); + } + } else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit) { + int i = 0; + if (data->Buf[0] == '\0') + while (i < shlen(assets)) + assets[i].value->searched = true; + else + while (i < shlen(assets)) + assets[i].value->searched = + (strstr(assets[i].value->filename, data->Buf) == + NULL) ? false : true; + + } + + return 0; +} + +static int TextEditCallback(ImGuiInputTextCallbackData * data) +{ + static int dirty = 0; + + if (data->EventChar == '\n') { + dirty = 1; + } else if (data->EventChar == '(') { + //data->EventChar = 245; + dirty = 2; + } else if (data->EventChar == ')') { + dirty = 3; + } + + if (data->EventFlag == ImGuiInputTextFlags_CallbackAlways) { + if (dirty == 1) { + dirty = 0; + char *c = &data->Buf[data->CursorPos - 2]; + + /* Seek to last newline */ + while (*c != '\n') + c--; + c++; + if (isblank(*c)) { + char *ce = c; + + while (isblank(*ce)) + ce++; + + data->InsertChars(data->CursorPos, c, ce); + } + + } + } + + + return 0; +} + +void editor_save() +{ + FILE *feditor = fopen(editor_filename, "w+"); + fwrite(&editor, sizeof(editor), 1, feditor); + fclose(feditor); +} + +void editor_init(struct mSDLWindow *mwindow) +{ + projects = vec_make(sizeof(struct gameproject), 5); + levels = vec_make(MAXNAME, 10); + editor_load_projects(); + + FILE *feditor = fopen(editor_filename, "r"); + if (feditor == NULL) { + editor_save(); + } else { + fread(&editor, sizeof(editor), 1, feditor); + fclose(feditor); + } + + + + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO & io = ImGui::GetIO(); + (void) io; + ImGui::StyleColorsClassic(); + ImGui_ImplSDL2_InitForOpenGL(window->window, window->glContext); + ImGui_ImplOpenGL3_Init(); +} + +void editor_input(SDL_Event * e) +{ + ImGui_ImplSDL2_ProcessEvent(e); + io = &ImGui::GetIO(); + + + //User requests quit + if (e->type == SDL_QUIT) { + quit = true; + } + //Handle keypress with current mouse position + else if (!editor_wantkeyboard() && e->type == SDL_KEYDOWN) { + switch (e->key.keysym.sym) { + case SDLK_ESCAPE: + quit = true; + editor_save_projects(); + editor_save(); + break; + + case SDLK_1: + renderMode = LIT; + break; + + case SDLK_2: + renderMode = UNLIT; + break; + + case SDLK_3: + renderMode = WIREFRAME; + break; + + case SDLK_4: + renderMode = DIRSHADOWMAP; + break; + + case SDLK_5: + renderGizmos = !renderGizmos; + break; + + case SDLK_6: + debugDrawPhysics = !debugDrawPhysics; + break; + + case SDLK_7: + break; + + case SDLK_8: + break; + + case SDLK_9: + break; + + case SDLK_0: + break; + + case SDLK_t: + break; + + case SDLK_F2: + editor.showAssetMenu = !editor.showAssetMenu; + break; + + case SDLK_F3: + editor.showStats = !editor.showStats; + break; + + case SDLK_F4: + editor.showHierarchy = !editor.showHierarchy; + break; + + case SDLK_F5: + editor.showLighting = !editor.showLighting; + break; + + case SDLK_F6: + editor.showGameSettings = !editor.showGameSettings; + break; + + case SDLK_F7: + editor.showViewmode = !editor.showViewmode; + break; + + case SDLK_F8: + editor.showDebugMenu = !editor.showDebugMenu; + break; + + case SDLK_F9: + editor.showExport = !editor.showExport; + break; + + case SDLK_F10: + editor.showLevel = !editor.showLevel; + break; + + case SDLK_F11: + window_togglefullscreen(window); + break; + + case SDLK_BACKQUOTE: + editor.showREPL = !editor.showREPL; + break; + + case SDLK_k: + showGrid = !showGrid; + break; + + case SDLK_DELETE: + break; + + case SDLK_f: + /* + if (selectedobject != NULL) { + cam_goto_object(&camera, &selectedobject->transform); + } + */ + break; + + }; + } else if (!editor_wantkeyboard() && e->type == SDL_MOUSEBUTTONDOWN) { + if (selectedobject != NULL) { + switch (e->key.keysym.sym) { + case SDLK_g: + // handle translate + break; + + case SDLK_r: + break; + + case SDLK_t: + break; + } + } + switch (e->button.button) { + case SDL_BUTTON_RIGHT: + SDL_SetRelativeMouseMode(SDL_TRUE); + break; + + case SDL_BUTTON_MIDDLE: +/* + glBindFramebuffer(GL_FRAMEBUFFER, debugColorPickBO); + int mx = 0; + int my = 0; + SDL_GetMouseState(&mx, &my); + unsigned char data[4]; + glReadPixels(mx, SCREEN_HEIGHT - my, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); + int pickID = data[0] + data[1]*256 + data[2]*256*256; + snprintf(objectName, 200, "Object %d", pickID); + pickGameObject(pickID); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + */ + + pickGameObject(-1); + + break; + } + + } else if (!editor_wantkeyboard() && e->type == SDL_MOUSEBUTTONUP) { + switch (e->button.button) { + case SDL_BUTTON_RIGHT: + + SDL_SetRelativeMouseMode(SDL_FALSE); + SDL_WarpMouseInWindow(window->window, SCREEN_WIDTH / 2.f, + SCREEN_HEIGHT / 2.f); + break; + } + } else if (e->type == SDL_MOUSEWHEEL) { + mouseWheelY = e->wheel.y; + } + + + + + SDL_GetRelativeMouseState(&xchange, &ychange); + + if (SDL_GetRelativeMouseMode()) { + // camera_update(&camera, xchange, ychange, currentKeyStates, mouseWheelY, deltaT); + } +} + +int editor_wantkeyboard() +{ + return io->WantCaptureKeyboard; +} + +void editor_project_gui() +{ +/* Grid, etc */ + if (grid1_draw) + draw_grid(grid1_width, grid1_span); + if (grid2_draw) + draw_grid(grid2_width, grid2_span); + + + + if (debugDrawPhysics) { + /* + for (int i = 0; i < number_of_gameobjects(); i++) + phys2d_dbgdrawcircle(objects[i]->circle); + */ + } + + + + if (ImGui::BeginMainMenuBar()) { + ImGui::Text("Current level: %s", + current_level[0] == + '\0' ? "Level not saved!" : current_level); + + if (ImGui::BeginMenu("Windows")) { + ImGui::MenuItem("Resources", "F2", &editor.showAssetMenu); + ImGui::MenuItem("Hierarchy", "F4", &editor.showHierarchy); + ImGui::MenuItem("Lighting", "F5", &editor.showLighting); + ImGui::MenuItem("Game Settings", "F6", + &editor.showGameSettings); + ImGui::MenuItem("View", "F7", &editor.showViewmode); + ImGui::MenuItem("Debug", "F8", &editor.showDebugMenu); + ImGui::MenuItem("Export", "F9", &editor.showExport); + ImGui::MenuItem("Level", "F10", &editor.showLevel); + ImGui::MenuItem("REPL", "`", &editor.showREPL); + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Levels")) { + if (ImGui::Button("New")) { + new_level(); + current_level[0] = '\0'; + } + + + if (ImGui::Button("Save")) { + save_level(current_level); + get_levels(); + } + + if (ImGui::Button("Save as")) { + save_level(levelname); + strcpy(current_level, levelname); + levelname[0] = '\0'; + get_levels(); + } + + ImGui::SameLine(); + ImGui::InputText("", levelname, MAXNAME); + + vec_walk(levels, (void (*)(void *)) &editor_level_btn); + + ImGui::EndMenu(); + } + + ImGui::EndMainMenuBar(); + } + + if (editor.showExport) { + ImGui::Begin("Export and Bake", &editor.showExport); + + if (ImGui::Button("Bake")) { + } + if (ImGui::Button("Build")) { + } + + ImGui::End(); + } + + + // Shadow map vars + if (editor.showLighting) { + ImGui::Begin("Lighting options", &editor.showLighting); + if (ImGui::CollapsingHeader("Directional shadow map")) { + ImGui::SliderFloat("Near plane", &near_plane, -200.f, 200.f, + NULL, 1.f); + ImGui::SliderFloat("Far plane", &far_plane, -200.f, 200.f, + NULL, 1.f); + ImGui::SliderFloat("Shadow Lookahead", &shadowLookahead, 0.f, + 100.f, NULL, 1.f); + ImGui::SliderFloat("Plane size", &plane_size, 0.f, 100.f, NULL, + 1.f); + } + + ImGui::End(); + } + + if (editor.showGameSettings) { + ImGui::Begin("Game settings", &editor.showGameSettings); + + ImGui::InputText("Game name", cur_project->name, 127); + + if (ImGui::CollapsingHeader("Physics")) { + ImGui::DragFloat("2d Gravity", &phys2d_gravity, 1.f, -5000.f, + 0.f, "%.3f"); + phys2d_apply(); + } + + if (ImGui::CollapsingHeader("Quality")) { + + } + + ImGui::End(); + } + + + if (editor.showStats) { + ImGui::Begin("Stats", &editor.showStats); + ImGui::Text("FPS: %2.4f", 1.f / deltaT); + ImGui::Text("Triangles rendered: %d", triCount); + ImGui::End(); + } + + + if (editor.showREPL) { + ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue; + ImGui::Begin("REPL", &editor.showREPL); + static char buffer[512] = { '\0' }; + if (ImGui::InputText("", buffer, 512, flags)) { + //scheme_load_string(sc, buffer); + script_run(buffer); + buffer[0] = { '\0' }; + } + ImGui::End(); + + } + + if (editor.showViewmode) { + ImGui::Begin("View options", &editor.showViewmode); + + ImGui::SliderFloat("Camera FOV", &editorFOV, 0.1f, 90.f); + ImGui::SliderFloat("Camera Near Plane", &editorClose, 0.1f, 5.f); + ImGui::SliderFloat("Camera Far Plane", &editorFar, 50.f, 10000.f); + + if (ImGui::CollapsingHeader("Shading mode")) { + ImGui::RadioButton("Lit", &renderMode, RenderMode::LIT); + ImGui::RadioButton("Unlit", &renderMode, RenderMode::UNLIT); + ImGui::RadioButton("Wireframe", &renderMode, + RenderMode::WIREFRAME); + ImGui::RadioButton("Directional shadow map", &renderMode, + RenderMode::DIRSHADOWMAP); + } + + if (ImGui::CollapsingHeader("Lighting")) { + ImGui::Checkbox("Shadows", &renderDynamicShadows); + ImGui::Checkbox("Ambient Occlusion", &renderAO); + } + + if (ImGui::CollapsingHeader("Debug Draws")) { + ImGui::Checkbox("Gizmos", &renderGizmos); + ImGui::Checkbox("Grid", &showGrid); + ImGui::Checkbox("Physics", &debugDrawPhysics); + } + + ImGui::End(); + } + + if (editor.showHierarchy) { + ImGui::Begin("Objects", &editor.showHierarchy); + + if (ImGui::Button("New Object")) { + MakeGameobject(); + } + + obj_gui_hierarchy(selectedobject); + + ImGui::End(); + } + + ImGui::Begin("Simulate"); + + if (physOn) { + if (ImGui::Button("Pause")) + game_pause(); + + ImGui::SameLine(); + if (ImGui::Button("Stop")) + game_stop(); + } else { + if (ImGui::Button("Play")) + game_start(); + } + + ImGui::End(); + + + ImGui::Begin("Prefab Creator"); + + vec_walk(prefabs, (void (*)(void *)) &editor_prefab_btn); + + ImGui::End(); + + + if (editor.showAssetMenu) { + ImGui::Begin("Asset Menu", &editor.showAssetMenu); + + ImGui::InputText("Search", asset_search_buffer, 100, + ImGuiInputTextFlags_CallbackEdit, MyCallback); + + if (ImGui::Button("Reload all files")) + get_all_files(); + + ImGui::BeginChild("##scrolling"); + for (int i = 0; i < shlen(assets); i++) { + if (!assets[i].value->searched) + continue; + + if (ImGui::Button(assets[i].value->filename + stemlen)) { + editor_selectasset(assets[i].value); + } + } + ImGui::EndChild(); + + ImGui::End(); + } + + if (selected_asset) + editor_asset_gui(selected_asset); + + + + + if (editor.showDebugMenu) { + ImGui::Begin("Debug Menu", &editor.showDebugMenu); + if (ImGui::Button("Reload Shaders")) { + shader_compile_all(); + } + //ImGui::SliderFloat("Grid scale", &gridScale, 100.f, 500.f, "%1.f"); + + ImGui::SliderInt("Grid 1 Span", &grid1_span, 1, 500); + ImGui::SameLine(); + ImGui::Checkbox("Draw", &grid1_draw); + + ImGui::SliderInt("Grid 2 Span", &grid2_span, 10, 1000); + ImGui::SameLine(); + ImGui::Checkbox("Draw", &grid2_draw); + + /* + ImGui::SliderFloat("Grid Opacity", &gridOpacity, 0.f, 1.f); + ImGui::SliderFloat("Small unit", &smallGridUnit, 0.5f, 5.f); + ImGui::SliderFloat("Big unit", &bigGridUnit, 10.f, 50.f); + ImGui::SliderFloat("Small thickness", &gridSmallThickness, 1.f, 10.f, "%1.f"); + ImGui::SliderFloat("Big thickness", &gridBigThickness, 1.f, 10.f, "%1.f"); + ImGui::ColorEdit3("1 pt grid color", (float*)&gridSmallColor); + ImGui::ColorEdit3("10 pt grid color", (float*)&gridBigColor); + */ + //ImGui::SliderInt("MSAA", &msaaSamples, 0, 4); + ImGui::End(); + } + + startobjectgui: + + if (selectedobject) { + draw_point(selectedobject->transform.position[0], + selectedobject->transform.position[1], 5); + + + ImGui::Begin("Object Parameters"); + + if (ImGui::Button("Save")) + gameobject_saveprefab(selectedobject); + + ImGui::SameLine(); + if (ImGui::Button("Del")) { + gameobject_delete(selected_index); + pickGameObject(-1); + ImGui::End(); + goto startobjectgui; + } + + ImGui::SameLine(); + if (selectedobject->editor.prefabSync) { + if (ImGui::Button("Revert")) + gameobject_revertprefab(selectedobject); + + } + + + ImGui::InputText("Name", selectedobject->editor.mname, 50); + + ImGui::InputText("Prefab", selectedobject->editor.prefabName, 50, + selectedobject->editor. + prefabSync ? ImGuiInputTextFlags_ReadOnly : 0); + + object_gui(selectedobject); + + + ImGui::End(); + + + ImGui::Begin("Components"); + + for (int i = 0; i < ncomponent; i++) { + if (ImGui::Button(components[i].name)) { + gameobject_addcomponent(selectedobject, &components[i]); + } + } + + + ImGui::End(); + + } + + +} + +void editor_render() +{ + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + ImGui::NewFrame(); + + + if (cur_project) + editor_project_gui(); + else + editor_proj_select_gui(); + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); +} + + +void pickGameObject(int pickID) +{ + if (pickID >= 0 && pickID < gameobjects->len) { + selected_index = pickID; + selectedobject = + (struct mGameObject *) vec_get(gameobjects, pickID); + } else { + selected_index = -1; + selectedobject = NULL; + } +} + +int is_allowed_extension(const char *ext) +{ + for (int i = 0; + i < sizeof(allowed_extensions) / sizeof(allowed_extensions[0]); + i++) { + if (!strcmp(ext + 1, allowed_extensions[i])) + return true; + } + + return false; +} + +void editor_level_btn(char *level) +{ + if (ImGui::Button(level)) { + load_level(level); + strcpy(current_level, level); + } +} + +void editor_selectasset(struct fileasset *asset) +{ + const char *ext = get_extension(asset->filename); + + if (!strcmp(ext + 1, "png") || !strcmp(ext + 1, "jpg")) { + asset->data = + texture_loadfromfile((struct Texture *) asset->data, + asset->filename); + tex_gui_anim.tex = (struct Texture *) asset->data; + asset->type = ASSET_TYPE_IMAGE; + tex_anim_set(&tex_gui_anim); + tex_scale = float ((float) ASSET_WIN_SIZE / tex_gui_anim.tex->width); + if (tex_scale >= 10.f) + tex_scale = 10.f; + } else if (!strcmp(ext + 1, "glsl")) { + asset->type = ASSET_TYPE_TEXT; + + FILE *fasset = fopen(asset->filename, "rb"); + + fseek(fasset, 0, SEEK_END); + long length = ftell(fasset); + fseek(fasset, 0, SEEK_SET); + asset->data = malloc(ASSET_TEXT_BUF); + fread(asset->data, 1, length, fasset); + fclose(fasset); + + + } + selected_asset = asset; +} + +void editor_selectasset_str(char *path) +{ + struct fileasset *asset = shget(assets, path); + + if (asset) + editor_selectasset(asset); +} + +void editor_asset_tex_gui(struct Texture *tex) +{ + ImGui::Text("%dx%d", tex->width, tex->height); + + ImGui::SliderFloat("Zoom", &tex_scale, 0.01f, 10.f); + + int old_sprite = tex->opts.sprite; + ImGui::Checkbox("Sprite", (bool *) &tex->opts.sprite); + + if (old_sprite != tex->opts.sprite) + tex_gpu_load(tex); + +/* + ImGui::RadioButton("Raw", &tex_view, 0); + ImGui::SameLine(); ImGui::RadioButton("View 1", &tex_view, 1); + ImGui::SameLine(); ImGui::RadioButton("View 2", &tex_view, 2); +*/ + + ImGui::Checkbox("Animation", (bool *) &tex->opts.animation); + + if (tex->opts.animation) { + int old_frames = tex->anim.frames; + int old_ms = tex->anim.ms; + ImGui::SliderInt("Frames", &tex->anim.frames, 1, 20); + ImGui::SliderInt("FPS", &tex->anim.ms, 1, 24); + + + + + if (tex_gui_anim.playing) { + if (ImGui::Button("Pause")) + anim_pause(&tex_gui_anim); + ImGui::SameLine(); + if (tex_gui_anim.playing && ImGui::Button("Stop")) + anim_stop(&tex_gui_anim); + } else { + if (ImGui::Button("Play")) + anim_play(&tex_gui_anim); + + ImGui::SameLine(); + if (ImGui::Button("Bkwd")) + anim_bkwd(&tex_gui_anim); + + + ImGui::SameLine(); + if (ImGui::Button("Fwd")) + anim_fwd(&tex_gui_anim); + } + + + + + + + + + ImGui::SameLine(); + ImGui::Text("Frame %d/%d", tex_gui_anim.frame + 1, + tex_gui_anim.tex->anim.frames); + + + + + + if (old_frames != tex->anim.frames || old_ms != tex->anim.ms) + tex_anim_set(&tex_gui_anim); + + ImVec2 uv0 = ImVec2(tex_gui_anim.uv.x, tex_gui_anim.uv.y); + ImVec2 uv1 = ImVec2(tex_gui_anim.uv.x + tex_gui_anim.uv.w, + tex_gui_anim.uv.y + tex_gui_anim.uv.h); + ImGui::Image((void *) (intptr_t) tex->id, + ImVec2(tex->width * tex_gui_anim.uv.w * tex_scale, + tex->height * tex_gui_anim.uv.h * tex_scale), + uv0, uv1); + } else { + ImGui::Image((void *) (intptr_t) tex->id, + ImVec2(tex->width * tex_scale, + tex->height * tex_scale)); + } + +} + +void editor_asset_text_gui(char *text) +{ + ImGui::InputTextMultiline("File edit", text, ASSET_TEXT_BUF, + ImVec2(600, 500), + ImGuiInputTextFlags_CallbackAlways | + ImGuiInputTextFlags_CallbackCharFilter, + TextEditCallback); + if (ImGui::Button("Save")) { + FILE *f = fopen(selected_asset->filename, "wd"); + size_t len = strlen(text); + fwrite(text, len, 1, f); + fclose(f); + } +} + +void editor_asset_gui(struct fileasset *asset) +{ + ImGui::Begin("Asset Viewer"); + + ImGui::Text("%s", selected_asset->filename); + + ImGui::SameLine(); + if (ImGui::Button("Close")) + selected_asset = NULL; + + switch (asset->type) { + case ASSET_TYPE_NULL: + break; + + case ASSET_TYPE_IMAGE: + editor_asset_tex_gui((struct Texture *) asset->data); + break; + + case ASSET_TYPE_TEXT: + editor_asset_text_gui((char *) asset->data); + break; + } + + ImGui::End(); +} + +void editor_load_projects() +{ + FILE *f = fopen("projects.yugh", "r"); + if (!f) + return; + + vec_load(projects, f); + fclose(f); +} + +void editor_save_projects() +{ + FILE *f = fopen("projects.yugh", "w"); + vec_store(projects, f); + fclose(f); +} + +void editor_project_btn_gui(struct gameproject *gp) +{ + if (ImGui::Button(gp->name)) + editor_init_project(gp); + + + ImGui::SameLine(); + ImGui::Text(gp->path); +} + +void editor_proj_select_gui() +{ + ImGui::Begin("Project Select"); + + vec_walk(projects, (void (*)(void *)) &editor_project_btn_gui); + + ImGui::InputText("Project import path", setpath, MAXPATH); + ImGui::SameLine(); + if (ImGui::Button("Create")) { + editor_make_project(setpath); + } + ImGui::SameLine(); + if (ImGui::Button("Import")) { + editor_import_project(setpath); + } + + ImGui::End(); +} + +void editor_init_project(struct gameproject *gp) +{ + cur_project = gp; + DATA_PATH = gp->path; + stemlen = strlen(DATA_PATH); + findPrefabs(); + get_levels(); + get_all_files(); +} + +void editor_make_project(char *path) +{ + FILE *f = path_open("%s%s", "w", path, "/project.yugh"); + cur_project = + (struct gameproject *) malloc(sizeof(struct gameproject)); + strncpy(cur_project->name, "New Game", 127); + strncpy(cur_project->path, path, 2048); + vec_add(projects, cur_project); + fwrite(cur_project, sizeof(*cur_project), 1, f); + fclose(f); + + editor_init_project(cur_project); + + editor_save_projects(); +} + +void editor_import_project(char *path) +{ + FILE *f = path_open("%s%s", "r", path, "/project.yugh"); + if (!f) + return; + + struct gameproject *gp = (struct gameproject *) malloc(sizeof(*gp)); + fread(gp, sizeof(*gp), 1, f); + fclose(f); + + vec_add(projects, gp); +} + + +/////// Object GUIs +#include "light.h" +#include "transform.h" +#include "static_actor.h" + +/* +void light_gui(struct mLight *light) +{ + object_gui(&light->obj); + + if (ImGui::CollapsingHeader("Light")) { + ImGui::DragFloat("Strength", &light->strength, 0.001f, 0.f, 1.f); + ImGui::ColorEdit3("Color", &light->color[0]); + ImGui::Checkbox("Dynamic", (bool *) &light->dynamic); + } +} + + +void pointlight_gui(struct mPointLight *light) +{ + light_gui(&light->light); + + if (ImGui::CollapsingHeader("Point Light")) { + ImGui::DragFloat("Constant", &light->constant, 0.001f, 0.f, 1.f); + ImGui::DragFloat("Linear", &light->linear, 0.001f, 0.f, 0.3f); + ImGui::DragFloat("Quadratic", &light->quadratic, 0.001f, 0.f, + 0.3f); + } + +} + +void spotlight_gui(struct mSpotLight *spot) +{ + light_gui(&spot->light); + + if (ImGui::CollapsingHeader("Spotlight")) { + ImGui::DragFloat("Linear", &spot->linear, 0.001f, 0.f, 1.f); + ImGui::DragFloat("Quadratic", &spot->quadratic, 0.001f, 0.f, 1.f); + ImGui::DragFloat("Distance", &spot->distance, 0.1f, 0.f, 200.f); + ImGui::DragFloat("Cutoff Degrees", &spot->cutoff, 0.01f, 0.f, + 0.7f); + ImGui::DragFloat("Outer Cutoff Degrees", &spot->outerCutoff, 0.01f, + 0.f, 0.7f); + } +} +*/ + +void staticactor_gui(struct mStaticActor *sa) +{ + object_gui(&sa->obj); + if (ImGui::CollapsingHeader("Model")) { + ImGui::Checkbox("Cast Shadows", &sa->castShadows); + ImGui::Text("Model path", &sa->currentModelPath); + + ImGui::SameLine(); + if (ImGui::Button("Load model")) { + //asset_command = set_new_model; + curActor = sa; + } + + } +} + +void trans_drawgui(struct mTransform *T) +{ + /*ImGui::DragFloat3("Position", (float *) &T->position, 0.01f, -1000.f, + 1000.f, "%4.2f"); + ImGui::DragFloat("Rotation", (float *) &T->rotation[0] , 0.5f, 0.f, + 360.f, "%4.2f"); */ + + ImGui::DragFloat("Scale", (float *) &T->scale, 0.001f, 0.f, 1000.f, + "%3.1f"); +} + +void object_gui(struct mGameObject *go) +{ + float temp_pos[2]; + temp_pos[0] = cpBodyGetPosition(go->body).x; + temp_pos[1] = cpBodyGetPosition(go->body).y; + + draw_point(temp_pos[0], temp_pos[1], 3); + + ImGui::DragFloat2("Position", (float *) temp_pos, 1.f, 0.f, 0.f, + "%.0f"); + + cpVect tvect = { temp_pos[0], temp_pos[1] }; + cpBodySetPosition(go->body, tvect); + + float mtry = cpBodyGetAngle(go->body); + float modtry = fmodf(mtry * RAD2DEGS, 360.f); + float modtry2 = modtry; + ImGui::DragFloat("Angle", &modtry, 0.5f, -1000.f, 1000.f, "%3.1f"); + modtry -= modtry2; + cpBodySetAngle(go->body, mtry + (modtry * DEG2RADS)); + + ImGui::DragFloat("Scale", &go->scale, 0.001f, 0.f, 1000.f, "%3.3f"); + + if (ImGui::Button("Start")) { + + } + + ImGui::SameLine(); + if (ImGui::Button("Update")) { + + } + + ImGui::SameLine(); + if (ImGui::Button("Fixed Update")) { + + } + + ImGui::SameLine(); + if (ImGui::Button("End")) { + + } + + ImGui::RadioButton("Static", (int *) &go->bodytype, + (int) CP_BODY_TYPE_STATIC); + ImGui::SameLine(); + ImGui::RadioButton("Dynamic", (int *) &go->bodytype, + (int) CP_BODY_TYPE_DYNAMIC); + ImGui::SameLine(); + ImGui::RadioButton("Kinematic", (int *) &go->bodytype, + (int) CP_BODY_TYPE_KINEMATIC); + + cpBodySetType(go->body, go->bodytype); + + if (go->bodytype == CP_BODY_TYPE_DYNAMIC) { + ImGui::DragFloat("Mass", &go->mass, 0.01f, 0.01f, 1000.f); + cpBodySetMass(go->body, go->mass); + } + + ImGui::DragFloat("Friction", &go->f, 0.01f, 0.f, 10.f); + ImGui::DragFloat("Elasticity", &go->e, 0.01f, 0.f, 2.f); + + int n = -1; + + for (int i = 0; i < go->components->len; i++) { + ImGui::PushID(i); + + struct component *c = + (struct component *) vec_get(go->components, i); + + if (c->draw_debug) + c->draw_debug(c->data); + + if (ImGui::CollapsingHeader(c->name)) { + if (ImGui::Button("Del")) { + n = i; + } + + c->draw_gui(c->data); + + + } + + end: + + + + ImGui::PopID(); + } + + if (n >= 0) + gameobject_delcomponent(go, n); +} + + +void sprite_gui(struct mSprite *sprite) +{ + + //ImGui::Text("Path", sprite->tex->path); + //ImGui::SameLine(); + if (ImGui::Button("Load texture") && selected_asset != NULL) { + sprite_loadtex(sprite, selected_asset->filename); + } + + if (sprite->tex != NULL) { + ImGui::Text("%s", sprite->tex->path); + ImGui::Text("%dx%d", sprite->tex->width, sprite->tex->height); + if (ImGui::ImageButton + ((void *) (intptr_t) sprite->tex->id, ImVec2(50, 50))) { + editor_selectasset_str(sprite->tex->path); + } + } + + ImGui::DragFloat2("Sprite Position", (float *) sprite->pos, 0.01f, + -1.f, 0.f); + + if (ImGui::Button("C")) { + sprite->pos[0] = -0.5f; + sprite->pos[1] = -0.5f; + } + + ImGui::SameLine(); + if (ImGui::Button("U")) { + sprite->pos[0] = -0.5f; + sprite->pos[1] = -1.f; + } + + ImGui::SameLine(); + if (ImGui::Button("D")) { + sprite->pos[0] = -0.5f; + sprite->pos[1] = 0.f; + } + +} + +void circle_gui(struct phys2d_circle *circle) +{ + + ImGui::DragFloat("Radius", &circle->radius, 1.f, 1.f, 10000.f); + ImGui::DragFloat2("Offset", circle->offset, 1.f, 0.f, 0.f); + + phys2d_applycircle(circle); + + + +} + +void segment_gui(struct phys2d_segment *seg) +{ + + ImGui::DragFloat2("a", seg->a, 1.f, 0.f, 0.f); + ImGui::DragFloat2("b", seg->b, 1.f, 0.f, 0.f); + + phys2d_applyseg(seg); + + + +} + +void box_gui(struct phys2d_box *box) +{ + + ImGui::DragFloat("Width", &box->w, 1.f, 0.f, 1000.f); + ImGui::DragFloat("Height", &box->h, 1.f, 0.f, 1000.f); + ImGui::DragFloat2("Offset", box->offset, 1.f, 0.f, 0.f); + ImGui::DragFloat("Radius", &box->r, 1.f, 0.f, 100.f); + + phys2d_applybox(box); + + + +} + +void poly_gui(struct phys2d_poly *poly) +{ + + if (ImGui::Button("Add Poly Vertex")) + phys2d_polyaddvert(poly); + + for (int i = 0; i < poly->n; i++) { + ImGui::PushID(i); + ImGui::DragFloat2("P", &poly->points[i * 2], 1.f, 0.f, 0.f); + ImGui::PopID(); + } + + ImGui::DragFloat("Radius", &poly->radius); + + phys2d_applypoly(poly); + + + + +} + +void edge_gui(struct phys2d_edge *edge) +{ + + if (ImGui::Button("Add Edge Vertex")) + phys2d_edgeaddvert(edge); + + for (int i = 0; i < edge->n; i++) { + ImGui::PushID(i); + ImGui::DragFloat2("E", &edge->points[i * 2], 1.f, 0.f, 0.f); + ImGui::PopID(); + } + + ImGui::DragFloat("Thickness", &edge->thickness); + + phys2d_applyedge(edge); + + + +} + +void editor_makenewobject() +{ + +} + +int obj_gui_hierarchy(struct mGameObject *selected) +{ + for (int i = 0; i < gameobjects->len; i++) { + struct mGameObject *go = + (struct mGameObject *) vec_get(gameobjects, i); + if (ImGui::Selectable(go->editor.mname, go == selected, 1 << 22)) { + if (go != selected) + pickGameObject(i); + } + } + + return 0; +} + +void get_levels() +{ + fill_extensions(levels, DATA_PATH, EXT_LEVEL); +} + +void editor_prefab_btn(char *prefab) +{ + if (ImGui::Button(prefab)) { + gameobject_makefromprefab(prefab); + /*GameObject* newprefab = (GameObject*)createPrefab(*prefab); */ + /*cam_inverse_goto(&camera, &newprefab->transform); */ + } + +} + +void game_start() +{ + physOn = 1; +} + +void game_resume() +{ + physOn = 1; +} + +void game_stop() +{ + physOn = 0; +} + +void game_pause() +{ + physOn = 0; +} + +void pinball_flipper_gui(struct flipper *flip) +{ + ImGui::DragFloat("Angle start", &flip->angle1, 0, 360); + ImGui::DragFloat("Angle end", &flip->angle2, 0, 360); + ImGui::DragFloat("Flipper speed", &flip->flipspeed, 0, 100); +} diff --git a/source/editor/editor.h b/source/editor/editor.h new file mode 100644 index 0000000..a0861bd --- /dev/null +++ b/source/editor/editor.h @@ -0,0 +1,98 @@ +#ifndef EDITOR_H +#define EDITOR_H + +#include "config.h" +#include +#include +#include "resources.h" + + +struct mCamera; + +#define ASSET_TYPE_NULL 0 +#define ASSET_TYPE_IMAGE 1 +#define ASSET_TYPE_TEXT 2 + +struct fileasset { + char *filename; + short extension_len; + short filename_len; + bool searched; + short type; + void *data; +}; + +struct editorVars { + bool showStats; + bool showHierarchy; + bool showLighting; + bool showGameSettings; + bool showViewmode; + bool showDebugMenu; + bool showAssetMenu; + bool showREPL; + bool showExport; + bool showLevel; +}; + +struct gameproject { + char name[127]; + char path[MAXPATH]; +}; + +struct Texture; + +void pickGameObject(int pickID); +int is_allowed_extension(const char *ext); + +void editor_init(struct mSDLWindow *mwindow); +void editor_input(SDL_Event * e); +void editor_render(); +int editor_wantkeyboard(); +void editor_save(); +void editor_makenewobject(); + +void editor_project_gui(); + +void editor_init_project(struct gameproject *gp); +void editor_save_projects(); +void editor_load_projects(); +void editor_proj_select_gui(); +void editor_import_project(char *path); +void editor_make_project(char *path); + +void editor_selectasset(struct fileasset *asset); +void editor_selectasset_str(char *path); +void editor_asset_gui(struct fileasset *asset); +void editor_asset_tex_gui(struct Texture *tex); +void editor_asset_text_gui(char *text); + +void editor_level_btn(char *level); +void editor_prefab_btn(char *prefab); + +void game_start(); +void game_resume(); +void game_stop(); +void game_pause(); + +void get_levels(); + +///////// Object GUIs +void light_gui(struct mLight *light); +void pointlight_gui(struct mPointLight *light); +void spotlight_gui(struct mSpotLight *spot); +void staticactor_gui(struct mStaticActor *sa); +void trans_drawgui(struct mTransform *T); +void object_gui(struct mGameObject *go); +void sprite_gui(struct mSprite *sprite); +void circle_gui(struct phys2d_circle *circle); +void segment_gui(struct phys2d_segment *seg); +void box_gui(struct phys2d_box *box); +void poly_gui(struct phys2d_poly *poly); +void edge_gui(struct phys2d_edge *edge); +void shape_gui(struct phys2d_shape *shape); +void pinball_flipper_gui(struct flipper *flip); + +int obj_gui_hierarchy(struct mGameObject *selected); + +#endif diff --git a/source/editor/editorstate.c b/source/editor/editorstate.c new file mode 100644 index 0000000..1deb320 --- /dev/null +++ b/source/editor/editorstate.c @@ -0,0 +1,19 @@ +#include "editorstate.h" +#include + +/* +void (*asset_command)(char *asset) = print_file; + +void print_file(char *file) +{ + printf("File path: %s\n", file); +} + +void set_new_model(char *modelPath) +{ + printf("Loading new model: %s\n", modelPath); + curActor->model = GetExistingModel(modelPath); + strcpy(curActor->currentModelPath, modelPath); +} + +*/ diff --git a/source/editor/editorstate.h b/source/editor/editorstate.h new file mode 100644 index 0000000..261d504 --- /dev/null +++ b/source/editor/editorstate.h @@ -0,0 +1,10 @@ +#ifndef EDITORSTATE_H +#define EDITORSTATE_H + +void set_new_model(char *modelPath); + +extern void (*asset_command)(char *asset); + +void print_file(char *file); + +#endif diff --git a/source/engine/2dcamera.h b/source/engine/2dcamera.h new file mode 100644 index 0000000..b89e386 --- /dev/null +++ b/source/engine/2dcamera.h @@ -0,0 +1,4 @@ +#ifndef TWODCAMERA_H +#define TWODCAMERA_H + +#endif diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c new file mode 100644 index 0000000..eb61dbb --- /dev/null +++ b/source/engine/2dphysics.c @@ -0,0 +1,385 @@ +#include "2dphysics.h" + +#include "gameobject.h" +#include +#include "mathc.h" + +cpBody *ballBody = NULL; +cpSpace *space = NULL; +float phys2d_gravity = -50.f; +int physOn = 0; + +void phys2d_init() +{ + space = cpSpaceNew(); + cpSpaceSetGravity(space, cpv(0, phys2d_gravity)); +} + +void phys2d_update(float deltaT) +{ + cpSpaceStep(space, deltaT * physOn); +} + +void phys2d_apply() +{ + cpSpaceSetGravity(space, cpv(0, phys2d_gravity)); +} + +void phys2d_shape_apply(struct phys2d_shape *shape) +{ + cpShapeSetFriction(shape->shape, shape->go->f); + cpShapeSetElasticity(shape->shape, shape->go->e); +} + +void init_phys2dshape(struct phys2d_shape *shape, struct mGameObject *go) +{ + shape->go = go; + phys2d_shape_apply(shape); +} + +struct phys2d_circle *Make2DCircle(struct mGameObject *go) +{ + struct phys2d_circle *new = malloc(sizeof(struct phys2d_circle)); + + new->radius = 10.f; + new->offset[0] = 0.f; + new->offset[1] = 0.f; + phys2d_circleinit(new, go); + + return new; +} + +void phys2d_circleinit(struct phys2d_circle *circle, + struct mGameObject *go) +{ + circle->shape.shape = + cpSpaceAddShape(space, + cpCircleShapeNew(go->body, circle->radius, + cpvzero)); + init_phys2dshape(&circle->shape, go); +} + +struct phys2d_segment *Make2DSegment(struct mGameObject *go) +{ + struct phys2d_segment *new = malloc(sizeof(struct phys2d_segment)); + + new->thickness = 1.f; + new->a[0] = 0.f; + new->a[1] = 0.f; + new->b[0] = 0.f; + new->b[1] = 0.f; + phys2d_seginit(new, go); + + return new; +} + +void phys2d_seginit(struct phys2d_segment *seg, struct mGameObject *go) +{ + seg->shape.shape = + cpSpaceAddShape(space, + cpSegmentShapeNew(go->body, cpvzero, cpvzero, + seg->thickness)); + init_phys2dshape(&seg->shape, go); +} + +struct phys2d_box *Make2DBox(struct mGameObject *go) +{ + struct phys2d_box *new = malloc(sizeof(struct phys2d_box)); + + new->w = 50.f; + new->h = 50.f; + new->r = 0.f; + new->offset[0] = 0.f; + new->offset[1] = 0.f; + + phys2d_boxinit(new, go); + + return new; +} + +void phys2d_boxinit(struct phys2d_box *box, struct mGameObject *go) +{ + cpVect verts[4] = + { { -5.f, -5.f }, { 5.f, -5.f }, { 5.f, 5.f }, { -5.f, 5.f } }; + cpTransform T = { 0 }; + box->shape.shape = + cpSpaceAddShape(space, + cpBoxShapeNew(go->body, box->w, box->h, box->r)); + init_phys2dshape(&box->shape, go); + phys2d_applybox(box); +} + +struct phys2d_poly *Make2DPoly(struct mGameObject *go) +{ + struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly)); + + new->n = 0; + new->points = NULL; + new->radius = 0.f; + + phys2d_polyinit(new, go); + + return new; +} + +void phys2d_polyinit(struct phys2d_poly *poly, struct mGameObject *go) +{ + cpTransform T = { 0 }; + poly->shape.shape = + cpSpaceAddShape(space, + cpPolyShapeNew(go->body, 0, NULL, T, + poly->radius)); + init_phys2dshape(&poly->shape, go); + phys2d_applypoly(poly); +} + +void phys2d_polyaddvert(struct phys2d_poly *poly) +{ + poly->n++; + float *oldpoints = poly->points; + poly->points = calloc(2 * poly->n, sizeof(float)); + memcpy(poly->points, oldpoints, sizeof(float) * 2 * (poly->n - 1)); + free(oldpoints); +} + +struct phys2d_edge *Make2DEdge(struct mGameObject *go) +{ + struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge)); + + new->n = 2; + new->points = calloc(2 * 2, sizeof(float)); + new->thickness = 0.f; + new->shapes = malloc(sizeof(cpShape *)); + + phys2d_edgeinit(new, go); + + return new; +} + +void phys2d_edgeinit(struct phys2d_edge *edge, struct mGameObject *go) +{ + edge->shapes[0] = + cpSpaceAddShape(space, + cpSegmentShapeNew(go->body, cpvzero, cpvzero, + edge->thickness)); + edge->shape.go = go; + phys2d_edgeshapeapply(&edge->shape, edge->shapes[0]); + + + + phys2d_applyedge(edge); +} + +void phys2d_edgeshapeapply(struct phys2d_shape *mshape, cpShape * shape) +{ + cpShapeSetFriction(shape, mshape->go->f); + cpShapeSetElasticity(shape, mshape->go->e); +} + +void phys2d_edgeaddvert(struct phys2d_edge *edge) +{ + edge->n++; + float *oldp = edge->points; + edge->points = calloc(edge->n * 2, sizeof(float)); + memcpy(edge->points, oldp, sizeof(float) * 2 * (edge->n - 1)); + + cpShape **oldshapes = edge->shapes; + edge->shapes = malloc(sizeof(cpShape *) * (edge->n - 1)); + memcpy(edge->shapes, oldshapes, sizeof(cpShape *) * (edge->n - 2)); + cpVect a = + { edge->points[(edge->n - 2) * 2], + edge->points[(edge->n - 2) * 2 + 1] }; + cpVect b = + { edge->points[(edge->n - 1) * 2], + edge->points[(edge->n - 1) * 2 + 1] }; + edge->shapes[edge->n - 2] = + cpSpaceAddShape(space, + cpSegmentShapeNew(edge->shape.go->body, a, b, + edge->thickness)); + phys2d_edgeshapeapply(&edge->shape, edge->shapes[edge->n - 2]); + + free(oldp); + free(oldshapes); +} + +#include "debugdraw.h" +#include "gameobject.h" +#include +#include + +void phys2d_applycircle(struct phys2d_circle *circle) +{ + float radius = circle->radius * circle->shape.go->scale; + float s = circle->shape.go->scale; + cpVect offset = { circle->offset[0] * s, circle->offset[1] * s }; + + cpCircleShapeSetRadius(circle->shape.shape, radius); + cpCircleShapeSetOffset(circle->shape.shape, offset); + cpBodySetMoment(circle->shape.go->body, + cpMomentForCircle(circle->shape.go->mass, 0, radius, + offset)); +} + +void phys2d_applyseg(struct phys2d_segment *seg) +{ + float s = seg->shape.go->scale; + cpVect a = { seg->a[0] * s, seg->a[1] * s }; + cpVect b = { seg->b[0] * s, seg->b[1] * s }; + cpSegmentShapeSetEndpoints(seg->shape.shape, a, b); + cpSegmentShapeSetRadius(seg->shape.shape, seg->thickness * s); +} + +void phys2d_applybox(struct phys2d_box *box) +{ + float s = box->shape.go->scale; + cpTransform T = { 0 }; + T.a = s; + T.d = s; + T.tx = box->offset[0] * s; + T.ty = box->offset[1] * s; + float hh = box->h / 2.f; + float hw = box->w / 2.f; + cpVect verts[4] = + { { -hw, -hh }, { hw, -hh }, { hw, hh }, { -hw, hh } }; + cpPolyShapeSetVerts(box->shape.shape, 4, verts, T); + cpPolyShapeSetRadius(box->shape.shape, box->r); +} + +void phys2d_applypoly(struct phys2d_poly *poly) +{ + cpVect verts[poly->n]; + + for (int i = 0; i < poly->n; i++) { + verts[i].x = poly->points[i * 2]; + verts[i].y = poly->points[i * 2 + 1]; + } + + CP_CONVEX_HULL(poly->n, verts, hullCount, hullVerts); + + float s = poly->shape.go->scale; + cpTransform T = { 0 }; + T.a = s; + T.d = s; + + cpPolyShapeSetVerts(poly->shape.shape, hullCount, hullVerts, T); + cpPolyShapeSetRadius(poly->shape.shape, poly->radius); +} + +void phys2d_applyedge(struct phys2d_edge *edge) +{ + float s = edge->shape.go->scale; + + for (int i = 0; i < edge->n - 1; i++) { + cpVect a = + { edge->points[i * 2] * s, edge->points[i * 2 + 1] * s }; + cpVect b = + { edge->points[i * 2 + 2] * s, edge->points[i * 2 + 3] * s }; + cpSegmentShapeSetEndpoints(edge->shapes[i], a, b); + cpSegmentShapeSetRadius(edge->shapes[i], edge->thickness); + } +} + +void phys2d_dbgdrawcircle(struct phys2d_circle *circle) +{ + cpVect p = cpBodyGetPosition(circle->shape.go->body); + cpVect o = cpCircleShapeGetOffset(circle->shape.shape); + float d = sqrt(pow(o.x, 2.f) + pow(o.y, 2.f)); + float a = atan2(o.y, o.x) + cpBodyGetAngle(circle->shape.go->body); + draw_circle(p.x + (d * cos(a)), p.y + (d * sin(a)), + cpCircleShapeGetRadius(circle->shape.shape), 1); +} + +void phys2d_dbgdrawseg(struct phys2d_segment *seg) +{ + cpVect p = cpBodyGetPosition(seg->shape.go->body); + float s = seg->shape.go->scale; + cpVect a = cpSegmentShapeGetA(seg->shape.shape); + cpVect b = cpSegmentShapeGetB(seg->shape.shape); + + float angle = cpBodyGetAngle(seg->shape.go->body); + float ad = sqrt(pow(a.x, 2.f) + pow(a.y, 2.f)); + float bd = sqrt(pow(b.x, 2.f) + pow(b.y, 2.f)); + float aa = atan2(a.y, a.x) + angle; + float ba = atan2(b.y, b.x) + angle; + draw_line(ad * cos(aa) + p.x, ad * sin(aa) + p.y, bd * cos(ba) + p.x, + bd * sin(ba) + p.y); +} + +void phys2d_dbgdrawbox(struct phys2d_box *box) +{ + int n = cpPolyShapeGetCount(box->shape.shape); + cpVect b = cpBodyGetPosition(box->shape.go->body); + float angle = cpBodyGetAngle(box->shape.go->body); + float points[n * 2]; + + for (int i = 0; i < n; i++) { + cpVect p = cpPolyShapeGetVert(box->shape.shape, i); + float d = sqrt(pow(p.x, 2.f) + pow(p.y, 2.f)); + float a = atan2(p.y, p.x) + angle; + points[i * 2] = d * cos(a) + b.x; + points[i * 2 + 1] = d * sin(a) + b.y; + } + + draw_poly(points, n); +} + +void phys2d_dbgdrawpoly(struct phys2d_poly *poly) +{ + cpVect b = cpBodyGetPosition(poly->shape.go->body); + float angle = cpBodyGetAngle(poly->shape.go->body); + + float s = poly->shape.go->scale; + for (int i = 0; i < poly->n; i++) { + float point[2]; + float d = + sqrt(pow(poly->points[i * 2] * s, 2.f) + + pow(poly->points[i * 2 + 1] * s, 2.f)); + float a = + atan2(poly->points[i * 2 + 1], poly->points[i * 2]) + angle; + draw_point(b.x + d * cos(a), b.y + d * sin(a), 3); + } + + if (poly->n >= 3) { + int n = cpPolyShapeGetCount(poly->shape.shape); + float points[n * 2]; + + for (int i = 0; i < n; i++) { + cpVect p = cpPolyShapeGetVert(poly->shape.shape, i); + float d = sqrt(pow(p.x, 2.f) + pow(p.y, 2.f)); + float a = atan2(p.y, p.x) + angle; + points[i * 2] = d * cos(a) + b.x; + points[i * 2 + 1] = d * sin(a) + b.y; + } + + draw_poly(points, n); + } + +} + +void phys2d_dbgdrawedge(struct phys2d_edge *edge) +{ + cpVect p = cpBodyGetPosition(edge->shape.go->body); + float s = edge->shape.go->scale; + float angle = cpBodyGetAngle(edge->shape.go->body); + + for (int i = 0; i < edge->n; i++) { + float point[2]; + float d = + sqrt(pow(edge->points[i * 2] * s, 2.f) + + pow(edge->points[i * 2 + 1] * s, 2.f)); + float a = + atan2(edge->points[i * 2 + 1], edge->points[i * 2]) + angle; + draw_point(p.x + d * cos(a), p.y + d * sin(a), 3); + } + + for (int i = 0; i < edge->n - 1; i++) { + cpVect a = cpSegmentShapeGetA(edge->shapes[i]); + cpVect b = cpSegmentShapeGetB(edge->shapes[i]); + float ad = sqrt(pow(a.x, 2.f) + pow(a.y, 2.f)); + float bd = sqrt(pow(b.x, 2.f) + pow(b.y, 2.f)); + float aa = atan2(a.y, a.x) + angle; + float ba = atan2(b.y, b.x) + angle; + draw_line(ad * cos(aa) + p.x, ad * sin(aa) + p.y, + bd * cos(ba) + p.x, bd * sin(ba) + p.y); + } +} diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h new file mode 100644 index 0000000..7822676 --- /dev/null +++ b/source/engine/2dphysics.h @@ -0,0 +1,90 @@ +#ifndef TWODPHYSICS_H +#define TWODPHYSICS_H + +#include + + +struct mGameObject; + +extern cpBody *ballBody; +extern float phys2d_gravity; +extern int physOn; +extern cpSpace *space; + +struct phys2d_shape { + cpShape *shape; + struct mGameObject *go; +}; + +struct phys2d_circle { + float radius; + float offset[2]; + struct phys2d_shape shape; +}; + +struct phys2d_segment { + float a[2]; + float b[2]; + float thickness; + struct phys2d_shape shape; +}; + +struct phys2d_box { + float w; + float h; + float r; + float offset[2]; + struct phys2d_shape shape; +}; + +struct phys2d_edge { + int n; + float *points; + float thickness; + cpShape **shapes; + struct phys2d_shape shape; +}; + +struct phys2d_poly { + int n; + float *points; + float radius; + struct phys2d_shape shape; +}; + +struct phys2d_circle *Make2DCircle(struct mGameObject *go); +void phys2d_circleinit(struct phys2d_circle *circle, + struct mGameObject *go); +void phys2d_applycircle(struct phys2d_circle *circle); +void phys2d_dbgdrawcircle(struct phys2d_circle *circle); + +struct phys2d_segment *Make2DSegment(struct mGameObject *go); +void phys2d_seginit(struct phys2d_segment *seg, struct mGameObject *go); +void phys2d_applyseg(struct phys2d_segment *seg); +void phys2d_dbgdrawseg(struct phys2d_segment *seg); + +struct phys2d_box *Make2DBox(struct mGameObject *go); +void phys2d_boxinit(struct phys2d_box *box, struct mGameObject *go); +void phys2d_applybox(struct phys2d_box *box); +void phys2d_dbgdrawbox(struct phys2d_box *box); + +struct phys2d_poly *Make2DPoly(struct mGameObject *go); +void phys2d_polyinit(struct phys2d_poly *poly, struct mGameObject *go); +void phys2d_applypoly(struct phys2d_poly *poly); +void phys2d_dbgdrawpoly(struct phys2d_poly *poly); +void phys2d_polyaddvert(struct phys2d_poly *poly); + +struct phys2d_edge *Make2DEdge(struct mGameObject *go); +void phys2d_edgeinit(struct phys2d_edge *edge, struct mGameObject *go); +void phys2d_applyedge(struct phys2d_edge *edge); +void phys2d_edgeshapeapply(struct phys2d_shape *mshape, cpShape * shape); +void phys2d_dbgdrawedge(struct phys2d_edge *edge); +void phys2d_edgeaddvert(struct phys2d_edge *edge); + + +void phys2d_init(); +void phys2d_update(float deltaT); +void phys2d_apply(); + + +#endif diff --git a/source/engine/3dphysics.c b/source/engine/3dphysics.c new file mode 100644 index 0000000..b46a615 --- /dev/null +++ b/source/engine/3dphysics.c @@ -0,0 +1,47 @@ +#include <3dphysics.h> + +/* +btDefaultCollisionConfiguration *collisionConfig { +NULL}; +btCollisionDispatcher *dispatcher { +NULL}; +btBroadphaseInterface *overlappingPairCache { +NULL}; +btSequentialImpulseConstraintSolver *solver { +NULL}; +btDiscreteDynamicsWorld *dynamicsWorld { +NULL}; +btRigidBody *worldFloor { +NULL}; + +void btUpdate() +{ + // dynamicsWorld->stepSimulation(deltaT); +} + +void btInit() +{ + // collisionConfig = new btDefaultCollisionConfiguration(); + // dispatcher = new btCollisionDispatcher(collisionConfig); + // overlappingPairCache = new btDbvtBroadphase(); + // solver = new btSequentialImpulseConstraintSolver; + // dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfig); + // dynamicsWorld->setGravity(btVector3(0.f, -9.8f, 0.f)); + // btDebugDrawer = new BulletDebugDrawer_OpenGL(); + // dynamicsWorld->setDebugDrawer(btDebugDrawer); + + + //btDebugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb); + // Add camera and plane to world + // dynamicsWorld->addRigidBody(camera.body); + // camera.body->setGravity(btVector3(0.f, 0.f, 0.f)); + + // Create and add plane + // btStaticPlaneShape* floorShape = new btStaticPlaneShape(btVector3(0.f, 1.f, 0.f), 0.f); + // btDefaultMotionState* motionState = new btDefaultMotionState(); + // btVector3 bodyInertia; + // btRigidBody::btRigidBodyConstructionInfo bodyCI = btRigidBody::btRigidBodyConstructionInfo(0.f, motionState, floorShape, bodyInertia); + // worldFloor = new btRigidBody(bodyCI); + // dynamicsWorld->addRigidBody(worldFloor); +} +*/ diff --git a/source/engine/3dphysics.h b/source/engine/3dphysics.h new file mode 100644 index 0000000..3d6a394 --- /dev/null +++ b/source/engine/3dphysics.h @@ -0,0 +1,4 @@ +#ifndef THREEDPHYSICS_H +#define THREEDPHYSICS_H + +#endif diff --git a/source/engine/billboard.h b/source/engine/billboard.h new file mode 100644 index 0000000..bd39495 --- /dev/null +++ b/source/engine/billboard.h @@ -0,0 +1,4 @@ +#ifndef BILLBOARD_H +#define BILLBOARD_H + +#endif diff --git a/source/engine/camera.c b/source/engine/camera.c new file mode 100644 index 0000000..b2f7e2c --- /dev/null +++ b/source/engine/camera.c @@ -0,0 +1,137 @@ +#include "camera.h" + +#include "gameobject.h" +#include "input.h" +#include + +const float CAMERA_MINSPEED = 1.f; +const float CAMERA_MAXSPEED = 300.f; +const float CAMERA_ROTATESPEED = 6.f; + +void cam_goto_object(struct mCamera *cam, struct mTransform *transform) +{ + mfloat_t fwd[3] = { 0.f }; + vec3_subtract(cam->transform.position, transform->position, + vec3_multiply_f(fwd, trans_forward(fwd, transform), + 10.f)); +} + +void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform) +{ + mfloat_t fwd[3] = { 0.f }; + vec3_add(transform->position, cam->transform.position, + vec3_multiply_f(fwd, trans_forward(fwd, &cam->transform), + 10.f)); +} + +mfloat_t *getviewmatrix(mfloat_t view[16], + const struct mCamera *const camera) +{ + mfloat_t fwd[3] = { 0.f }; + mfloat_t look[3] = { 0.f }; + vec3_rotate_quat(fwd, FORWARD, camera->transform.rotation); + vec3_add(look, camera->transform.position, fwd); + mat4_look_at(view, camera->transform.position, look, UP); + return view; + /*return mat4_look_at(view, ncam.transform.position, + vec3_add(look, ncam.transform.position, + trans_forward(fwd, &ncam.transform)), + UP); */ +} + +void camera_2d_update(struct mCamera *camera, float deltaT) +{ + static mfloat_t holdvec[3]; + static mfloat_t frame[3]; + vec3_zero(frame); + + if (currentKeystates[SDL_SCANCODE_W]) + vec3_add(frame, frame, UP); + if (currentKeystates[SDL_SCANCODE_S]) + vec3_add(frame, frame, DOWN); + if (currentKeystates[SDL_SCANCODE_A]) + vec3_add(frame, frame, LEFT); + if (currentKeystates[SDL_SCANCODE_D]) + vec3_add(frame, frame, RIGHT); + + float speedMult = currentKeystates[SDL_SCANCODE_LSHIFT] ? 2.f : 1.f; + + if (!vec3_is_zero(frame)) { + vec3_normalize(frame, frame); + vec3_add(camera->transform.position, camera->transform.position, + vec3_multiply_f(frame, frame, + camera->speed * speedMult * deltaT)); + } + +} + +/* +void camera_update(struct mCamera * camera, float mouseX, float mouseY, + const uint8_t * keystate, int32_t mouseWheelY, + float deltaTime) +{ + // if (SDL_GetRelativeMouseMode()) vec3_zero(camera->frame_move); + + static mfloat_t holdvec[VEC3_SIZE]; + vec3_zero(camera->frame_move); + + if (currentKeystates[SDL_SCANCODE_W]) + vec3_add(camera->frame_move, camera->frame_move, + trans_forward(holdvec, &camera->transform)); + + if (currentKeystates[SDL_SCANCODE_S]) + vec3_subtract(camera->frame_move, camera->frame_move, + trans_forward(holdvec, &camera->transform)); + + if (currentKeystates[SDL_SCANCODE_A]) + vec3_subtract(camera->frame_move, camera->frame_move, + trans_right(holdvec, &camera->transform)); + + if (currentKeystates[SDL_SCANCODE_D]) + vec3_add(camera->frame_move, camera->frame_move, + trans_right(holdvec, &camera->transform)); + + if (currentKeystates[SDL_SCANCODE_E]) + vec3_add(camera->frame_move, camera->frame_move, + trans_up(holdvec, &camera->transform)); + + if (currentKeystates[SDL_SCANCODE_Q]) + vec3_subtract(camera->frame_move, camera->frame_move, + trans_up(holdvec, &camera->transform)); + + camera->speedMult = currentKeystates[SDL_SCANCODE_LSHIFT] ? 2.f : 1.f; + + + if (!vec3_is_zero(camera->frame_move)) { + vec3_normalize(camera->frame_move, camera->frame_move); + vec3_add(camera->transform.position, camera->transform.position, + vec3_multiply_f(camera->frame_move, camera->frame_move, + camera->speed * camera->speedMult * + deltaTime)); + } + // Adjust speed based on mouse wheel + camera->speed = + clampf(camera->speed + mouseWheelY, CAMERA_MINSPEED, + CAMERA_MAXSPEED); + + + // TODO: Handle this as additive quaternions + + camera->yaw -= mouseX * CAMERA_ROTATESPEED * deltaTime; + camera->pitch -= mouseY * CAMERA_ROTATESPEED * deltaTime; + + + if (camera->pitch > 89.f) + camera->pitch = 89.f; + if (camera->pitch < -89.f) + camera->pitch = -89.f; + + mfloat_t qyaw[4] = {0.f}; + mfloat_t qpitch[4] = {0.f}; + + quat_from_axis_angle(qyaw, UP, camera->yaw); + quat_from_axis_angle(qpitch, RIGHT, camera->pitch); + quat_multiply(camera->transform.rotation, qyaw, qpitch); + +} +*/ diff --git a/source/engine/camera.h b/source/engine/camera.h new file mode 100644 index 0000000..eea9122 --- /dev/null +++ b/source/engine/camera.h @@ -0,0 +1,24 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include "transform.h" + +extern const float CAMERA_MINSPEED; +extern const float CAMERA_MAXSPEED; +extern const float CAMERA_ROTATESPEED; + +struct mCamera { + struct mTransform transform; + float speed; + float speedMult; + mfloat_t frame_move[VEC3_SIZE]; +}; + +void camera_2d_update(struct mCamera *camera, float deltaT); + +mfloat_t *getviewmatrix(mfloat_t view[MAT4_SIZE], + const struct mCamera *const camera); +void cam_goto_object(struct mCamera *cam, struct mTransform *transform); +void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform); + +#endif diff --git a/source/engine/component.h b/source/engine/component.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/source/engine/component.h @@ -0,0 +1 @@ +#pragma once diff --git a/source/engine/config.h b/source/engine/config.h new file mode 100644 index 0000000..2e662ff --- /dev/null +++ b/source/engine/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + + +#define MAXPATH 256 /* 255 chars + null */ +#define MAXNAME 50 + + + +#define SCREEN_WIDTH 1280 +#define SCREEN_HEIGHT 720 +#define PI 3.14159265358979323846264338327950288f +#define DEG2RADS 0.0174532925199432957692369076848861271344287188854172545609719144f +#define RAD2DEGS 57.2958f +#define MSAA_SAMPLES 2 + + +#endif \ No newline at end of file diff --git a/source/engine/datastream.c b/source/engine/datastream.c new file mode 100644 index 0000000..3e22802 --- /dev/null +++ b/source/engine/datastream.c @@ -0,0 +1,173 @@ +#include "datastream.h" + +#include + +#include "config.h" +#include "shader.h" +#include "resources.h" +#include +#include + +static void ds_update_texture(uint32_t unit, uint32_t texture, + plm_plane_t * plane) +{ + glActiveTexture(unit); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, plane->width, plane->height, 0, + GL_RED, GL_UNSIGNED_BYTE, plane->data); +} + +static void render_frame(plm_t * mpeg, plm_frame_t * frame, void *user) +{ + struct datastream *ds = user; + shader_use(ds->shader); + ds_update_texture(GL_TEXTURE0, ds->texture_y, &frame->y); + ds_update_texture(GL_TEXTURE1, ds->texture_cb, &frame->cb); + ds_update_texture(GL_TEXTURE2, ds->texture_cr, &frame->cr); +} + +static void render_audio(plm_t * mpeg, plm_samples_t * samples, void *user) +{ + struct datastream *ds = (struct datastream *) user; + int size = sizeof(float) * samples->count * 2; + SDL_QueueAudio(ds->audio_device, samples->interleaved, size); +} + +void ds_openvideo(struct datastream *ds, const char *video, + const char *adriver) +{ + ds_stop(ds); + char buf[MAXPATH] = {'\0'}; + sprintf(buf, "%s%s", DATA_PATH, video); + ds->plm = plm_create_with_filename(buf); + + if (!ds->plm) { + SDL_Log("Couldn't open %s", video); + } + + int samplerate = plm_get_samplerate(ds->plm); + + SDL_Log("Opened %s - framerate: %f, samplerate: %d, duration: %f", + video, + plm_get_framerate(ds->plm), + plm_get_samplerate(ds->plm), plm_get_duration(ds->plm) + ); + + plm_set_video_decode_callback(ds->plm, render_frame, ds); + plm_set_audio_decode_callback(ds->plm, render_audio, ds); + plm_set_loop(ds->plm, false); + + plm_set_audio_enabled(ds->plm, true); + plm_set_audio_stream(ds->plm, 0); + SDL_AudioSpec audio_spec; + SDL_memset(&audio_spec, 0, sizeof(audio_spec)); + audio_spec.freq = samplerate; + audio_spec.format = AUDIO_F32; + audio_spec.channels = 2; + audio_spec.samples = 4096; + + ds->audio_device = + SDL_OpenAudioDevice(adriver, 0, &audio_spec, NULL, 0); + printf("Opened audio device %d on driver %s\n", ds->audio_device, + adriver); + // if (audio_device == 0) { + // SDL_Log("Failed to open audio device: %s", SDL_GetError()); + // } + SDL_PauseAudioDevice(ds->audio_device, 0); + + + + + // Adjust the audio lead time according to the audio_spec buffer size + //plm_set_audio_lead_time(plm, (double)audio_spec.samples / (double)samplerate); + + ds->playing = true; +} + +struct datastream *MakeDatastream(struct mShader *shader) +{ + struct datastream *newds = + (struct datastream *) malloc(sizeof(struct datastream)); + newds->shader = shader; + shader_use(newds->shader); + glGenTextures(1, &newds->texture_y); + glBindTexture(GL_TEXTURE_2D, newds->texture_y); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + shader_setint(newds->shader, "texture_y", 0); + + glGenTextures(1, &newds->texture_cb); + glBindTexture(GL_TEXTURE_2D, newds->texture_cb); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + shader_setint(newds->shader, "texture_cb", 1); + + glGenTextures(1, &newds->texture_cr); + glBindTexture(GL_TEXTURE_2D, newds->texture_cr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + shader_setint(newds->shader, "texture_cr", 2); + + return newds; +} + +void ds_advance(struct datastream *ds, uint32_t ms) +{ + if (ds->playing) { + double advanceTime = ms / 1000.f; + plm_decode(ds->plm, advanceTime); + } +} + +void ds_seek(struct datastream *ds, uint32_t time) +{ + SDL_ClearQueuedAudio(0); + plm_seek(ds->plm, time, false); +} + +void ds_fwdframes(struct datastream *ds, int frames) +{ + for (int i = 0; i < frames; i++) { + plm_frame_t *frame = plm_decode_video(ds->plm); + render_frame(ds->plm, frame, ds); + } +} + + + +void ds_pause(struct datastream *ds) +{ + ds->playing = false; +} + +void ds_stop(struct datastream *ds) +{ + if (ds->plm != NULL) { + plm_destroy(ds->plm); + ds->plm = NULL; + } + if (ds->audio_device) + SDL_CloseAudioDevice(ds->audio_device); + ds->playing = false; +} + +// TODO: Must be a better way +int ds_videodone(struct datastream *ds) +{ + return (ds->plm == NULL) + || plm_get_time(ds->plm) >= plm_get_duration(ds->plm); +} + +double ds_remainingtime(struct datastream *ds) +{ + if (ds->plm != NULL) + return plm_get_duration(ds->plm) - plm_get_time(ds->plm); + else + return 0.f; +} diff --git a/source/engine/datastream.h b/source/engine/datastream.h new file mode 100644 index 0000000..1dced35 --- /dev/null +++ b/source/engine/datastream.h @@ -0,0 +1,30 @@ +#ifndef DATASTREAM_H +#define DATASTREAM_H + +#include + +typedef struct plm_t plm_t; + + +struct datastream { + plm_t *plm; + struct mShader *shader; + double last_time; + int playing; + SDL_AudioDeviceID audio_device; + uint32_t texture_y; + uint32_t texture_cb; + uint32_t texture_cr; +}; + +struct datastream *MakeDatastream(struct mShader *shader); +void ds_openvideo(struct datastream *ds, const char *path, + const char *adriver); +void ds_advance(struct datastream *ds, uint32_t ms); +void ds_seek(struct datastream *ds, uint32_t time); +void ds_pause(struct datastream *ds); +void ds_stop(struct datastream *ds); +int ds_videodone(struct datastream *ds); +double ds_remainingtime(struct datastream *ds); + +#endif diff --git a/source/engine/engine.c b/source/engine/engine.c new file mode 100644 index 0000000..ecbb17b --- /dev/null +++ b/source/engine/engine.c @@ -0,0 +1,122 @@ +#define PL_MPEG_IMPLEMENTATION +#define CGLTF_IMPLEMENTATION +#define GL_GLEXT_PROTOTYPES + +//#define MATHC_USE_INT16 +//#define MATHC_FLOATING_POINT_TYPE GLfloat +//#define MATHC_USE_DOUBLE_FLOATING_POINT + +#define STB_DS_IMPLEMENTATION +#include + +#define STB_IMAGE_IMPLEMENTATION +#include + +#include + +#ifdef EDITOR +#include "editor.h" +#endif + +#include +#include "openglrender.h" +#include "window.h" +#include "camera.h" +#include "input.h" +#include "sprite.h" +#include "2dphysics.h" +#include "gameobject.h" +#include "registry.h" + +#define FPS30 33 +#define FPS60 17 +#define FPS120 8; +#define FPS144 7 +#define FPS300 3 + +unsigned int frameCount = 0; +Uint32 lastTick = 0; +Uint32 frameTick = 0; +Uint32 elapsed = 0; + +Uint32 physMS = FPS144; +Uint32 physlag = 0; +Uint32 renderMS = FPS144; +Uint32 renderlag = 0; + + + +int main(int argc, char **args) +{ + + script_init(); + + registry_init(); + gameobjects = vec_make(sizeof(struct mGameObject), 100); + prefabs = vec_make(MAXNAME, 25); + + // TODO: Init these on the heap instead + struct mCamera camera = { 0 }; + camera.speed = 500; + + stbi_set_flip_vertically_on_load(1); + + resources_init(); + openglInit(); + sprite_initialize(); + +#ifdef EDITOR + editor_init(window); +#endif + + phys2d_init(); + + quit = false; + SDL_Event e; + + //While application is running + while (!quit) { + frameTick = SDL_GetTicks(); + elapsed = frameTick - lastTick; + lastTick = frameTick; + deltaT = elapsed / 1000.f; + + physlag += elapsed; + renderlag += elapsed; + + input_poll(); + + if (physlag >= physMS) { + phys2d_update(physMS / 1000.f); + + physlag -= physMS; + } + + + if (renderlag >= renderMS) { + if (physOn) { + vec_walk(gameobjects, gameobject_update); + } + + + camera_2d_update(&camera, renderMS / 1000.f); + + openglRender(&camera); + + +#ifdef EDITOR + editor_render(); +#endif + + window_swap(window); + + renderlag -= renderMS; + } + } + + + SDL_StopTextInput(); + SDL_Quit(); + + return 0; +} diff --git a/source/engine/font.c b/source/engine/font.c new file mode 100644 index 0000000..0345ae3 --- /dev/null +++ b/source/engine/font.c @@ -0,0 +1,240 @@ +#include "font.h" + +#include +#include +#include +#include +#include +#include + + +#define STB_TRUETYPE_IMPLEMENTATION +#include + +static struct Character Characters[127] = { '\0' }; + +static uint32_t VBO = 0; +static uint32_t VAO = 0; + +unsigned char ttf_buffer[24 << 20]; +unsigned char temp_bitmap[512 * 512]; + +struct sFont MakeFont(const char *fontfile, int height) +{ + struct sFont newfont = { 0 }; + newfont.height = height; + + char fontpath[256]; + snprintf(fontpath, 256, "fonts/%s", fontfile); + + stbtt_fontinfo fontinfo = { 0 }; + int i, j, ascent, baseline, ch = 0; + + stbtt_InitFont(&fontinfo, ttf_buffer, 0); + stbtt_GetFontVMetrics(&fontinfo, &ascent, 0, 0); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + for (unsigned char c = 0; c < 128; c++) { + unsigned char *bitmap; + int advance, lsb, w, h; + stbtt_GetCodepointHMetrics(&fontinfo, c, &advance, &lsb); + bitmap = + stbtt_GetCodepointBitmap(&fontinfo, 0, + stbtt_ScaleForPixelHeight(&fontinfo, + newfont. + height), c, + &w, &h, 0, 0); + + GLuint ftexture; + glGenTextures(1, &ftexture); + glBindTexture(GL_TEXTURE_2D, ftexture); + glTexImage2D(GL_TEXTURE_2D, + 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, bitmap); + + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + + Characters[c].TextureID = ftexture; + Characters[c].Advance = advance; + Characters[c].Size[0] = w; + Characters[c].Size[1] = h; + Characters[c].Bearing[0] = lsb; + Characters[c].Bearing[1] = 0; + } + + // configure VAO/VBO for texture quads + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4, NULL, + GL_DYNAMIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + return newfont; + + +} + +void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, + struct mShader *shader, float color[3]) +{ + float xpos = cursor[0] + c.Bearing[0] * scale; + float ypos = cursor[1] - (c.Size[1] - c.Bearing[1]) * scale; + + float w = c.Size[0] * scale; + float h = c.Size[1] * scale; + + float verts[4 * 4] = { + xpos, ypos + h, 0.f, 0.f, + xpos, ypos, 0.f, 1.f, + xpos + w, ypos + h, 1.f, 0.f, + xpos + w, ypos, 1.f, 1.f + }; + + // float outlineWidth = 1.1; + + // float ow = c.Size[0] * scale * outlineWidth; + // float oh = c.Size[1] * scale * outlineWidth; + + // float oxpos = cursor[0] + c.Bearing[0] * scale * outlineWidth - ((ow-w)/2); + // float oypos = cursor[1] - (c.Size[1] - c.Bearing[1]) * scale * outlineWidth - ((oh-h)/2); + + + + // float overts[4*4] = { + // oxpos, oypos + oh, 0.f, 0.f, + // oxpos, oypos, 0.f, 1.f, + // oxpos + ow, oypos + oh, 1.f, 0.f, + // oxpos + ow, oypos, 1.f, 1.f + // }; + + float shadowOffset = 6.f; + float sxpos = + cursor[0] + c.Bearing[0] * scale + (scale * shadowOffset); + float sypos = + cursor[1] - (c.Size[1] - c.Bearing[1]) * scale - + (scale * shadowOffset); + + float sverts[4 * 4] = { + sxpos, sypos + h, 0.f, 0.f, + sxpos, sypos, 0.f, 1.f, + sxpos + w, sypos + h, 1.f, 0.f, + sxpos + w, sypos, 1.f, 1.f + }; + + + glBindTexture(GL_TEXTURE_2D, c.TextureID); + + //// Shadow pass + float black[3] = { 0, 0, 0 }; + shader_setvec3(shader, "textColor", black); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(sverts), sverts); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + //// Outline pass + + + + shader_setvec3(shader, "textColor", color); + + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + +} + +void renderText(struct sFont font, struct mShader *shader, + const char *text, mfloat_t pos[2], float scale, + mfloat_t color[3], float lw) +{ + shader_use(shader); + shader_setvec3(shader, "textColor", color); + + mfloat_t cursor[2] = { 0.f }; + cursor[0] = pos[0]; + cursor[1] = pos[1]; + + glActiveTexture(GL_TEXTURE0); + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + + char modText[sizeof(*text)]; + strcpy(modText, text); + + char *line, *wordstart; + line = strtok(modText, "\n"); + + while (line != NULL) { + cursor[0] = pos[0]; + + int wordWidth = 0; + + // iterate through all characters + while (*line != '\0') { + + wordstart = line; + if (!isspace(*line)) { + struct Character ch = Characters[*line]; + + if (lw > 0 + && (cursor[0] + ((ch.Advance >> 6) * scale) - pos[0] >= + lw)) { + cursor[0] = pos[0]; + cursor[1] -= scale * font.height; + + } else { + // now advance cursors for next glyph (note that advance is number of 1/64 pixels) + cursor[0] += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + } + + sdrawCharacter(ch, cursor, scale, shader, color); + ++line; + } else { + while (!isspace(*line) || *line != '\0') { // Seek line to the end of the word + ++line; + wordWidth += (Characters[*line].Advance >> 6) * scale; + } + + // Now wordStart and stringPos surround the word, go through them. If the word that's about to be drawn goes past the line width, go to next line + if (lw > 0 && (cursor[0] + wordWidth - pos[0] >= lw)) { + cursor[0] = pos[0]; + cursor[1] -= scale * font.height; + } + + while (wordstart < line) { // Go through + + + struct Character ch = Characters[*wordstart]; + sdrawCharacter(Characters[*wordstart], cursor, scale, + shader, color); + + cursor[0] += (ch.Advance >> 6) * scale; + ++wordstart; + } + } + + + + } + cursor[1] -= scale * font.height; + + line = strtok(NULL, "\n"); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); +} diff --git a/source/engine/font.h b/source/engine/font.h new file mode 100644 index 0000000..1b18eaa --- /dev/null +++ b/source/engine/font.h @@ -0,0 +1,29 @@ +#ifndef FONT_H +#define FONT_H + +#include "mathc.h" + +struct mShader; + +/// Holds all state information relevant to a character as loaded using FreeType +struct Character { + uint32_t TextureID; // ID handle of the glyph texture + mfloat_t Size[2]; // Size of glyph + mfloat_t Bearing[2]; // Offset from baseline to left/top of glyph + unsigned int Advance; // Horizontal offset to advance to next glyph +}; + +struct sFont { + uint32_t fontTexture; + uint32_t height; +}; + +struct sFont MakeFont(const char *fontfile, int height); +void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, + struct mShader *shader, float color[3]); +void renderText(struct sFont font, struct mShader *shader, + const char *text, mfloat_t pos[2], float scale, + mfloat_t color[3], float lw); + + +#endif diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c new file mode 100644 index 0000000..51e795f --- /dev/null +++ b/source/engine/gameobject.c @@ -0,0 +1,200 @@ +#include "gameobject.h" + +#include "shader.h" +#include "sprite.h" +#include "registry.h" +#include "2dphysics.h" +#include "script.h" +#include "vec.h" +#include "input.h" +#include +#include + +struct vec *gameobjects = NULL; +struct mGameObject *updateGO = NULL; + +const int nameBuf[MAXNAME] = { 0 }; +const int prefabNameBuf[MAXNAME] = { 0 }; + +struct mGameObject *get_gameobject_from_id(int id) +{ + return vec_get(gameobjects, id - 1); +} + +static void gameobject_setpickcolor(struct mGameObject *go) +{ + float r = ((go->editor.id & 0x000000FF) >> 0) / 255.f; + float g = ((go->editor.id & 0x0000FF00) >> 8) / 255.f; + float b = ((go->editor.id & 0x00FF0000) >> 16) / 255.f; + + go->editor.color[0] = r; + go->editor.color[1] = g; + go->editor.color[2] = b; +} + +struct mGameObject *MakeGameobject() +{ + struct mGameObject *go = vec_add(gameobjects, NULL); + go->editor.id = gameobjects->len - 1; + go->transform.scale = 1.f; + gameobject_setpickcolor(go); + strncpy(go->editor.mname, "New object", MAXNAME); + go->scale = 1.f; + go->bodytype = CP_BODY_TYPE_STATIC; + go->mass = 1.f; + go->body = cpSpaceAddBody(space, cpBodyNew(go->mass, 1.f)); + + go->components = vec_make(sizeof(struct component), 10); + + return go; +} + +void gameobject_addcomponent(struct mGameObject *go, struct component *c) +{ + struct component *newc = vec_add(go->components, c); + newc->go = go; + newc->data = newc->make(newc->go); +} + +void gameobject_delete(int id) +{ + vec_delete(gameobjects, id); +} + +void gameobject_delcomponent(struct mGameObject *go, int n) +{ + vec_del_order(go->components, n); +} + +void setup_model_transform(struct mTransform *t, struct mShader *s, + float scale) +{ + mfloat_t modelT[16] = { 0.f }; + mfloat_t matbuff[16] = { 0.f }; + memcpy(modelT, UNITMAT4, sizeof(modelT)); + mat4_translate_vec3(modelT, t->position); + mat4_multiply(modelT, modelT, + mat4_rotation_quat(matbuff, t->rotation)); + mat4_scale_vec3f(modelT, scale); + shader_setmat4(s, "model", modelT); + +} + +void gameobject_save(struct mGameObject *go, FILE * file) +{ + fwrite(go, sizeof(*go), 1, file); + + vec_store(go->components, file); + + for (int i = 0; i < go->components->len; i++) { + struct component *c = vec_get(go->components, i); + fwrite(c, c->datasize, 1, file); + } +} + +void gameobject_saveprefab(struct mGameObject *go) +{ + char prefabfname[60] = { '\0' }; + strncat(prefabfname, go->editor.prefabName, MAXNAME); + strncat(prefabfname, ".yugh", 10); + FILE *pfile = fopen(prefabfname, "w+"); + gameobject_save(go, pfile); + fclose(pfile); + + findPrefabs(); +} + +void gameobject_makefromprefab(char *path) +{ + FILE *fprefab = fopen(path, "r"); + if (fprefab == NULL) { + return; + } + + struct mGameObject *new = MakeGameobject(); + fread(new, sizeof(*new), 1, fprefab); + + new->editor.id = gameobjects->len - 1; + new->body = cpSpaceAddBody(space, cpBodyNew(new->mass, 1.f)); + + gameobject_init(new, fprefab); + + fclose(fprefab); +} + +void gameobject_init(struct mGameObject *go, FILE * fprefab) +{ + go->body = cpSpaceAddBody(space, cpBodyNew(go->mass, 1.f)); + + vec_load(go->components, fprefab); + + for (int i = 0; i < go->components->len; i++) { + struct component *newc = + vec_set(go->components, i, + &components[((struct component *) + vec_get(go->components, i))->id]); + newc->go = go; + newc->data = malloc(newc->datasize); + fread(newc->data, newc->datasize, 1, fprefab); + newc->init(newc->data, go); + } +} + +void gameobject_syncprefabs(char *revertPath) +{ +/* + struct mGameObject **go = objects; + int i = 0; + while(i != nobjects) { + if ((*go)->editor.curPrefabPath && !strcmp((*go)->editor.curPrefabPath, revertPath)) { ; }//objectRevertPrefab(go); //TODO: revertprefab + } +*/ +} + +void gameobject_revertprefab(struct mGameObject *go) +{ + +} + +void toggleprefab(struct mGameObject *go) +{ + go->editor.prefabSync = !go->editor.prefabSync; + + if (go->editor.prefabSync) { + strcpy(go->editor.prefabName, go->editor.rootPrefabName); + gameobject_revertprefab(go); //TODO: object revert prefab + } else { + go->editor.prefabName[0] = '\0'; + } +} + +void component_update(struct component *c) +{ + if (c->update) + c->update(c->data, c->go); +} + +void gameobject_update(struct mGameObject *go) +{ + if (go->update) { + updateGO = go; + script_run(updateGO->update); + } + + vec_walk(go->components, component_update); +} + +void gameobject_move(struct mGameObject *go, float xs, float ys) +{ + cpVect p = cpBodyGetPosition(go->body); + p.x += xs * deltaT; + p.y += ys * deltaT; + cpBodySetPosition(go->body, p); +} + +void gameobject_rotate(struct mGameObject *go, float as) +{ + cpFloat a = cpBodyGetAngle(go->body); + a += as * deltaT; + cpBodySetAngle(go->body, a); +} diff --git a/source/engine/gameobject.h b/source/engine/gameobject.h new file mode 100644 index 0000000..156973e --- /dev/null +++ b/source/engine/gameobject.h @@ -0,0 +1,73 @@ +#ifndef GAMEOBJECT_H +#define GAMEOBJECT_H + +#include +#include "mathc.h" +#include "transform.h" +#include "config.h" +#include +#include + +struct mShader; +struct mSprite; +struct component; +struct vec; + +extern struct mGameObject *updateGO; +extern struct vec *gameobjects; + +struct editor { + mfloat_t color[3]; + int id; + bool active; + bool prefabSync; + char mname[MAXNAME]; + char *curPrefabPath; + char prefabName[MAXNAME]; + char rootPrefabName[MAXNAME]; +}; + +struct mGameObject { + struct mTransform transform; + struct editor editor; + cpBodyType bodytype; + float scale; + float mass; + cpBody *body; + float f; /* friction */ + float e; /* elasticity */ + struct vec *components; + char *start; + char *update; + char *fixedupdate; + char *stop; +}; + +struct mGameObject *MakeGameobject(); +void gameobject_delete(int id); +void clear_gameobjects(); +int number_of_gameobjects(); +void set_n_gameobjects(int n); +void setup_model_transform(struct mTransform *t, struct mShader *s, + float scale); +void toggleprefab(struct mGameObject *go); +struct mGameObject *get_gameobject_from_id(int id); +void gameobject_save(struct mGameObject *go, FILE * file); +void gameobject_addcomponent(struct mGameObject *go, struct component *c); +void gameobject_delcomponent(struct mGameObject *go, int n); +void gameobject_loadcomponent(struct mGameObject *go, int id); + +void gameobject_saveprefab(struct mGameObject *go); +void gameobject_makefromprefab(char *path); +void gameobject_syncprefabs(char *revertPath); +void gameobject_revertprefab(struct mGameObject *go); + +void gameobject_init(struct mGameObject *go, FILE * fprefab); + +void gameobject_update(struct mGameObject *go); +void update_gameobjects(); + +void gameobject_move(struct mGameObject *go, float xs, float ys); +void gameobject_rotate(struct mGameObject *go, float as); + +#endif diff --git a/source/engine/gizmo.c b/source/engine/gizmo.c new file mode 100644 index 0000000..42e42a1 --- /dev/null +++ b/source/engine/gizmo.c @@ -0,0 +1 @@ +#include diff --git a/source/engine/gizmo.h b/source/engine/gizmo.h new file mode 100644 index 0000000..5d23c32 --- /dev/null +++ b/source/engine/gizmo.h @@ -0,0 +1,4 @@ +#ifndef GIZMO_H +#define GIZMO_H + +#endif diff --git a/source/engine/input.c b/source/engine/input.c new file mode 100644 index 0000000..e41bd91 --- /dev/null +++ b/source/engine/input.c @@ -0,0 +1,33 @@ +#include "input.h" + +#include "window.h" +#include + +int32_t mouseWheelX = 0; +int32_t mouseWheelY = 0; +int ychange = 0; +int xchange = 0; +float deltaT = 0; +int quit = 0; +SDL_Event e = { 0 }; + +uint8_t *currentKeystates = NULL; + +void input_poll() +{ + ychange = 0; + xchange = 0; + mouseWheelX = 0; + mouseWheelY = 0; + currentKeystates = SDL_GetKeyboardState(NULL); + + while (SDL_PollEvent(&e)) { + window_handle_event(window, &e); + +#ifdef EDITOR + editor_input(&e); +#endif + } + + +} diff --git a/source/engine/input.h b/source/engine/input.h new file mode 100644 index 0000000..cc55940 --- /dev/null +++ b/source/engine/input.h @@ -0,0 +1,18 @@ +#ifndef INPUT_H +#define INPUT_H + +#include +#include + +extern int32_t mouseWheelX; +extern int32_t mouseWheelY; +extern int ychange; +extern int xchange; +extern float deltaT; +extern int quit; +extern SDL_Event e; +extern uint8_t *currentKeystates; + +void input_poll(); + +#endif diff --git a/source/engine/level.c b/source/engine/level.c new file mode 100644 index 0000000..d1b486d --- /dev/null +++ b/source/engine/level.c @@ -0,0 +1,50 @@ +#include "level.h" +#include +#include +#include "vec.h" +#include "gameobject.h" + +void save_level(char name[MAXNAME]) +{ + FILE *lfile = res_open(name, "w+"); + + if (!lfile) return; + + + int objs = gameobjects->len; + fwrite(&objs, sizeof(objs), 1, lfile); + + for (int i = 0; i < objs; i++) { + gameobject_save(vec_get(gameobjects, i), lfile); + } + + fclose(lfile); +} + +void load_level(char name[MAXNAME]) +{ + FILE *lfile = fopen(name, "r"); + + if (!lfile) return; + + + int objs; + fread(&objs, sizeof(objs), 1, lfile); + + vec_clear(gameobjects); + + + for (int i = 0; i < objs; i++) { + struct mGameObject *go = vec_add(gameobjects, NULL); + fread(go, sizeof(struct mGameObject), 1, lfile); + gameobject_init(go, lfile); + } + + fclose(lfile); + +} + +void new_level() +{ + vec_clear(gameobjects); +} diff --git a/source/engine/level.h b/source/engine/level.h new file mode 100644 index 0000000..8f3e7df --- /dev/null +++ b/source/engine/level.h @@ -0,0 +1,17 @@ +#ifndef LEVEL_H +#define LEVEL_H + +#include "config.h" + +// This class holds all of the entities and options for a level. Really it's nothing more than a container and access point for all the entities currently loaded into the game. + +struct level { + char name[MAXNAME]; +}; + +void save_level(char name[MAXNAME]); +void load_level(char name[MAXNAME]); +void new_level(); + + +#endif diff --git a/source/engine/light.c b/source/engine/light.c new file mode 100644 index 0000000..667262e --- /dev/null +++ b/source/engine/light.c @@ -0,0 +1,160 @@ +#include +#include + + +/* +void Light::serialize(FILE * file) +{ + GameObject::serialize(file); + + SerializeFloat(file, &strength); + SerializeVec3(file, (float *) &color); + SerializeBool(file, &dynamic); +} + +void Light::deserialize(FILE * file) +{ + GameObject::deserialize(file); + + DeserializeFloat(file, &strength); + DeserializeVec3(file, (float *) &color); + DeserializeBool(file, &dynamic); +} + + + +static const mfloat_t dlight_init_rot[3] = { 80.f, 120.f, 165.f }; + +struct mDirectionalLight *dLight = NULL; + +struct mDirectionalLight *MakeDLight() +{ + if (dLight != NULL) { + dLight = + (struct mDirectionalLight *) + malloc(sizeof(struct mDirectionalLight)); + quat_from_euler(dLight->light.obj.transform.rotation, + dlight_init_rot); + + return dLight; + } + + return dLight; +} + +void dlight_prepshader(struct mDirectionalLight *light, + struct mShader *shader) +{ + mfloat_t fwd[3] = { 0.f }; + trans_forward(fwd, &light->light.obj.transform); + shader_setvec3(shader, "dirLight.direction", fwd); + shader_setvec3(shader, "dirLight.color", light->light.color); + shader_setfloat(shader, "dirLight.strength", light->light.strength); +} + + + +static struct mPointLight *pointLights[4]; +static int numLights = 0; + + +struct mPointLight *MakePointlight() +{ + if (numLights < 4) { + struct mPointLight *light = + (struct mPointLight *) malloc(sizeof(struct mPointLight)); + pointLights[numLights++] = light; + light->light.strength = 0.2f; + light->constant = 1.f; + light->linear = 0.9f; + light->quadratic = 0.032f; + return light; + } + + return NULL; +} + +static void prepstring(char *buffer, char *prepend, const char *append) +{ + snprintf(buffer, 100, "%s%s", prepend, append); +} + +void pointlights_prepshader(struct mShader *shader) +{ + for (int i = 0; i < numLights; i++) + pointlight_prepshader(pointLights[i], shader, i); +} + +void pointlight_prepshader(struct mPointLight *light, + struct mShader *shader, int num) +{ + shader_use(shader); + char prepend[100] = { '\0' }; + snprintf(prepend, 100, "%s%d%s", "pointLights[", num, "]."); + char str[100] = { '\0' }; + + prepstring(str, prepend, "position"); + shader_setvec3(shader, str, light->light.obj.transform.position); + + prepstring(str, prepend, "constant"); + shader_setfloat(shader, str, light->constant); + + prepstring(str, prepend, "linear"); + shader_setfloat(shader, str, light->linear); + + prepstring(str, prepend, "quadratic"); + shader_setfloat(shader, str, light->quadratic); + + prepstring(str, prepend, "strength"); + shader_setfloat(shader, str, light->light.strength); + + prepstring(str, prepend, "color"); + shader_setvec3(shader, str, light->light.color); +} + + + + +static struct mSpotLight *spotLights[4]; +static int numSpots = 0; + +struct mSpotLight *MakeSpotlight() +{ + if (numSpots < 4) { + struct mSpotLight *light = + (struct mSpotLight *) malloc(sizeof(struct mSpotLight)); + spotLights[numSpots++] = light; + return light; + } + + return NULL; +} + + + +void spotlights_prepshader(struct mShader *shader) +{ + for (int i = 0; i < numSpots; i++) + spotlight_prepshader(spotLights[i], shader, i); +} + +void spotlight_prepshader(struct mSpotLight *light, struct mShader *shader, + int num) +{ + mfloat_t fwd[3] = { 0.f }; + trans_forward(fwd, &light->light.obj.transform); + shader_use(shader); + shader_setvec3(shader, "spotLight.position", + light->light.obj.transform.position); + shader_setvec3(shader, "spotLight.direction", fwd); + shader_setvec3(shader, "spotLight.color", light->light.color); + shader_setfloat(shader, "spotLight.strength", light->light.strength); + shader_setfloat(shader, "spotLight.cutoff", light->cutoff); + shader_setfloat(shader, "spotLight.distance", light->distance); + shader_setfloat(shader, "spotLight.outerCutoff", light->outerCutoff); + shader_setfloat(shader, "spotLight.linear", light->linear); + shader_setfloat(shader, "spotLight.quadratic", light->quadratic); + shader_setfloat(shader, "spotLight.constant", light->constant); +} + +*/ \ No newline at end of file diff --git a/source/engine/light.h b/source/engine/light.h new file mode 100644 index 0000000..c51986f --- /dev/null +++ b/source/engine/light.h @@ -0,0 +1,58 @@ +#ifndef LIGHT_H +#define LIGHT_H + +/* +struct mLight { + struct mGameObject obj; + mfloat_t color[3]; + float strength; + int dynamic; + int on; +}; + + +struct mPointLight { + struct mLight light; + float constant; + float linear; + float quadratic; +}; + +struct mPointLight *MakePointlight(); +void pointlight_prepshader(struct mPointLight *light, + struct mShader *shader, int num); +void pointlights_prepshader(struct mShader *shader); + + +struct mSpotLight { + struct mLight light; + float constant; + float linear; + float quadratic; + float distance; + + float cutoff; + float outerCutoff; +}; + +struct mSpotLight *MakeSpotlight(); +void spotlight_gui(struct mSpotLight *light); +void spotlight_prepshader(struct mSpotLight *light, struct mShader *shader, + int num); +void spotlights_prepshader(struct mShader *shader); + + + +struct mDirectionalLight { + struct mLight light; +}; + +void dlight_prepshader(struct mDirectionalLight *light, + struct mShader *shader); +struct mDirectionalLight *MakeDLight(); + +extern struct mDirectionalLight *dLight; + +*/ + +#endif diff --git a/source/engine/log.c b/source/engine/log.c new file mode 100644 index 0000000..a40a659 --- /dev/null +++ b/source/engine/log.c @@ -0,0 +1,56 @@ +#include "log.h" + +#include +#include +#include +#include +#include +#include + +#define logLevel 0 + +void mYughLog(int category, int priority, const char *message, + int line, const char *file, ...) +{ + if (priority >= logLevel) { + time_t now = time(0); + char *dt = ctime(&now); + dt[strlen(dt) - 1] = '\0'; // The above time conversion adds a \n; this removes it + + va_list args; + va_start(args, message); + char msgbuffer[ERROR_BUFFER] = { '\0' }; + vsnprintf(msgbuffer, ERROR_BUFFER, message, args); + va_end(args); + + char buffer[ERROR_BUFFER] = { '\0' }; + snprintf(buffer, ERROR_BUFFER, "LEVEL %d :: %s [ %s:%d ] %s\n", + priority, msgbuffer, file, line, dt); + + //SDL_LogMessage(category, priority, buffer); + printf(buffer); + fflush(stdout); + } +} + +void FlushGLErrors() +{ + GLenum glErr = GL_NO_ERROR; + glErr = glGetError(); + while (glErr != GL_NO_ERROR) { + YughLog(SDL_LOG_CATEGORY_RENDER, SDL_LOG_PRIORITY_ERROR, + "GL Error: %d", glErr); + glErr = glGetError(); + } +} + +int TestSDLError(int sdlErr) +{ + if (sdlErr != 0) { + YughLog(0, SDL_LOG_PRIORITY_ERROR, "SDL Error :: %s", + SDL_GetError()); + return 0; + } + + return 1; +} \ No newline at end of file diff --git a/source/engine/log.h b/source/engine/log.h new file mode 100644 index 0000000..becf55a --- /dev/null +++ b/source/engine/log.h @@ -0,0 +1,17 @@ +#ifndef LOG_H +#define LOG_H + +#include + +#define ERROR_BUFFER 2048 + +#define YughLog(cat, pri, msg, ...) mYughLog(cat, pri, msg, __LINE__, __FILE__, __VA_ARGS__) + +void mYughLog(int category, int priority, const char *message, + int line, const char *file, ...); + +void FlushGLErrors(); + +int TestSDLError(int sdlErr); + +#endif \ No newline at end of file diff --git a/source/engine/mathc.c b/source/engine/mathc.c new file mode 100644 index 0000000..dbcc5e9 --- /dev/null +++ b/source/engine/mathc.c @@ -0,0 +1,7545 @@ +/* +Copyright © 2018 Felipe Ferreira da Silva + +This software is provided 'as-is', without any express or implied warranty. In +no event will the authors be held liable for any damages arising from the use of +this software. + +Permission is granted to anyone to use this software for any purpose, including +commercial applications, and to alter it and redistribute it freely, subject to +the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "mathc.h" + +const mfloat_t VEC3ZERO[3] = { 0.f, 0.f, 0.f }; +const mfloat_t UP[3] = { 0.f, 1.f, 0.f }; +const mfloat_t DOWN[3] = { 0.f, -1.f, 0.f }; +const mfloat_t FORWARD[3] = { 0.f, 0.f, 1.f }; +const mfloat_t BACK[3] = { 0.f, 0.f, -1.f }; +const mfloat_t RIGHT[3] = { 1.f, 0.f, 0.f }; +const mfloat_t LEFT[3] = { -1.f, 0.f, 0.f }; + +const float UNITMAT4[16] = + { 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, +0.f, 1.f }; + +const mfloat_t VEC2_ZERO[2] = { 0.f, 0.f }; +const mint_t VEC2I_ZERO[2] = { 0, 0 }; +const mfloat_t VEC3_ZERO[3] = { 0.f, 0.f, 0.f }; +const mint_t VEC3I_ZERO[3] = { 0, 0, 0 }; + +const mfloat_t VEC2_ONE[2] = { 1.f, 1.f }; +const mint_t VEC2I_ONE[2] = { 1, 1 }; +const mfloat_t VEC3_ONE[3] = { 1.f, 1.f, 1.f }; +const mint_t VEC3I_ONE[3] = { 1, 1, 1 }; + +#include + +typedef float mfloat_t; + +#if defined(MATHC_USE_INT) +mint_t clampi(mint_t value, mint_t min, mint_t max) +{ + if (value < min) { + value = min; + } else if (value > max) { + value = max; + } + return value; +} +#endif + +#if defined(MATHC_USE_FLOATING_POINT) +bool nearly_equal(mfloat_t a, mfloat_t b, mfloat_t epsilon) +{ + bool result = false; + if (a == b) { + result = true; + } else if (MFABS(a - b) <= epsilon) { + result = true; + } + return result; +} + +mfloat_t to_radians(mfloat_t degrees) +{ + return MRADIANS(degrees); +} + +mfloat_t to_degrees(mfloat_t radians) +{ + return MDEGREES(radians); +} + +mfloat_t clampf(mfloat_t value, mfloat_t min, mfloat_t max) +{ + if (value < min) { + value = min; + } else if (value > max) { + value = max; + } + return value; +} +#endif + +#if defined(MATHC_USE_INT) +bool vec2i_is_zero(mint_t * v0) +{ + return v0[0] == 0 && v0[1] == 0; +} + +bool vec2i_is_equal(mint_t * v0, mint_t * v1) +{ + return v0[0] == v1[0] && v0[1] == v1[1]; +} + +mint_t *vec2i(mint_t * result, mint_t x, mint_t y) +{ + result[0] = x; + result[1] = y; + return result; +} + +mint_t *vec2i_assign(mint_t * result, mint_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + return result; +} + +#if defined(MATHC_USE_FLOATING_POINT) +mint_t *vec2i_assign_vec2(mint_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + return result; +} +#endif + +mint_t *vec2i_zero(mint_t * result) +{ + result[0] = 0; + result[1] = 0; + return result; +} + +mint_t *vec2i_one(mint_t * result) +{ + result[0] = 1; + result[1] = 1; + return result; +} + +mint_t *vec2i_sign(mint_t * result, mint_t * v0) +{ + if (v0[0] > 0) { + result[0] = 1; + } else if (v0[0] < 0) { + result[0] = -1; + } else { + result[0] = 0; + } + if (v0[1] > 0) { + result[1] = 1; + } else if (v0[1] < 0) { + result[1] = -1; + } else { + result[1] = 0; + } + return result; +} + +mint_t *vec2i_add(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] + v1[0]; + result[1] = v0[1] + v1[1]; + return result; +} + +mint_t *vec2i_add_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] + i; + result[1] = v0[1] + i; + return result; +} + +mint_t *vec2i_subtract(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] - v1[0]; + result[1] = v0[1] - v1[1]; + return result; +} + +mint_t *vec2i_subtract_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] - i; + result[1] = v0[1] - i; + return result; +} + +mint_t *vec2i_multiply(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] * v1[0]; + result[1] = v0[1] * v1[1]; + return result; +} + +mint_t *vec2i_multiply_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] * i; + result[1] = v0[1] * i; + return result; +} + +mint_t *vec2i_divide(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] / v1[0]; + result[1] = v0[1] / v1[1]; + return result; +} + +mint_t *vec2i_divide_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] / i; + result[1] = v0[1] / i; + return result; +} + +mint_t *vec2i_snap(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = (v0[0] / v1[0]) * v1[0]; + result[1] = (v0[1] / v1[1]) * v1[1]; + return result; +} + +mint_t *vec2i_snap_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = (v0[0] / i) * i; + result[1] = (v0[1] / i) * i; + return result; +} + +mint_t *vec2i_negative(mint_t * result, mint_t * v0) +{ + result[0] = -v0[0]; + result[1] = -v0[1]; + return result; +} + +mint_t *vec2i_abs(mint_t * result, mint_t * v0) +{ + result[0] = v0[0]; + if (result[0] < 0) { + result[0] = -result[0]; + } + result[1] = v0[1]; + if (result[1] < 0) { + result[1] = -result[1]; + } + return result; +} + +mint_t *vec2i_max(mint_t * result, mint_t * v0, mint_t * v1) +{ + if (v0[0] > v1[0]) { + result[0] = v0[0]; + } else { + result[0] = v1[0]; + } + if (v0[1] > v1[1]) { + result[1] = v0[1]; + } else { + result[1] = v1[1]; + } + return result; +} + +mint_t *vec2i_min(mint_t * result, mint_t * v0, mint_t * v1) +{ + if (v0[0] < v1[0]) { + result[0] = v0[0]; + } else { + result[0] = v1[0]; + } + if (v0[1] < v1[1]) { + result[1] = v0[1]; + } else { + result[1] = v1[1]; + } + return result; +} + +mint_t *vec2i_clamp(mint_t * result, mint_t * v0, mint_t * v1, mint_t * v2) +{ + vec2i_min(result, v0, v1); + vec2i_max(result, v0, v2); + return result; +} + +mint_t *vec2i_tangent(mint_t * result, mint_t * v0) +{ + mint_t a0 = v0[0]; + mint_t a1 = v0[1]; + result[0] = a1; + result[1] = -a0; + return result; +} + +bool vec3i_is_zero(mint_t * v0) +{ + return v0[0] == 0 && v0[1] == 0 && v0[2] == 0; +} + +bool vec3i_is_equal(mint_t * v0, mint_t * v1) +{ + return v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2]; +} + +mint_t *vec3i(mint_t * result, mint_t x, mint_t y, mint_t z) +{ + result[0] = x; + result[1] = y; + result[2] = z; + return result; +} + +mint_t *vec3i_assign(mint_t * result, mint_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + return result; +} + +#if defined(MATHC_USE_FLOATING_POINT) +mint_t *vec3i_assign_vec3(mint_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + return result; +} +#endif + +mint_t *vec3i_zero(mint_t * result) +{ + result[0] = 0; + result[1] = 0; + result[2] = 0; + return result; +} + +mint_t *vec3i_one(mint_t * result) +{ + result[0] = 1; + result[1] = 1; + result[2] = 1; + return result; +} + +mint_t *vec3i_sign(mint_t * result, mint_t * v0) +{ + if (v0[0] > 0) { + result[0] = 1; + } else if (v0[0] < 0) { + result[0] = -1; + } else { + result[0] = 0; + } + if (v0[1] > 0) { + result[1] = 1; + } else if (v0[1] < 0) { + result[1] = -1; + } else { + result[1] = 0; + } + if (v0[2] > 0) { + result[2] = 1; + } else if (v0[2] < 0) { + result[2] = -1; + } else { + result[2] = 0; + } + return result; +} + +mint_t *vec3i_add(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] + v1[0]; + result[1] = v0[1] + v1[1]; + result[2] = v0[2] + v1[2]; + return result; +} + +mint_t *vec3i_add_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] + i; + result[1] = v0[1] + i; + result[2] = v0[2] + i; + return result; +} + +mint_t *vec3i_subtract(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] - v1[0]; + result[1] = v0[1] - v1[1]; + result[2] = v0[2] - v1[2]; + return result; +} + +mint_t *vec3i_subtract_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] - i; + result[1] = v0[1] - i; + result[2] = v0[2] - i; + return result; +} + +mint_t *vec3i_multiply(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] * v1[0]; + result[1] = v0[1] * v1[1]; + result[2] = v0[2] * v1[2]; + return result; +} + +mint_t *vec3i_multiply_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] * i; + result[1] = v0[1] * i; + result[2] = v0[2] * i; + return result; +} + +mint_t *vec3i_divide(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] / v1[0]; + result[1] = v0[1] / v1[1]; + result[2] = v0[2] / v1[2]; + return result; +} + +mint_t *vec3i_divide_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] / i; + result[1] = v0[1] / i; + result[2] = v0[2] / i; + return result; +} + +mint_t *vec3i_snap(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = (v0[0] / v1[0]) * v1[0]; + result[1] = (v0[1] / v1[1]) * v1[1]; + result[2] = (v0[2] / v1[2]) * v1[2]; + return result; +} + +mint_t *vec3i_snap_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = (v0[0] / i) * i; + result[1] = (v0[1] / i) * i; + result[2] = (v0[2] / i) * i; + return result; +} + +mint_t *vec3i_cross(mint_t * result, mint_t * v0, mint_t * v1) +{ + mint_t cross[VEC3_SIZE]; + cross[0] = v0[1] * v1[2] - v0[2] * v1[1]; + cross[1] = v0[2] * v1[0] - v0[0] * v1[2]; + cross[2] = v0[0] * v1[1] - v0[1] * v1[0]; + result[0] = cross[0]; + result[1] = cross[1]; + result[2] = cross[2]; + return result; +} + +mint_t *vec3i_negative(mint_t * result, mint_t * v0) +{ + result[0] = -v0[0]; + result[1] = -v0[1]; + result[2] = -v0[2]; + return result; +} + +mint_t *vec3i_abs(mint_t * result, mint_t * v0) +{ + result[0] = v0[0]; + if (result[0] < 0) { + result[0] = -result[0]; + } + result[1] = v0[1]; + if (result[1] < 0) { + result[1] = -result[1]; + } + result[2] = v0[2]; + if (result[2] < 0) { + result[2] = -result[2]; + } + return result; +} + +mint_t *vec3i_max(mint_t * result, mint_t * v0, mint_t * v1) +{ + if (v0[0] > v1[0]) { + result[0] = v0[0]; + } else { + result[0] = v1[0]; + } + if (v0[1] > v1[1]) { + result[1] = v0[1]; + } else { + result[1] = v1[1]; + } + if (v0[2] > v1[2]) { + result[2] = v0[2]; + } else { + result[2] = v1[2]; + } + return result; +} + +mint_t *vec3i_min(mint_t * result, mint_t * v0, mint_t * v1) +{ + if (v0[0] < v1[0]) { + result[0] = v0[0]; + } else { + result[0] = v1[0]; + } + if (v0[1] < v1[1]) { + result[1] = v0[1]; + } else { + result[1] = v1[1]; + } + if (v0[2] < v1[2]) { + result[2] = v0[2]; + } else { + result[2] = v1[2]; + } + return result; +} + +mint_t *vec3i_clamp(mint_t * result, mint_t * v0, mint_t * v1, mint_t * v2) +{ + vec3i_min(result, v0, v1); + vec3i_max(result, v0, v2); + return result; +} + +bool vec4i_is_zero(mint_t * v0) +{ + return v0[0] == 0 && v0[1] == 0 && v0[2] == 0 && v0[3] == 0; +} + +bool vec4i_is_equal(mint_t * v0, mint_t * v1) +{ + return v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2] + && v0[3] == v1[3]; +} + +mint_t *vec4i(mint_t * result, mint_t x, mint_t y, mint_t z, mint_t w) +{ + result[0] = x; + result[1] = y; + result[2] = z; + result[3] = w; + return result; +} + +mint_t *vec4i_assign(mint_t * result, mint_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + result[3] = v0[3]; + return result; +} + +#if defined(MATHC_USE_FLOATING_POINT) +mint_t *vec4i_assign_vec4(mint_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + result[3] = v0[3]; + return result; +} +#endif + +mint_t *vec4i_zero(mint_t * result) +{ + result[0] = 0; + result[1] = 0; + result[2] = 0; + result[3] = 0; + return result; +} + +mint_t *vec4i_one(mint_t * result) +{ + result[0] = 1; + result[1] = 1; + result[2] = 1; + result[3] = 1; + return result; +} + +mint_t *vec4i_sign(mint_t * result, mint_t * v0) +{ + if (v0[0] > 0) { + result[0] = 1; + } else if (v0[0] < 0) { + result[0] = -1; + } else { + result[0] = 0; + } + if (v0[1] > 0) { + result[1] = 1; + } else if (v0[1] < 0) { + result[1] = -1; + } else { + result[1] = 0; + } + if (v0[2] > 0) { + result[2] = 1; + } else if (v0[2] < 0) { + result[2] = -1; + } else { + result[2] = 0; + } + if (v0[3] > 0) { + result[3] = 1; + } else if (v0[3] < 0) { + result[3] = -1; + } else { + result[3] = 0; + } + return result; +} + +mint_t *vec4i_add(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] + v1[0]; + result[1] = v0[1] + v1[1]; + result[2] = v0[2] + v1[2]; + result[3] = v0[3] + v1[3]; + return result; +} + +mint_t *vec4i_add_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] + i; + result[1] = v0[1] + i; + result[2] = v0[2] + i; + result[3] = v0[3] + i; + return result; +} + +mint_t *vec4i_subtract(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] - v1[0]; + result[1] = v0[1] - v1[1]; + result[2] = v0[2] - v1[2]; + result[3] = v0[3] - v1[3]; + return result; +} + +mint_t *vec4i_subtract_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] - i; + result[1] = v0[1] - i; + result[2] = v0[2] - i; + result[3] = v0[3] - i; + return result; +} + +mint_t *vec4i_multiply(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] * v1[0]; + result[1] = v0[1] * v1[1]; + result[2] = v0[2] * v1[2]; + result[3] = v0[3] * v1[3]; + return result; +} + +mint_t *vec4i_multiply_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] * i; + result[1] = v0[1] * i; + result[2] = v0[2] * i; + result[3] = v0[3] * i; + return result; +} + +mint_t *vec4i_divide(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = v0[0] / v1[0]; + result[1] = v0[1] / v1[1]; + result[2] = v0[2] / v1[2]; + result[3] = v0[3] / v1[3]; + return result; +} + +mint_t *vec4i_divide_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = v0[0] / i; + result[1] = v0[1] / i; + result[2] = v0[2] / i; + result[3] = v0[3] / i; + return result; +} + +mint_t *vec4i_snap(mint_t * result, mint_t * v0, mint_t * v1) +{ + result[0] = (v0[0] / v1[0]) * v1[0]; + result[1] = (v0[1] / v1[1]) * v1[1]; + result[2] = (v0[2] / v1[2]) * v1[2]; + result[3] = (v0[3] / v1[3]) * v1[3]; + return result; +} + +mint_t *vec4i_snap_i(mint_t * result, mint_t * v0, mint_t i) +{ + result[0] = (v0[0] / i) * i; + result[1] = (v0[1] / i) * i; + result[2] = (v0[2] / i) * i; + result[3] = (v0[3] / i) * i; + return result; +} + +mint_t *vec4i_negative(mint_t * result, mint_t * v0) +{ + result[0] = -v0[0]; + result[1] = -v0[1]; + result[2] = -v0[2]; + result[3] = -v0[3]; + return result; +} + +mint_t *vec4i_abs(mint_t * result, mint_t * v0) +{ + result[0] = v0[0]; + if (result[0] < 0) { + result[0] = -result[0]; + } + result[1] = v0[1]; + if (result[1] < 0) { + result[1] = -result[1]; + } + result[2] = v0[2]; + if (result[2] < 0) { + result[2] = -result[2]; + } + result[3] = v0[3]; + if (result[3] < 0) { + result[3] = -result[3]; + } + return result; +} + +mint_t *vec4i_max(mint_t * result, mint_t * v0, mint_t * v1) +{ + if (v0[0] > v1[0]) { + result[0] = v0[0]; + } else { + result[0] = v1[0]; + } + if (v0[1] > v1[1]) { + result[1] = v0[1]; + } else { + result[1] = v1[1]; + } + if (v0[2] > v1[2]) { + result[2] = v0[2]; + } else { + result[2] = v1[2]; + } + if (v0[3] > v1[3]) { + result[3] = v0[3]; + } else { + result[3] = v1[3]; + } + return result; +} + +mint_t *vec4i_min(mint_t * result, mint_t * v0, mint_t * v1) +{ + if (v0[0] < v1[0]) { + result[0] = v0[0]; + } else { + result[0] = v1[0]; + } + if (v0[1] < v1[1]) { + result[1] = v0[1]; + } else { + result[1] = v1[1]; + } + if (v0[2] < v1[2]) { + result[2] = v0[2]; + } else { + result[2] = v1[2]; + } + if (v0[3] < v1[3]) { + result[3] = v0[3]; + } else { + result[3] = v1[3]; + } + return result; +} + +mint_t *vec4i_clamp(mint_t * result, mint_t * v0, mint_t * v1, mint_t * v2) +{ + vec4i_min(result, v0, v1); + vec4i_max(result, v0, v2); + return result; +} +#endif + +#if defined(MATHC_USE_FLOATING_POINT) +bool vec2_is_zero(mfloat_t * v0) +{ + return MFABS(v0[0]) < MFLT_EPSILON && MFABS(v0[1]) < MFLT_EPSILON; +} + +bool vec2_is_equal(mfloat_t * v0, mfloat_t * v1) +{ + return MFABS(v0[0] - v1[0]) < MFLT_EPSILON + && MFABS(v0[1] - v1[1]) < MFLT_EPSILON; +} + +mfloat_t *vec2(mfloat_t * result, mfloat_t x, mfloat_t y) +{ + result[0] = x; + result[1] = y; + return result; +} + +mfloat_t *vec2_assign(mfloat_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + return result; +} + +#if defined(MATHC_USE_INT) +mfloat_t *vec2_assign_vec2i(mfloat_t * result, mint_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + return result; +} +#endif + +mfloat_t *vec2_zero(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *vec2_one(mfloat_t * result) +{ + result[0] = MFLOAT_C(1.0); + result[1] = MFLOAT_C(1.0); + return result; +} + +mfloat_t *vec2_sign(mfloat_t * result, mfloat_t * v0) +{ + if (v0[0] > MFLOAT_C(0.0)) { + result[0] = MFLOAT_C(1.0); + } else if (v0[0] < MFLOAT_C(0.0)) { + result[0] = -MFLOAT_C(1.0); + } else { + result[0] = MFLOAT_C(0.0); + } + if (v0[1] > MFLOAT_C(0.0)) { + result[1] = MFLOAT_C(1.0); + } else if (v0[1] < MFLOAT_C(0.0)) { + result[1] = -MFLOAT_C(1.0); + } else { + result[1] = MFLOAT_C(0.0); + } + return result; +} + +mfloat_t *vec2_add(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] + v1[0]; + result[1] = v0[1] + v1[1]; + return result; +} + +mfloat_t *vec2_add_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] + f; + result[1] = v0[1] + f; + return result; +} + +mfloat_t *vec2_subtract(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] - v1[0]; + result[1] = v0[1] - v1[1]; + return result; +} + +mfloat_t *vec2_subtract_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] - f; + result[1] = v0[1] - f; + return result; +} + +mfloat_t *vec2_multiply(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] * v1[0]; + result[1] = v0[1] * v1[1]; + return result; +} + +mfloat_t *vec2_multiply_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] * f; + result[1] = v0[1] * f; + return result; +} + +mfloat_t *vec2_multiply_mat2(mfloat_t * result, mfloat_t * v0, + mfloat_t * m0) +{ + mfloat_t x = v0[0]; + mfloat_t y = v0[1]; + result[0] = m0[0] * x + m0[2] * y; + result[1] = m0[1] * x + m0[3] * y; + return result; +} + +mfloat_t *vec2_divide(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] / v1[0]; + result[1] = v0[1] / v1[1]; + return result; +} + +mfloat_t *vec2_divide_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] / f; + result[1] = v0[1] / f; + return result; +} + +mfloat_t *vec2_snap(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFLOOR(v0[0] / v1[0]) * v1[0]; + result[1] = MFLOOR(v0[1] / v1[1]) * v1[1]; + return result; +} + +mfloat_t *vec2_snap_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = MFLOOR(v0[0] / f) * f; + result[1] = MFLOOR(v0[1] / f) * f; + return result; +} + +mfloat_t *vec2_negative(mfloat_t * result, mfloat_t * v0) +{ + result[0] = -v0[0]; + result[1] = -v0[1]; + return result; +} + +mfloat_t *vec2_abs(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MFABS(v0[0]); + result[1] = MFABS(v0[1]); + return result; +} + +mfloat_t *vec2_floor(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MFLOOR(v0[0]); + result[1] = MFLOOR(v0[1]); + return result; +} + +mfloat_t *vec2_ceil(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MCEIL(v0[0]); + result[1] = MCEIL(v0[1]); + return result; +} + +mfloat_t *vec2_round(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MROUND(v0[0]); + result[1] = MROUND(v0[1]); + return result; +} + +mfloat_t *vec2_max(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFMAX(v0[0], v1[0]); + result[1] = MFMAX(v0[1], v1[1]); + return result; +} + +mfloat_t *vec2_min(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFMIN(v0[0], v1[0]); + result[1] = MFMIN(v0[1], v1[1]); + return result; +} + +mfloat_t *vec2_clamp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2) +{ + vec2_min(result, v0, v1); + vec2_max(result, v0, v2); + return result; +} + +mfloat_t *vec2_normalize(mfloat_t * result, mfloat_t * v0) +{ + mfloat_t l = MSQRT(v0[0] * v0[0] + v0[1] * v0[1]); + result[0] = v0[0] / l; + result[1] = v0[1] / l; + return result; +} + +mfloat_t vec2_dot(mfloat_t * v0, mfloat_t * v1) +{ + return v0[0] * v1[0] + v0[1] * v1[1]; +} + +mfloat_t *vec2_project(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + mfloat_t d = vec2_dot(v1, v1); + mfloat_t s = vec2_dot(v0, v1) / d; + result[0] = v1[0] * s; + result[1] = v1[1] * s; + return result; +} + +mfloat_t *vec2_slide(mfloat_t * result, mfloat_t * v0, mfloat_t * normal) +{ + mfloat_t d = vec2_dot(v0, normal); + result[0] = v0[0] - normal[0] * d; + result[1] = v0[1] - normal[1] * d; + return result; +} + +mfloat_t *vec2_reflect(mfloat_t * result, mfloat_t * v0, mfloat_t * normal) +{ + mfloat_t d = MFLOAT_C(2.0) * vec2_dot(v0, normal); + result[0] = normal[0] * d - v0[0]; + result[1] = normal[1] * d - v0[1]; + return result; +} + +mfloat_t *vec2_tangent(mfloat_t * result, mfloat_t * v0) +{ + mfloat_t a0 = v0[0]; + mfloat_t a1 = v0[1]; + result[0] = a1; + result[1] = -a0; + return result; +} + +mfloat_t *vec2_rotate(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + mfloat_t cs = MCOS(f); + mfloat_t sn = MSIN(f); + mfloat_t x = v0[0]; + mfloat_t y = v0[1]; + result[0] = x * cs - y * sn; + result[1] = x * sn + y * cs; + return result; +} + +mfloat_t *vec2_lerp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t f) +{ + result[0] = v0[0] + (v1[0] - v0[0]) * f; + result[1] = v0[1] + (v1[1] - v0[1]) * f; + return result; +} + +mfloat_t *vec2_bezier3(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t f) +{ + mfloat_t tmp0[VEC2_SIZE]; + mfloat_t tmp1[VEC2_SIZE]; + vec2_lerp(tmp0, v0, v1, f); + vec2_lerp(tmp1, v1, v2, f); + vec2_lerp(result, tmp0, tmp1, f); + return result; +} + +mfloat_t *vec2_bezier4(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t * v3, mfloat_t f) +{ + mfloat_t tmp0[VEC2_SIZE]; + mfloat_t tmp1[VEC2_SIZE]; + mfloat_t tmp2[VEC2_SIZE]; + mfloat_t tmp3[VEC2_SIZE]; + mfloat_t tmp4[VEC2_SIZE]; + vec2_lerp(tmp0, v0, v1, f); + vec2_lerp(tmp1, v1, v2, f); + vec2_lerp(tmp2, v2, v3, f); + vec2_lerp(tmp3, tmp0, tmp1, f); + vec2_lerp(tmp4, tmp1, tmp2, f); + vec2_lerp(result, tmp3, tmp4, f); + return result; +} + +mfloat_t vec2_angle(mfloat_t * v0) +{ + return MATAN2(v0[1], v0[0]); +} + +mfloat_t vec2_length(mfloat_t * v0) +{ + return MSQRT(v0[0] * v0[0] + v0[1] * v0[1]); +} + +mfloat_t vec2_length_squared(mfloat_t * v0) +{ + return v0[0] * v0[0] + v0[1] * v0[1]; +} + +mfloat_t vec2_distance(mfloat_t * v0, mfloat_t * v1) +{ + return MSQRT((v0[0] - v1[0]) * (v0[0] - v1[0]) + + (v0[1] - v1[1]) * (v0[1] - v1[1])); +} + +mfloat_t vec2_distance_squared(mfloat_t * v0, mfloat_t * v1) +{ + return (v0[0] - v1[0]) * (v0[0] - v1[0]) + (v0[1] - v1[1]) * (v0[1] - + v1[1]); +} + +bool vec2_linear_independent(mfloat_t * v0, mfloat_t * v1) +{ + return (v0[0] * v1[1] - v1[0] * v0[1]) != 0; +} + +mfloat_t **vec2_orthonormalization(mfloat_t result[2][2], + mfloat_t basis[2][2]) +{ + mfloat_t v0[2]; + mfloat_t v1[2]; + + for (int32_t i = 0; i < 2; ++i) { + v0[i] = basis[0][i]; + v1[i] = basis[1][i]; + } + + if (!vec2_linear_independent(v0, v1)) { + return (mfloat_t **) result; + } + + mfloat_t proju1[2]; + mfloat_t u0[2]; + mfloat_t u1[2]; + + for (int32_t i = 0; i < 2; ++i) { + u0[i] = v0[i]; + } + + vec2_project(proju1, v1, v0); + vec2_subtract(u1, v1, proju1); + vec2_normalize(result[0], u0); + vec2_normalize(result[1], u1); + + return (mfloat_t **) result; +} + +bool vec3_is_zero(mfloat_t * v0) +{ + return MFABS(v0[0]) < MFLT_EPSILON && MFABS(v0[1]) < MFLT_EPSILON + && MFABS(v0[2]) < MFLT_EPSILON; +} + +bool vec3_is_equal(mfloat_t * v0, mfloat_t * v1) +{ + return MFABS(v0[0] - v1[0]) < MFLT_EPSILON + && MFABS(v0[1] - v1[1]) < MFLT_EPSILON + && MFABS(v0[2] - v1[2]) < MFLT_EPSILON; +} + +mfloat_t *vec3(mfloat_t * result, mfloat_t x, mfloat_t y, mfloat_t z) +{ + result[0] = x; + result[1] = y; + result[2] = z; + return result; +} + +mfloat_t *vec3_assign(mfloat_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + return result; +} + +#if defined(MATHC_USE_INT) +mfloat_t *vec3_assign_vec3i(mfloat_t * result, mint_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + return result; +} +#endif + +mfloat_t *vec3_zero(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *vec3_one(mfloat_t * result) +{ + result[0] = MFLOAT_C(1.0); + result[1] = MFLOAT_C(1.0); + result[2] = MFLOAT_C(1.0); + return result; +} + +mfloat_t *vec3_sign(mfloat_t * result, mfloat_t * v0) +{ + if (v0[0] > MFLOAT_C(0.0)) { + result[0] = MFLOAT_C(1.0); + } else if (v0[0] < 0) { + result[0] = -MFLOAT_C(1.0); + } else { + result[0] = MFLOAT_C(0.0); + } + if (v0[1] > MFLOAT_C(0.0)) { + result[1] = MFLOAT_C(1.0); + } else if (v0[1] < 0) { + result[1] = -MFLOAT_C(1.0); + } else { + result[1] = MFLOAT_C(0.0); + } + if (v0[2] > MFLOAT_C(0.0)) { + result[2] = MFLOAT_C(1.0); + } else if (v0[2] < 0) { + result[2] = -MFLOAT_C(1.0); + } else { + result[2] = MFLOAT_C(0.0); + } + return result; +} + +mfloat_t *vec3_add(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1) +{ + result[0] = v0[0] + v1[0]; + result[1] = v0[1] + v1[1]; + result[2] = v0[2] + v1[2]; + return result; +} + +mfloat_t *vec3_add_f(mfloat_t * result, const mfloat_t * v0, + const mfloat_t f) +{ + result[0] = v0[0] + f; + result[1] = v0[1] + f; + result[2] = v0[2] + f; + return result; +} + +mfloat_t *vec3_subtract(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1) +{ + result[0] = v0[0] - v1[0]; + result[1] = v0[1] - v1[1]; + result[2] = v0[2] - v1[2]; + return result; +} + +mfloat_t *vec3_subtract_f(mfloat_t * result, const mfloat_t * v0, + const mfloat_t f) +{ + result[0] = v0[0] - f; + result[1] = v0[1] - f; + result[2] = v0[2] - f; + return result; +} + +mfloat_t *vec3_multiply(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1) +{ + result[0] = v0[0] * v1[0]; + result[1] = v0[1] * v1[1]; + result[2] = v0[2] * v1[2]; + return result; +} + +mfloat_t *vec3_multiply_f(mfloat_t * result, const mfloat_t * v0, + const mfloat_t f) +{ + result[0] = v0[0] * f; + result[1] = v0[1] * f; + result[2] = v0[2] * f; + return result; +} + +mfloat_t *vec3_multiply_mat3(mfloat_t * result, mfloat_t * v0, + mfloat_t * m0) +{ + mfloat_t x = v0[0]; + mfloat_t y = v0[1]; + mfloat_t z = v0[2]; + result[0] = m0[0] * x + m0[3] * y + m0[6] * z; + result[1] = m0[1] * x + m0[4] * y + m0[7] * z; + result[2] = m0[2] * x + m0[5] * y + m0[8] * z; + return result; +} + +mfloat_t *vec3_divide(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] / v1[0]; + result[1] = v0[1] / v1[1]; + result[2] = v0[2] / v1[2]; + return result; +} + +mfloat_t *vec3_divide_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] / f; + result[1] = v0[1] / f; + result[2] = v0[2] / f; + return result; +} + +mfloat_t *vec3_snap(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFLOOR(v0[0] / v1[0]) * v1[0]; + result[1] = MFLOOR(v0[1] / v1[1]) * v1[1]; + result[2] = MFLOOR(v0[2] / v1[2]) * v1[2]; + return result; +} + +mfloat_t *vec3_snap_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = MFLOOR(v0[0] / f) * f; + result[1] = MFLOOR(v0[1] / f) * f; + result[2] = MFLOOR(v0[2] / f) * f; + return result; +} + +mfloat_t *vec3_negative(mfloat_t * result, mfloat_t * v0) +{ + result[0] = -v0[0]; + result[1] = -v0[1]; + result[2] = -v0[2]; + return result; +} + +mfloat_t *vec3_abs(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MFABS(v0[0]); + result[1] = MFABS(v0[1]); + result[2] = MFABS(v0[2]); + return result; +} + +mfloat_t *vec3_floor(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MFLOOR(v0[0]); + result[1] = MFLOOR(v0[1]); + result[2] = MFLOOR(v0[2]); + return result; +} + +mfloat_t *vec3_ceil(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MCEIL(v0[0]); + result[1] = MCEIL(v0[1]); + result[2] = MCEIL(v0[2]); + return result; +} + +mfloat_t *vec3_round(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MROUND(v0[0]); + result[1] = MROUND(v0[1]); + result[2] = MROUND(v0[2]); + return result; +} + +mfloat_t *vec3_max(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFMAX(v0[0], v1[0]); + result[1] = MFMAX(v0[1], v1[1]); + result[2] = MFMAX(v0[2], v1[2]); + return result; +} + +mfloat_t *vec3_min(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFMIN(v0[0], v1[0]); + result[1] = MFMIN(v0[1], v1[1]); + result[2] = MFMIN(v0[2], v1[2]); + return result; +} + +mfloat_t *vec3_clamp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2) +{ + vec3_min(result, v0, v1); + vec3_max(result, v0, v2); + return result; +} + +mfloat_t *vec3_cross(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1) +{ + + result[0] = v0[1] * v1[2] - v0[2] * v1[1]; + result[1] = v0[2] * v1[0] - v0[0] * v1[2]; + result[2] = v0[0] * v1[1] - v0[1] * v1[0]; + return result; +} + +mfloat_t *vec3_normalize(mfloat_t * result, mfloat_t * v0) +{ + mfloat_t l = MSQRT(v0[0] * v0[0] + v0[1] * v0[1] + v0[2] * v0[2]); + result[0] = v0[0] / l; + result[1] = v0[1] / l; + result[2] = v0[2] / l; + return result; +} + +mfloat_t vec3_dot(const mfloat_t * v0, const mfloat_t * v1) +{ + return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2]; +} + +mfloat_t *vec3_project(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + mfloat_t d = vec3_dot(v1, v1); + mfloat_t s = vec3_dot(v0, v1) / d; + result[0] = v1[0] * s; + result[1] = v1[1] * s; + result[2] = v1[2] * s; + return result; +} + +mfloat_t *vec3_slide(mfloat_t * result, mfloat_t * v0, mfloat_t * normal) +{ + mfloat_t d = vec3_dot(v0, normal); + result[0] = v0[0] - normal[0] * d; + result[1] = v0[1] - normal[1] * d; + result[2] = v0[2] - normal[2] * d; + return result; +} + +mfloat_t *vec3_reflect(mfloat_t * result, mfloat_t * v0, mfloat_t * normal) +{ + mfloat_t d = MFLOAT_C(2.0) * vec3_dot(v0, normal); + result[0] = normal[0] * d - v0[0]; + result[1] = normal[1] * d - v0[1]; + result[2] = normal[2] * d - v0[2]; + return result; +} + +mfloat_t *vec3_rotate(mfloat_t * result, mfloat_t * v0, mfloat_t * ra, + mfloat_t f) +{ + mfloat_t cs; + mfloat_t sn; + mfloat_t x; + mfloat_t y; + mfloat_t z; + mfloat_t rx; + mfloat_t ry; + mfloat_t rz; + cs = MCOS(f); + sn = MSIN(f); + x = v0[0]; + y = v0[1]; + z = v0[2]; + vec3_normalize(ra, ra); + rx = ra[0]; + ry = ra[1]; + rz = ra[2]; + result[0] = + x * (cs + rx * rx * (1 - cs)) + y * (rx * ry * (1 - cs) - + rz * sn) + z * (rx * rz * (1 - + cs) + + ry * sn); + result[1] = + x * (ry * rx * (1 - cs) + rz * sn) + y * (cs + + ry * ry * (1 - cs)) + + z * (ry * rz * (1 - cs) - rx * sn); + result[2] = + x * (rz * rx * (1 - cs) - ry * sn) + y * (rz * ry * (1 - cs) + + rx * sn) + z * (cs + + rz * rz * + (1 - + cs)); + return result; +} + +mfloat_t *vec3_lerp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t f) +{ + result[0] = v0[0] + (v1[0] - v0[0]) * f; + result[1] = v0[1] + (v1[1] - v0[1]) * f; + result[2] = v0[2] + (v1[2] - v0[2]) * f; + return result; +} + +mfloat_t *vec3_bezier3(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t f) +{ + mfloat_t tmp0[VEC3_SIZE]; + mfloat_t tmp1[VEC3_SIZE]; + vec3_lerp(tmp0, v0, v1, f); + vec3_lerp(tmp1, v1, v2, f); + vec3_lerp(result, tmp0, tmp1, f); + return result; +} + +mfloat_t *vec3_bezier4(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t * v3, mfloat_t f) +{ + mfloat_t tmp0[VEC3_SIZE]; + mfloat_t tmp1[VEC3_SIZE]; + mfloat_t tmp2[VEC3_SIZE]; + mfloat_t tmp3[VEC3_SIZE]; + mfloat_t tmp4[VEC3_SIZE]; + vec3_lerp(tmp0, v0, v1, f); + vec3_lerp(tmp1, v1, v2, f); + vec3_lerp(tmp2, v2, v3, f); + vec3_lerp(tmp3, tmp0, tmp1, f); + vec3_lerp(tmp4, tmp1, tmp2, f); + vec3_lerp(result, tmp3, tmp4, f); + return result; +} + +mfloat_t vec3_length(mfloat_t * v0) +{ + return MSQRT(v0[0] * v0[0] + v0[1] * v0[1] + v0[2] * v0[2]); +} + +mfloat_t vec3_length_squared(mfloat_t * v0) +{ + return v0[0] * v0[0] + v0[1] * v0[1] + v0[2] * v0[2]; +} + +mfloat_t vec3_distance(mfloat_t * v0, mfloat_t * v1) +{ + return MSQRT((v0[0] - v1[0]) * (v0[0] - v1[0]) + + (v0[1] - v1[1]) * (v0[1] - v1[1]) + (v0[2] - + v1[2]) * (v0[2] - + v1[2])); +} + +mfloat_t vec3_distance_squared(mfloat_t * v0, mfloat_t * v1) +{ + return (v0[0] - v1[0]) * (v0[0] - v1[0]) + (v0[1] - v1[1]) * (v0[1] - + v1[1]) + + (v0[2] - v1[2]) * (v0[2] - v1[2]); +} + +bool vec3_linear_independent(mfloat_t * v0, mfloat_t * v1, mfloat_t * v2) +{ + return v0[0] * v1[1] * v2[2] + v0[1] * v1[2] * v2[0] + + v0[2] * v1[0] * v2[1] + - v0[2] * v1[1] * v2[0] - v0[1] * v1[0] * v2[2] - + v0[0] * v1[2] * v2[1]; +} + +mfloat_t **vec3_orthonormalization(mfloat_t result[3][3], + mfloat_t basis[3][3]) +{ + mfloat_t v0[3]; + mfloat_t v1[3]; + mfloat_t v2[3]; + + for (int32_t i = 0; i < 3; ++i) { + v0[i] = basis[0][i]; + v1[i] = basis[1][i]; + v2[i] = basis[2][i]; + } + + if (!vec3_linear_independent(v0, v1, v2)) { + return (mfloat_t **) result; + } + + mfloat_t proj[3]; + mfloat_t u0[3]; + mfloat_t u1[3]; + mfloat_t u2[3]; + + for (int32_t i = 0; i < 3; ++i) { + u0[i] = v0[i]; + } + + vec3_project(proj, v1, u0); + vec3_subtract(u1, v1, proj); + + vec3_project(proj, v2, u0); + vec3_subtract(u2, v2, proj); + vec3_project(proj, v2, u1); + vec3_subtract(u2, u2, proj); + + vec3_normalize(result[0], u0); + vec3_normalize(result[1], u1); + vec3_normalize(result[2], u2); + + return (mfloat_t **) result; +} + + +mfloat_t *vec3_rotate_quat(mfloat_t * result, const mfloat_t * v, + const mfloat_t * q) +{ + mfloat_t qi[4]; + quat_conjugate(qi, q); + + mfloat_t vq[4] = { 0 }; + vq[0] = v[0]; + vq[1] = v[1]; + vq[2] = v[2]; + + quat_multiply(vq, q, vq); + quat_multiply(vq, vq, qi); + + result[0] = vq[0]; + result[1] = vq[1]; + result[2] = vq[2]; + return result; +} + + +bool vec4_is_zero(mfloat_t * v0) +{ + return MFABS(v0[0]) < MFLT_EPSILON && MFABS(v0[1]) < MFLT_EPSILON + && MFABS(v0[2]) < MFLT_EPSILON && MFABS(v0[3]) < MFLT_EPSILON; +} + +bool vec4_is_equal(mfloat_t * v0, mfloat_t * v1) +{ + return MFABS(v0[0] - v1[0]) < MFLT_EPSILON + && MFABS(v0[1] - v1[1]) < MFLT_EPSILON + && MFABS(v0[2] - v1[2]) < MFLT_EPSILON + && MFABS(v0[3] - v1[3]) < MFLT_EPSILON; +} + +mfloat_t *vec4(mfloat_t * result, mfloat_t x, mfloat_t y, mfloat_t z, + mfloat_t w) +{ + result[0] = x; + result[1] = y; + result[2] = z; + result[3] = w; + return result; +} + +mfloat_t *vec4_assign(mfloat_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + result[3] = v0[3]; + return result; +} + +#if defined(MATHC_USE_INT) +mfloat_t *vec4_assign_vec4i(mfloat_t * result, mint_t * v0) +{ + result[0] = v0[0]; + result[1] = v0[1]; + result[2] = v0[2]; + result[3] = v0[3]; + return result; +} +#endif + +mfloat_t *vec4_zero(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *vec4_one(mfloat_t * result) +{ + result[0] = MFLOAT_C(1.0); + result[1] = MFLOAT_C(1.0); + result[2] = MFLOAT_C(1.0); + result[3] = MFLOAT_C(1.0); + return result; +} + +mfloat_t *vec4_sign(mfloat_t * result, mfloat_t * v0) +{ + if (v0[0] > MFLOAT_C(0.0)) { + result[0] = MFLOAT_C(1.0); + } else if (v0[0] < 0) { + result[0] = -MFLOAT_C(1.0); + } else { + result[0] = MFLOAT_C(0.0); + } + if (v0[1] > MFLOAT_C(0.0)) { + result[1] = MFLOAT_C(1.0); + } else if (v0[1] < 0) { + result[1] = -MFLOAT_C(1.0); + } else { + result[1] = MFLOAT_C(0.0); + } + if (v0[2] > MFLOAT_C(0.0)) { + result[2] = MFLOAT_C(1.0); + } else if (v0[2] < 0) { + result[2] = -MFLOAT_C(1.0); + } else { + result[2] = MFLOAT_C(0.0); + } + if (v0[3] > MFLOAT_C(0.0)) { + result[3] = MFLOAT_C(1.0); + } else if (v0[3] < 0) { + result[3] = -MFLOAT_C(1.0); + } else { + result[3] = MFLOAT_C(0.0); + } + return result; +} + +mfloat_t *vec4_add(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] + v1[0]; + result[1] = v0[1] + v1[1]; + result[2] = v0[2] + v1[2]; + result[3] = v0[3] + v1[3]; + return result; +} + +mfloat_t *vec4_add_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] + f; + result[1] = v0[1] + f; + result[2] = v0[2] + f; + result[3] = v0[3] + f; + return result; +} + +mfloat_t *vec4_subtract(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] - v1[0]; + result[1] = v0[1] - v1[1]; + result[2] = v0[2] - v1[2]; + result[3] = v0[3] - v1[3]; + return result; +} + +mfloat_t *vec4_subtract_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] - f; + result[1] = v0[1] - f; + result[2] = v0[2] - f; + result[3] = v0[3] - f; + return result; +} + +mfloat_t *vec4_multiply(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] * v1[0]; + result[1] = v0[1] * v1[1]; + result[2] = v0[2] * v1[2]; + result[3] = v0[3] * v1[3]; + return result; +} + +mfloat_t *vec4_multiply_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] * f; + result[1] = v0[1] * f; + result[2] = v0[2] * f; + result[3] = v0[3] * f; + return result; +} + +mfloat_t *vec4_multiply_mat4(mfloat_t * result, mfloat_t * v0, + mfloat_t * m0) +{ + mfloat_t x = v0[0]; + mfloat_t y = v0[1]; + mfloat_t z = v0[2]; + mfloat_t w = v0[3]; + result[0] = m0[0] * x + m0[4] * y + m0[8] * z + m0[12] * w; + result[1] = m0[1] * x + m0[5] * y + m0[9] * z + m0[13] * w; + result[2] = m0[2] * x + m0[6] * y + m0[10] * z + m0[14] * w; + result[3] = m0[3] * x + m0[7] * y + m0[11] * z + m0[15] * w; + return result; +} + +mfloat_t *vec4_divide(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = v0[0] / v1[0]; + result[1] = v0[1] / v1[1]; + result[2] = v0[2] / v1[2]; + result[3] = v0[3] / v1[3]; + return result; +} + +mfloat_t *vec4_divide_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = v0[0] / f; + result[1] = v0[1] / f; + result[2] = v0[2] / f; + result[3] = v0[3] / f; + return result; +} + +mfloat_t *vec4_snap(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFLOOR(v0[0] / v1[0]) * v1[0]; + result[1] = MFLOOR(v0[1] / v1[1]) * v1[1]; + result[2] = MFLOOR(v0[2] / v1[2]) * v1[2]; + result[3] = MFLOOR(v0[3] / v1[3]) * v1[3]; + return result; +} + +mfloat_t *vec4_snap_f(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + result[0] = MFLOOR(v0[0] / f) * f; + result[1] = MFLOOR(v0[1] / f) * f; + result[2] = MFLOOR(v0[2] / f) * f; + result[3] = MFLOOR(v0[3] / f) * f; + return result; +} + +mfloat_t *vec4_negative(mfloat_t * result, mfloat_t * v0) +{ + result[0] = -v0[0]; + result[1] = -v0[1]; + result[2] = -v0[2]; + result[3] = -v0[3]; + return result; +} + +mfloat_t *vec4_abs(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MFABS(v0[0]); + result[1] = MFABS(v0[1]); + result[2] = MFABS(v0[2]); + result[3] = MFABS(v0[3]); + return result; +} + +mfloat_t *vec4_floor(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MFLOOR(v0[0]); + result[1] = MFLOOR(v0[1]); + result[2] = MFLOOR(v0[2]); + result[3] = MFLOOR(v0[3]); + return result; +} + +mfloat_t *vec4_ceil(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MCEIL(v0[0]); + result[1] = MCEIL(v0[1]); + result[2] = MCEIL(v0[2]); + result[3] = MCEIL(v0[3]); + return result; +} + +mfloat_t *vec4_round(mfloat_t * result, mfloat_t * v0) +{ + result[0] = MROUND(v0[0]); + result[1] = MROUND(v0[1]); + result[2] = MROUND(v0[2]); + result[3] = MROUND(v0[3]); + return result; +} + +mfloat_t *vec4_max(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFMAX(v0[0], v1[0]); + result[1] = MFMAX(v0[1], v1[1]); + result[2] = MFMAX(v0[2], v1[2]); + result[3] = MFMAX(v0[3], v1[3]); + return result; +} + +mfloat_t *vec4_min(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + result[0] = MFMIN(v0[0], v1[0]); + result[1] = MFMIN(v0[1], v1[1]); + result[2] = MFMIN(v0[2], v1[2]); + result[3] = MFMIN(v0[3], v1[3]); + return result; +} + +mfloat_t *vec4_clamp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2) +{ + vec4_min(result, v0, v1); + vec4_max(result, v0, v2); + return result; +} + +mfloat_t *vec4_normalize(mfloat_t * result, mfloat_t * v0) +{ + mfloat_t l = + MSQRT(v0[0] * v0[0] + v0[1] * v0[1] + v0[2] * v0[2] + + v0[3] * v0[3]); + result[0] = v0[0] / l; + result[1] = v0[1] / l; + result[2] = v0[2] / l; + result[3] = v0[3] / l; + return result; +} + +mfloat_t *vec4_lerp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t f) +{ + result[0] = v0[0] + (v1[0] - v0[0]) * f; + result[1] = v0[1] + (v1[1] - v0[1]) * f; + result[2] = v0[2] + (v1[2] - v0[2]) * f; + result[3] = v0[3] + (v1[3] - v0[3]) * f; + return result; +} + +bool quat_is_zero(mfloat_t * q0) +{ + return MFABS(q0[0]) < MFLT_EPSILON && MFABS(q0[1]) < MFLT_EPSILON + && MFABS(q0[2]) < MFLT_EPSILON && MFABS(q0[3]) < MFLT_EPSILON; +} + +bool quat_is_equal(mfloat_t * q0, mfloat_t * q1) +{ + return MFABS(q0[0] - q1[0]) < MFLT_EPSILON + && MFABS(q0[1] - q1[1]) < MFLT_EPSILON + && MFABS(q0[2] - q1[2]) < MFLT_EPSILON + && MFABS(q0[3] - q1[3]) < MFLT_EPSILON; +} + +mfloat_t *quat(mfloat_t * result, mfloat_t x, mfloat_t y, mfloat_t z, + mfloat_t w) +{ + result[0] = x; + result[1] = y; + result[2] = z; + result[3] = w; + return result; +} + +mfloat_t *quat_assign(mfloat_t * result, mfloat_t * q0) +{ + result[0] = q0[0]; + result[1] = q0[1]; + result[2] = q0[2]; + result[3] = q0[3]; + return result; +} + +mfloat_t *quat_zero(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *quat_null(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(1.0); + return result; +} + +/* Grassman product */ +mfloat_t *quat_multiply(mfloat_t * result, const mfloat_t * q0, + const mfloat_t * q1) +{ + result[0] = + q0[3] * q1[0] + q0[0] * q1[3] + q0[1] * q1[2] - q0[2] * q1[1]; + result[1] = + q0[3] * q1[1] + q0[1] * q1[3] + q0[2] * q1[0] - q0[0] * q1[2]; + result[2] = + q0[3] * q1[2] + q0[2] * q1[3] + q0[0] * q1[1] - q0[1] * q1[0]; + result[3] = + q0[3] * q1[3] - q0[0] * q1[0] - q0[1] * q1[1] - q0[2] * q1[2]; + return result; +} + +mfloat_t *quat_mult_dir3(mfloat_t * result, const mfloat_t * q, + const mfloat_t * v) +{ + result[0] = q[3] * v[0] + q[0] + q[1] * v[2] - q[2] * v[1]; + result[1] = q[3] * v[1] + q[1] + q[2] * v[0] - q[0] * v[2]; + result[2] = q[3] * v[2] + q[2] + q[0] * v[1] - q[1] * v[0]; + result[3] = q[3] - q[0] * v[0] - q[1] * v[1] - q[2] * v[2]; + return result; +} + +mfloat_t *quat_mult_3d(mfloat_t * result, const mfloat_t * q, + const mfloat_t * p) +{ + result[0] = q[3] * p[0] + q[1] * p[2] - q[2] * p[1]; + result[1] = q[3] * p[1] + q[2] * p[0] - q[0] * p[2]; + result[2] = q[3] * p[2] + q[0] * p[1] - q[1] * p[0]; + result[3] = 0 - q[0] * p[0] - q[1] * p[1] - q[2] * p[2]; + return result; +} + +mfloat_t *quat_multiply_f(mfloat_t * result, mfloat_t * q0, mfloat_t f) +{ + result[0] = q0[0] * f; + result[1] = q0[1] * f; + result[2] = q0[2] * f; + result[3] = q0[3] * f; + return result; +} + +mfloat_t *quat_divide(mfloat_t * result, mfloat_t * q0, mfloat_t * q1) +{ + mfloat_t x = q0[0]; + mfloat_t y = q0[1]; + mfloat_t z = q0[2]; + mfloat_t w = q0[3]; + mfloat_t ls = + q1[0] * q1[0] + q1[1] * q1[1] + q1[8] * q1[8] + q1[3] * q1[3]; + mfloat_t normalized_x = -q1[0] / ls; + mfloat_t normalized_y = -q1[1] / ls; + mfloat_t normalized_z = -q1[8] / ls; + mfloat_t normalized_w = q1[3] / ls; + result[0] = + x * normalized_w + normalized_x * w + (y * normalized_z - + z * normalized_y); + result[1] = + y * normalized_w + normalized_y * w + (z * normalized_x - + x * normalized_z); + result[2] = + z * normalized_w + normalized_z * w + (x * normalized_y - + y * normalized_x); + result[3] = + w * normalized_w - (x * normalized_x + y * normalized_y + + z * normalized_z); + return result; +} + +mfloat_t *quat_divide_f(mfloat_t * result, mfloat_t * q0, mfloat_t f) +{ + result[0] = q0[0] / f; + result[1] = q0[1] / f; + result[2] = q0[2] / f; + result[3] = q0[3] / f; + return result; +} + +mfloat_t *quat_negative(mfloat_t * result, mfloat_t * q0) +{ + result[0] = -q0[0]; + result[1] = -q0[1]; + result[2] = -q0[2]; + result[3] = -q0[3]; + return result; +} + +mfloat_t *quat_conjugate(mfloat_t * result, const mfloat_t * q0) +{ + result[0] = -q0[0]; + result[1] = -q0[1]; + result[2] = -q0[2]; + result[3] = q0[3]; + return result; +} + +mfloat_t *quat_inverse(mfloat_t * result, mfloat_t * q0) +{ + mfloat_t l = + MFLOAT_C(1.0) / (q0[0] * q0[0] + q0[1] * q0[1] + q0[2] * q0[2] + + q0[3] * q0[3]); + result[0] = -q0[0] * l; + result[1] = -q0[1] * l; + result[2] = -q0[2] * l; + result[3] = q0[3] * l; + return result; +} + +mfloat_t *quat_normalize(mfloat_t * result, mfloat_t * q0) +{ + mfloat_t l = + MFLOAT_C(1.0) / MSQRT(q0[0] * q0[0] + q0[1] * q0[1] + + q0[2] * q0[2] + q0[3] * q0[3]); + result[0] = q0[0] * l; + result[1] = q0[1] * l; + result[2] = q0[2] * l; + result[3] = q0[3] * l; + return result; +} + +mfloat_t quat_dot(mfloat_t * q0, mfloat_t * q1) +{ + return q0[0] * q1[0] + q0[1] * q1[1] + q0[2] * q1[2] + q0[3] * q1[3]; +} + +mfloat_t *quat_power(mfloat_t * result, mfloat_t * q0, mfloat_t exponent) +{ + if (MFABS(q0[3]) < MFLOAT_C(1.0) - MFLT_EPSILON) { + mfloat_t alpha = MACOS(q0[3]); + mfloat_t new_alpha = alpha * exponent; + mfloat_t s = MSIN(new_alpha) / MSIN(alpha); + result[0] = result[0] * s; + result[1] = result[1] * s; + result[2] = result[2] * s; + result[3] = MCOS(new_alpha); + } else { + result[0] = q0[0]; + result[1] = q0[1]; + result[2] = q0[1]; + result[3] = q0[3]; + } + return result; +} + +mfloat_t *quat_from_axis_angle(mfloat_t * result, const mfloat_t * v0, + const mfloat_t angle) +{ + mfloat_t half = angle * MFLOAT_C(0.5); + mfloat_t s = MSIN(half); + result[0] = v0[0] * s; + result[1] = v0[1] * s; + result[2] = v0[2] * s; + result[3] = MCOS(half); + return result; +} + +mfloat_t *quat_from_vec3(mfloat_t * result, mfloat_t * v0, mfloat_t * v1) +{ + mfloat_t cross[VEC3_SIZE]; + mfloat_t d = vec3_dot(v0, v1); + mfloat_t a_ls = vec3_length_squared(v0); + mfloat_t b_ls = vec3_length_squared(v0); + vec3_cross(cross, v0, v1); + quat(result, cross[0], cross[1], cross[1], d + MSQRT(a_ls * b_ls)); + quat_normalize(result, result); + return result; +} + +mfloat_t *quat_from_euler(mfloat_t * q, const mfloat_t * euler) +{ + mfloat_t qx[4], qy[4], qz[4]; + quat_from_axis_angle(qx, RIGHT, euler[0]); + quat_from_axis_angle(qy, UP, euler[1]); + quat_from_axis_angle(qz, FORWARD, euler[2]); + return quat_multiply(q, qx, quat_multiply(q, qy, qz)); +} + +mfloat_t *quat_from_mat4(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t scale = m0[0] + m0[5] + m0[10]; + if (scale > MFLOAT_C(0.0)) { + mfloat_t sr = MSQRT(scale + MFLOAT_C(1.0)); + result[3] = sr * MFLOAT_C(0.5); + sr = MFLOAT_C(0.5) / sr; + result[0] = (m0[9] - m0[6]) * sr; + result[1] = (m0[2] - m0[8]) * sr; + result[2] = (m0[4] - m0[1]) * sr; + } else if ((m0[0] >= m0[5]) && (m0[0] >= m0[10])) { + mfloat_t sr = MSQRT(MFLOAT_C(1.0) + m0[0] - m0[5] - m0[10]); + mfloat_t half = MFLOAT_C(0.5) / sr; + result[0] = MFLOAT_C(0.5) * sr; + result[1] = (m0[4] + m0[1]) * half; + result[2] = (m0[8] + m0[2]) * half; + result[3] = (m0[9] - m0[6]) * half; + } else if (m0[5] > m0[10]) { + mfloat_t sr = MSQRT(MFLOAT_C(1.0) + m0[5] - m0[0] - m0[10]); + mfloat_t half = MFLOAT_C(0.5) / sr; + result[0] = (m0[1] + m0[4]) * half; + result[1] = MFLOAT_C(0.5) * sr; + result[2] = (m0[6] + m0[9]) * half; + result[3] = (m0[2] - m0[8]) * half; + } else { + mfloat_t sr = MSQRT(MFLOAT_C(1.0) + m0[10] - m0[0] - m0[5]); + mfloat_t half = MFLOAT_C(0.5) / sr; + result[0] = (m0[2] + m0[8]) * half; + result[1] = (m0[6] + m0[9]) * half; + result[2] = MFLOAT_C(0.5) * sr; + result[3] = (m0[4] - m0[1]) * half; + } + return result; +} + +mfloat_t *quat_lerp(mfloat_t * result, mfloat_t * q0, mfloat_t * q1, + mfloat_t f) +{ + result[0] = q0[0] + (q1[0] - q0[0]) * f; + result[1] = q0[1] + (q1[1] - q0[1]) * f; + result[2] = q0[2] + (q1[2] - q0[2]) * f; + result[3] = q0[3] + (q1[3] - q0[3]) * f; + return result; +} + +mfloat_t *quat_slerp(mfloat_t * result, mfloat_t * q0, mfloat_t * q1, + mfloat_t f) +{ + mfloat_t tmp1[QUAT_SIZE]; + mfloat_t d = quat_dot(q0, q1); + mfloat_t f0; + mfloat_t f1; + quat_assign(tmp1, q1); + if (d < MFLOAT_C(0.0)) { + quat_negative(tmp1, tmp1); + d = -d; + } + if (d > MFLOAT_C(0.9995)) { + f0 = MFLOAT_C(1.0) - f; + f1 = f; + } else { + mfloat_t theta = MACOS(d); + mfloat_t sin_theta = MSIN(theta); + f0 = MSIN((MFLOAT_C(1.0) - f) * theta) / sin_theta; + f1 = MSIN(f * theta) / sin_theta; + } + result[0] = q0[0] * f0 + tmp1[0] * f1; + result[1] = q0[1] * f0 + tmp1[1] * f1; + result[2] = q0[2] * f0 + tmp1[2] * f1; + result[3] = q0[3] * f0 + tmp1[3] * f1; + return result; +} + +mfloat_t quat_length(mfloat_t * q0) +{ + return MSQRT(q0[0] * q0[0] + q0[1] * q0[1] + q0[2] * q0[2] + + q0[3] * q0[3]); +} + +mfloat_t quat_length_squared(mfloat_t * q0) +{ + return q0[0] * q0[0] + q0[1] * q0[1] + q0[2] * q0[2] + q0[3] * q0[3]; +} + +mfloat_t quat_angle(mfloat_t * q0, mfloat_t * q1) +{ + mfloat_t s = MSQRT(quat_length_squared(q0) * quat_length_squared(q1)); + s = MFLOAT_C(1.0) / s; + return MACOS(quat_dot(q0, q1) * s); +} + +mfloat_t *mat2(mfloat_t * result, mfloat_t m11, mfloat_t m12, mfloat_t m21, + mfloat_t m22) +{ + result[0] = m11; + result[1] = m21; + result[2] = m12; + result[3] = m22; + return result; +} + +mfloat_t *mat2_zero(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *mat2_identity(mfloat_t * result) +{ + result[0] = MFLOAT_C(1.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(1.0); + return result; +} + +mfloat_t mat2_determinant(mfloat_t * m0) +{ + return m0[0] * m0[3] - m0[2] * m0[1]; +} + +mfloat_t *mat2_assign(mfloat_t * result, mfloat_t * m0) +{ + result[0] = m0[0]; + result[1] = m0[1]; + result[2] = m0[2]; + result[3] = m0[3]; + return result; +} + +mfloat_t *mat2_negative(mfloat_t * result, mfloat_t * m0) +{ + result[0] = -m0[0]; + result[1] = -m0[1]; + result[2] = -m0[2]; + result[3] = -m0[3]; + return result; +} + +mfloat_t *mat2_transpose(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t transposed[MAT2_SIZE]; + transposed[0] = m0[0]; + transposed[1] = m0[2]; + transposed[2] = m0[1]; + transposed[3] = m0[3]; + result[0] = transposed[0]; + result[1] = transposed[1]; + result[2] = transposed[2]; + result[3] = transposed[3]; + return result; +} + +mfloat_t *mat2_cofactor(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t cofactor[MAT2_SIZE]; + cofactor[0] = m0[3]; + cofactor[1] = -m0[2]; + cofactor[2] = -m0[1]; + cofactor[3] = m0[0]; + result[0] = cofactor[0]; + result[1] = cofactor[1]; + result[2] = cofactor[2]; + result[3] = cofactor[3]; + return result; +} + +mfloat_t *mat2_adjugate(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t adjugate[MAT2_SIZE]; + adjugate[0] = m0[3]; + adjugate[1] = -m0[1]; + adjugate[2] = -m0[2]; + adjugate[3] = m0[0]; + result[0] = adjugate[0]; + result[1] = adjugate[1]; + result[2] = adjugate[2]; + result[3] = adjugate[3]; + return result; +} + +mfloat_t *mat2_multiply(mfloat_t * result, mfloat_t * m0, mfloat_t * m1) +{ + mfloat_t multiplied[MAT3_SIZE]; + multiplied[0] = m0[0] * m1[0] + m0[2] * m1[1]; + multiplied[1] = m0[1] * m1[0] + m0[3] * m1[1]; + multiplied[2] = m0[0] * m1[2] + m0[2] * m1[3]; + multiplied[3] = m0[1] * m1[2] + m0[3] * m1[3]; + result[0] = multiplied[0]; + result[1] = multiplied[1]; + result[2] = multiplied[2]; + result[3] = multiplied[3]; + return result; +} + +mfloat_t *mat2_multiply_f(mfloat_t * result, mfloat_t * m0, mfloat_t f) +{ + result[0] = m0[0] * f; + result[1] = m0[1] * f; + result[2] = m0[2] * f; + result[3] = m0[3] * f; + return result; +} + +mfloat_t *mat2_inverse(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t inverse[MAT2_SIZE]; + mfloat_t det = mat2_determinant(m0); + mat2_cofactor(inverse, m0); + mat2_multiply_f(inverse, inverse, MFLOAT_C(1.0) / det); + result[0] = inverse[0]; + result[1] = inverse[1]; + result[2] = inverse[2]; + result[3] = inverse[3]; + return result; +} + +mfloat_t *mat2_scaling(mfloat_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[3] = v0[1]; + return result; +} + +mfloat_t *mat2_scale(mfloat_t * result, mfloat_t * m0, mfloat_t * v0) +{ + result[0] = m0[0] * v0[0]; + result[3] = m0[3] * v0[1]; + return result; +} + +mfloat_t *mat2_rotation_z(mfloat_t * result, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + result[0] = c; + result[1] = s; + result[2] = -s; + result[3] = c; + return result; +} + +mfloat_t *mat2_lerp(mfloat_t * result, mfloat_t * m0, mfloat_t * m1, + mfloat_t f) +{ + result[0] = m0[0] + (m1[0] - m0[0]) * f; + result[1] = m0[1] + (m1[1] - m0[1]) * f; + result[2] = m0[2] + (m1[2] - m0[2]) * f; + result[3] = m0[3] + (m1[3] - m0[3]) * f; + return result; +} + +mfloat_t *mat3(mfloat_t * result, mfloat_t m11, mfloat_t m12, mfloat_t m13, + mfloat_t m21, mfloat_t m22, mfloat_t m23, mfloat_t m31, + mfloat_t m32, mfloat_t m33) +{ + result[0] = m11; + result[1] = m21; + result[2] = m31; + result[3] = m12; + result[4] = m22; + result[5] = m32; + result[6] = m13; + result[7] = m23; + result[8] = m33; + return result; +} + +mfloat_t *mat3_zero(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(0.0); + result[5] = MFLOAT_C(0.0); + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *mat3_identity(mfloat_t * result) +{ + result[0] = MFLOAT_C(1.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(1.0); + result[5] = MFLOAT_C(0.0); + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(1.0); + return result; +} + +mfloat_t mat3_determinant(mfloat_t * m0) +{ + mfloat_t m11 = m0[0]; + mfloat_t m21 = m0[1]; + mfloat_t m31 = m0[2]; + mfloat_t m12 = m0[3]; + mfloat_t m22 = m0[4]; + mfloat_t m32 = m0[5]; + mfloat_t m13 = m0[6]; + mfloat_t m23 = m0[7]; + mfloat_t m33 = m0[8]; + mfloat_t determinant = m11 * m22 * m33 + + m12 * m23 * m31 + + m13 * m21 * m32 + - m11 * m23 * m32 - m12 * m21 * m33 - m13 * m22 * m31; + return determinant; +} + +mfloat_t *mat3_assign(mfloat_t * result, mfloat_t * m0) +{ + result[0] = m0[0]; + result[1] = m0[1]; + result[2] = m0[2]; + result[3] = m0[3]; + result[4] = m0[4]; + result[5] = m0[5]; + result[6] = m0[6]; + result[7] = m0[7]; + result[8] = m0[8]; + return result; +} + +mfloat_t *mat3_negative(mfloat_t * result, mfloat_t * m0) +{ + result[0] = -m0[0]; + result[1] = -m0[1]; + result[2] = -m0[2]; + result[3] = -m0[3]; + result[4] = -m0[4]; + result[5] = -m0[5]; + result[6] = -m0[6]; + result[7] = -m0[7]; + result[8] = -m0[8]; + return result; +} + +mfloat_t *mat3_transpose(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t transposed[MAT4_SIZE]; + transposed[0] = m0[0]; + transposed[1] = m0[3]; + transposed[2] = m0[6]; + transposed[3] = m0[1]; + transposed[4] = m0[4]; + transposed[5] = m0[7]; + transposed[6] = m0[2]; + transposed[7] = m0[5]; + transposed[8] = m0[8]; + result[0] = transposed[0]; + result[1] = transposed[1]; + result[2] = transposed[2]; + result[3] = transposed[3]; + result[4] = transposed[4]; + result[5] = transposed[5]; + result[6] = transposed[6]; + result[7] = transposed[7]; + result[8] = transposed[8]; + return result; +} + +mfloat_t *mat3_cofactor(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t cofactor[MAT3_SIZE]; + mfloat_t minor[MAT2_SIZE]; + minor[0] = m0[4]; + minor[1] = m0[5]; + minor[2] = m0[7]; + minor[3] = m0[8]; + cofactor[0] = mat2_determinant(minor); + minor[0] = m0[3]; + minor[1] = m0[5]; + minor[2] = m0[6]; + minor[3] = m0[8]; + cofactor[1] = -mat2_determinant(minor); + minor[0] = m0[3]; + minor[1] = m0[4]; + minor[2] = m0[6]; + minor[3] = m0[7]; + cofactor[2] = mat2_determinant(minor); + minor[0] = m0[1]; + minor[1] = m0[2]; + minor[2] = m0[7]; + minor[3] = m0[8]; + cofactor[3] = -mat2_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[2]; + minor[2] = m0[6]; + minor[3] = m0[8]; + cofactor[4] = mat2_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[6]; + minor[3] = m0[7]; + cofactor[5] = -mat2_determinant(minor); + minor[0] = m0[1]; + minor[1] = m0[2]; + minor[2] = m0[4]; + minor[3] = m0[5]; + cofactor[6] = mat2_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[2]; + minor[2] = m0[3]; + minor[3] = m0[5]; + cofactor[7] = -mat2_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[3]; + minor[3] = m0[4]; + cofactor[8] = mat2_determinant(minor); + result[0] = cofactor[0]; + result[1] = cofactor[1]; + result[2] = cofactor[2]; + result[3] = cofactor[3]; + result[4] = cofactor[4]; + result[5] = cofactor[5]; + result[6] = cofactor[6]; + result[7] = cofactor[7]; + result[8] = cofactor[8]; + return result; +} + +mfloat_t *mat3_multiply(mfloat_t * result, mfloat_t * m0, mfloat_t * m1) +{ + mfloat_t multiplied[MAT3_SIZE]; + multiplied[0] = m0[0] * m1[0] + m0[3] * m1[1] + m0[6] * m1[2]; + multiplied[1] = m0[1] * m1[0] + m0[4] * m1[1] + m0[7] * m1[2]; + multiplied[2] = m0[2] * m1[0] + m0[5] * m1[1] + m0[8] * m1[2]; + multiplied[3] = m0[0] * m1[3] + m0[3] * m1[4] + m0[6] * m1[5]; + multiplied[4] = m0[1] * m1[3] + m0[4] * m1[4] + m0[7] * m1[5]; + multiplied[5] = m0[2] * m1[3] + m0[5] * m1[4] + m0[8] * m1[5]; + multiplied[6] = m0[0] * m1[6] + m0[3] * m1[7] + m0[6] * m1[8]; + multiplied[7] = m0[1] * m1[6] + m0[4] * m1[7] + m0[7] * m1[8]; + multiplied[8] = m0[2] * m1[6] + m0[5] * m1[7] + m0[8] * m1[8]; + result[0] = multiplied[0]; + result[1] = multiplied[1]; + result[2] = multiplied[2]; + result[3] = multiplied[3]; + result[4] = multiplied[4]; + result[5] = multiplied[5]; + result[6] = multiplied[6]; + result[7] = multiplied[7]; + result[8] = multiplied[8]; + return result; +} + +mfloat_t *mat3_multiply_f(mfloat_t * result, mfloat_t * m0, mfloat_t f) +{ + result[0] = m0[0] * f; + result[1] = m0[1] * f; + result[2] = m0[2] * f; + result[3] = m0[3] * f; + result[4] = m0[4] * f; + result[5] = m0[5] * f; + result[6] = m0[6] * f; + result[7] = m0[7] * f; + result[8] = m0[8] * f; + return result; +} + +mfloat_t *mat3_inverse(mfloat_t * result, mfloat_t * m0) +{ + result = m0; + return result; +} + +mfloat_t *mat3_scaling(mfloat_t * result, mfloat_t * v0) +{ + result[0] = v0[0]; + result[4] = v0[1]; + result[8] = v0[2]; + return result; +} + +mfloat_t *mat3_scale(mfloat_t * result, mfloat_t * m0, mfloat_t * v0) +{ + result[0] = m0[0] * v0[0]; + result[4] = m0[4] * v0[1]; + result[8] = m0[8] * v0[2]; + return result; +} + +mfloat_t *mat3_rotation_x(mfloat_t * result, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + result[4] = c; + result[5] = s; + result[7] = -s; + result[8] = c; + return result; +} + +mfloat_t *mat3_rotation_y(mfloat_t * result, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + result[0] = c; + result[2] = -s; + result[6] = s; + result[8] = c; + return result; +} + +mfloat_t *mat3_rotation_z(mfloat_t * result, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + result[0] = c; + result[1] = s; + result[3] = -s; + result[4] = c; + return result; +} + +mfloat_t *mat3_rotation_axis(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + mfloat_t one_c = MFLOAT_C(1.0) - c; + mfloat_t x = v0[0]; + mfloat_t y = v0[4]; + mfloat_t z = v0[8]; + mfloat_t xx = x * x; + mfloat_t xy = x * y; + mfloat_t xz = x * z; + mfloat_t yy = y * y; + mfloat_t yz = y * z; + mfloat_t zz = z * z; + mfloat_t l = xx + yy + zz; + mfloat_t sqrt_l = MSQRT(l); + result[0] = (xx + (yy + zz) * c) / l; + result[1] = (xy * one_c + v0[2] * sqrt_l * s) / l; + result[2] = (xz * one_c - v0[1] * sqrt_l * s) / l; + result[3] = (xy * one_c - v0[2] * sqrt_l * s) / l; + result[4] = (yy + (xx + zz) * c) / l; + result[5] = (yz * one_c + v0[0] * sqrt_l * s) / l; + result[6] = (xz * one_c + v0[1] * sqrt_l * s) / l; + result[7] = (yz * one_c - v0[0] * sqrt_l * s) / l; + result[8] = (zz + (xx + yy) * c) / l; + return result; +} + +mfloat_t *mat3_rotation_quat(mfloat_t * result, mfloat_t * q0) +{ + mfloat_t xx = q0[0] * q0[0]; + mfloat_t yy = q0[1] * q0[1]; + mfloat_t zz = q0[2] * q0[2]; + mfloat_t xy = q0[0] * q0[1]; + mfloat_t zw = q0[2] * q0[3]; + mfloat_t xz = q0[8] * q0[0]; + mfloat_t yw = q0[1] * q0[3]; + mfloat_t yz = q0[1] * q0[2]; + mfloat_t xw = q0[0] * q0[3]; + result[0] = MFLOAT_C(1.0) - MFLOAT_C(2.0) * (yy - zz); + result[1] = MFLOAT_C(2.0) * (xy + zw); + result[2] = MFLOAT_C(2.0) * (xz - yw); + result[3] = MFLOAT_C(2.0) * (xy - zw); + result[4] = MFLOAT_C(1.0) - MFLOAT_C(2.0) * (xx - zz); + result[5] = MFLOAT_C(2.0) * (yz + xw); + result[6] = MFLOAT_C(2.0) * (xz + yw); + result[7] = MFLOAT_C(2.0) * (yz - xw); + result[8] = MFLOAT_C(1.0) - MFLOAT_C(2.0) * (xx - yy); + return result; +} + +mfloat_t *mat3_lerp(mfloat_t * result, mfloat_t * m0, mfloat_t * m1, + mfloat_t f) +{ + result[0] = m0[0] + (m1[0] - m0[0]) * f; + result[1] = m0[1] + (m1[1] - m0[1]) * f; + result[2] = m0[2] + (m1[2] - m0[2]) * f; + result[3] = m0[3] + (m1[3] - m0[3]) * f; + result[4] = m0[4] + (m1[4] - m0[4]) * f; + result[5] = m0[5] + (m1[5] - m0[5]) * f; + result[6] = m0[6] + (m1[6] - m0[6]) * f; + result[7] = m0[7] + (m1[7] - m0[7]) * f; + result[8] = m0[8] + (m1[8] - m0[8]) * f; + return result; +} + +mfloat_t *mat4(mfloat_t * result, mfloat_t m11, mfloat_t m12, mfloat_t m13, + mfloat_t m14, mfloat_t m21, mfloat_t m22, mfloat_t m23, + mfloat_t m24, mfloat_t m31, mfloat_t m32, mfloat_t m33, + mfloat_t m34, mfloat_t m41, mfloat_t m42, mfloat_t m43, + mfloat_t m44) +{ + result[0] = m11; + result[1] = m21; + result[2] = m31; + result[3] = m41; + result[4] = m12; + result[5] = m22; + result[6] = m32; + result[7] = m42; + result[8] = m13; + result[9] = m23; + result[10] = m33; + result[11] = m43; + result[12] = m14; + result[13] = m24; + result[14] = m34; + result[15] = m44; + return result; +} + +mfloat_t *mat4_zero(mfloat_t * result) +{ + result[0] = MFLOAT_C(0.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(0.0); + result[5] = MFLOAT_C(0.0); + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(0.0); + result[9] = MFLOAT_C(0.0); + result[10] = MFLOAT_C(0.0); + result[11] = MFLOAT_C(0.0); + result[12] = MFLOAT_C(0.0); + result[13] = MFLOAT_C(0.0); + result[14] = MFLOAT_C(0.0); + result[15] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *mat4_identity(mfloat_t * result) +{ + result[0] = MFLOAT_C(1.0); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(0.0); + result[5] = MFLOAT_C(1.0); + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(0.0); + result[9] = MFLOAT_C(0.0); + result[10] = MFLOAT_C(1.0); + result[11] = MFLOAT_C(0.0); + result[12] = MFLOAT_C(0.0); + result[13] = MFLOAT_C(0.0); + result[14] = MFLOAT_C(0.0); + result[15] = MFLOAT_C(1.0); + return result; +} + +mfloat_t mat4_determinant(mfloat_t * m0) +{ + mfloat_t m11 = m0[0]; + mfloat_t m21 = m0[1]; + mfloat_t m31 = m0[2]; + mfloat_t m41 = m0[3]; + mfloat_t m12 = m0[4]; + mfloat_t m22 = m0[5]; + mfloat_t m32 = m0[6]; + mfloat_t m42 = m0[7]; + mfloat_t m13 = m0[8]; + mfloat_t m23 = m0[9]; + mfloat_t m33 = m0[10]; + mfloat_t m43 = m0[11]; + mfloat_t m14 = m0[12]; + mfloat_t m24 = m0[13]; + mfloat_t m34 = m0[14]; + mfloat_t m44 = m0[15]; + mfloat_t determinant = m14 * m23 * m32 * m41 - m13 * m24 * m32 * m41 + - m14 * m22 * m33 * m41 + m12 * m24 * m33 * m41 + + m13 * m22 * m34 * m41 - m12 * m23 * m34 * m41 + - m14 * m23 * m31 * m42 + m13 * m24 * m31 * m42 + + m14 * m21 * m33 * m42 - m11 * m24 * m33 * m42 + - m13 * m21 * m34 * m42 + m11 * m23 * m34 * m42 + + m14 * m22 * m31 * m43 - m12 * m24 * m31 * m43 + - m14 * m21 * m32 * m43 + m11 * m24 * m32 * m43 + + m12 * m21 * m34 * m43 - m11 * m22 * m34 * m43 + - m13 * m22 * m31 * m44 + m12 * m23 * m31 * m44 + + m13 * m21 * m32 * m44 - m11 * m23 * m32 * m44 + - m12 * m21 * m33 * m44 + m11 * m22 * m33 * m44; + return determinant; +} + +mfloat_t *mat4_assign(mfloat_t * result, mfloat_t * m0) +{ + result[0] = m0[0]; + result[1] = m0[1]; + result[2] = m0[2]; + result[3] = m0[3]; + result[4] = m0[4]; + result[5] = m0[5]; + result[6] = m0[6]; + result[7] = m0[7]; + result[8] = m0[8]; + result[9] = m0[9]; + result[10] = m0[10]; + result[11] = m0[11]; + result[12] = m0[12]; + result[13] = m0[13]; + result[14] = m0[14]; + result[15] = m0[15]; + return result; +} + +mfloat_t *mat4_negative(mfloat_t * result, mfloat_t * m0) +{ + result[0] = -m0[0]; + result[1] = -m0[1]; + result[2] = -m0[2]; + result[3] = -m0[3]; + result[4] = -m0[4]; + result[5] = -m0[5]; + result[6] = -m0[6]; + result[7] = -m0[7]; + result[8] = -m0[8]; + result[9] = -m0[9]; + result[10] = -m0[10]; + result[11] = -m0[11]; + result[12] = -m0[12]; + result[13] = -m0[13]; + result[14] = -m0[14]; + result[15] = -m0[15]; + return result; +} + +mfloat_t *mat4_transpose(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t transposed[MAT4_SIZE]; + transposed[0] = m0[0]; + transposed[1] = m0[4]; + transposed[2] = m0[8]; + transposed[3] = m0[12]; + transposed[4] = m0[1]; + transposed[5] = m0[5]; + transposed[6] = m0[9]; + transposed[7] = m0[13]; + transposed[8] = m0[2]; + transposed[9] = m0[6]; + transposed[10] = m0[10]; + transposed[11] = m0[14]; + transposed[12] = m0[3]; + transposed[13] = m0[7]; + transposed[14] = m0[11]; + transposed[15] = m0[15]; + result[0] = transposed[0]; + result[1] = transposed[1]; + result[2] = transposed[2]; + result[3] = transposed[3]; + result[4] = transposed[4]; + result[5] = transposed[5]; + result[6] = transposed[6]; + result[7] = transposed[7]; + result[8] = transposed[8]; + result[9] = transposed[9]; + result[10] = transposed[10]; + result[11] = transposed[11]; + result[12] = transposed[12]; + result[13] = transposed[13]; + result[14] = transposed[14]; + result[15] = transposed[15]; + return result; +} + +mfloat_t *mat4_cofactor(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t cofactor[MAT4_SIZE]; + mfloat_t minor[MAT3_SIZE]; + minor[0] = m0[5]; + minor[1] = m0[6]; + minor[2] = m0[7]; + minor[3] = m0[9]; + minor[4] = m0[10]; + minor[5] = m0[11]; + minor[6] = m0[13]; + minor[7] = m0[14]; + minor[8] = m0[15]; + cofactor[0] = mat3_determinant(minor); + minor[0] = m0[4]; + minor[1] = m0[6]; + minor[2] = m0[7]; + minor[3] = m0[8]; + minor[4] = m0[10]; + minor[5] = m0[11]; + minor[6] = m0[12]; + minor[7] = m0[14]; + minor[8] = m0[15]; + cofactor[1] = -mat3_determinant(minor); + minor[0] = m0[4]; + minor[1] = m0[5]; + minor[2] = m0[7]; + minor[3] = m0[8]; + minor[4] = m0[9]; + minor[5] = m0[11]; + minor[6] = m0[12]; + minor[7] = m0[13]; + minor[8] = m0[15]; + cofactor[2] = mat3_determinant(minor); + minor[0] = m0[4]; + minor[1] = m0[5]; + minor[2] = m0[6]; + minor[3] = m0[8]; + minor[4] = m0[9]; + minor[5] = m0[10]; + minor[6] = m0[12]; + minor[7] = m0[13]; + minor[8] = m0[14]; + cofactor[3] = -mat3_determinant(minor); + minor[0] = m0[1]; + minor[1] = m0[2]; + minor[2] = m0[3]; + minor[3] = m0[9]; + minor[4] = m0[10]; + minor[5] = m0[11]; + minor[6] = m0[13]; + minor[7] = m0[14]; + minor[8] = m0[15]; + cofactor[4] = -mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[2]; + minor[2] = m0[3]; + minor[3] = m0[8]; + minor[4] = m0[10]; + minor[5] = m0[11]; + minor[6] = m0[12]; + minor[7] = m0[14]; + minor[8] = m0[15]; + cofactor[5] = mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[3]; + minor[3] = m0[8]; + minor[4] = m0[9]; + minor[5] = m0[11]; + minor[6] = m0[12]; + minor[7] = m0[13]; + minor[8] = m0[15]; + cofactor[6] = -mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[2]; + minor[3] = m0[8]; + minor[4] = m0[9]; + minor[5] = m0[10]; + minor[6] = m0[12]; + minor[7] = m0[13]; + minor[8] = m0[14]; + cofactor[7] = mat3_determinant(minor); + minor[0] = m0[1]; + minor[1] = m0[2]; + minor[2] = m0[3]; + minor[3] = m0[5]; + minor[4] = m0[6]; + minor[5] = m0[7]; + minor[6] = m0[13]; + minor[7] = m0[14]; + minor[8] = m0[15]; + cofactor[8] = mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[2]; + minor[2] = m0[3]; + minor[3] = m0[4]; + minor[4] = m0[6]; + minor[5] = m0[7]; + minor[6] = m0[12]; + minor[7] = m0[14]; + minor[8] = m0[15]; + cofactor[9] = -mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[3]; + minor[3] = m0[4]; + minor[4] = m0[5]; + minor[5] = m0[7]; + minor[6] = m0[12]; + minor[7] = m0[13]; + minor[8] = m0[15]; + cofactor[10] = mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[2]; + minor[3] = m0[4]; + minor[4] = m0[5]; + minor[5] = m0[6]; + minor[6] = m0[12]; + minor[7] = m0[13]; + minor[8] = m0[14]; + cofactor[11] = -mat3_determinant(minor); + minor[0] = m0[1]; + minor[1] = m0[2]; + minor[2] = m0[3]; + minor[3] = m0[5]; + minor[4] = m0[6]; + minor[5] = m0[7]; + minor[6] = m0[9]; + minor[7] = m0[10]; + minor[8] = m0[11]; + cofactor[12] = -mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[2]; + minor[2] = m0[3]; + minor[3] = m0[4]; + minor[4] = m0[6]; + minor[5] = m0[7]; + minor[6] = m0[8]; + minor[7] = m0[10]; + minor[8] = m0[11]; + cofactor[13] = mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[3]; + minor[3] = m0[4]; + minor[4] = m0[5]; + minor[5] = m0[7]; + minor[6] = m0[8]; + minor[7] = m0[9]; + minor[8] = m0[11]; + cofactor[14] = -mat3_determinant(minor); + minor[0] = m0[0]; + minor[1] = m0[1]; + minor[2] = m0[2]; + minor[3] = m0[4]; + minor[4] = m0[5]; + minor[5] = m0[6]; + minor[6] = m0[8]; + minor[7] = m0[9]; + minor[8] = m0[10]; + cofactor[15] = mat3_determinant(minor); + result[0] = cofactor[0]; + result[1] = cofactor[1]; + result[2] = cofactor[2]; + result[3] = cofactor[3]; + result[4] = cofactor[4]; + result[5] = cofactor[5]; + result[6] = cofactor[6]; + result[7] = cofactor[7]; + result[8] = cofactor[8]; + result[9] = cofactor[9]; + result[10] = cofactor[10]; + result[11] = cofactor[11]; + result[12] = cofactor[12]; + result[13] = cofactor[13]; + result[14] = cofactor[14]; + result[15] = cofactor[15]; + return result; +} + +mfloat_t *mat4_rotation_x(mfloat_t * result, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + result[5] = c; + result[6] = s; + result[9] = -s; + result[10] = c; + return result; +} + +mfloat_t *mat4_rotation_y(mfloat_t * result, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + result[0] = c; + result[2] = -s; + result[8] = s; + result[10] = c; + return result; +} + +mfloat_t *mat4_rotation_z(mfloat_t * result, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + result[0] = c; + result[1] = s; + result[4] = -s; + result[5] = c; + return result; +} + +mfloat_t *mat4_rotation_axis(mfloat_t * result, mfloat_t * v0, mfloat_t f) +{ + mfloat_t c = MCOS(f); + mfloat_t s = MSIN(f); + mfloat_t one_c = MFLOAT_C(1.0) - c; + mfloat_t x = v0[0]; + mfloat_t y = v0[1]; + mfloat_t z = v0[2]; + mfloat_t xx = x * x; + mfloat_t xy = x * y; + mfloat_t xz = x * z; + mfloat_t yy = y * y; + mfloat_t yz = y * z; + mfloat_t zz = z * z; + mfloat_t l = xx + yy + zz; + mfloat_t sqrt_l = MSQRT(l); + result[0] = (xx + (yy + zz) * c) / l; + result[1] = (xy * one_c + v0[2] * sqrt_l * s) / l; + result[2] = (xz * one_c - v0[1] * sqrt_l * s) / l; + result[3] = MFLOAT_C(0.0); + result[4] = (xy * one_c - v0[2] * sqrt_l * s) / l; + result[5] = (yy + (xx + zz) * c) / l; + result[6] = (yz * one_c + v0[0] * sqrt_l * s) / l; + result[7] = MFLOAT_C(0.0); + result[8] = (xz * one_c + v0[1] * sqrt_l * s) / l; + result[9] = (yz * one_c - v0[0] * sqrt_l * s) / l; + result[10] = (zz + (xx + yy) * c) / l; + result[11] = MFLOAT_C(0.0); + result[12] = MFLOAT_C(0.0); + result[13] = MFLOAT_C(0.0); + result[14] = MFLOAT_C(0.0); + result[15] = MFLOAT_C(1.0); + return result; +} + +mfloat_t *mat4_rotation_quat(mfloat_t * result, mfloat_t * q0) +{ + mfloat_t xx = q0[0] * q0[0]; + mfloat_t yy = q0[1] * q0[1]; + mfloat_t zz = q0[2] * q0[2]; + mfloat_t xy = q0[0] * q0[1]; + mfloat_t zw = q0[2] * q0[3]; + mfloat_t xz = q0[0] * q0[2]; + mfloat_t yw = q0[1] * q0[3]; + mfloat_t yz = q0[1] * q0[2]; + mfloat_t xw = q0[0] * q0[3]; + result[0] = MFLOAT_C(1.0) - MFLOAT_C(2.0) * (yy + zz); + result[1] = MFLOAT_C(2.0) * (xy + zw); + result[2] = MFLOAT_C(2.0) * (xz - yw); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(2.0) * (xy - zw); + result[5] = MFLOAT_C(1.0) - MFLOAT_C(2.0) * (xx + zz); + result[6] = MFLOAT_C(2.0) * (yz + xw); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(2.0) * (xz + yw); + result[9] = MFLOAT_C(2.0) * (yz - xw); + result[10] = MFLOAT_C(1.0) - MFLOAT_C(2.0) * (xx + yy); + result[11] = MFLOAT_C(0.0); + result[12] = MFLOAT_C(0.0); + result[13] = MFLOAT_C(0.0); + result[14] = MFLOAT_C(0.0); + result[15] = MFLOAT_C(1.0); + return result; +} + +mfloat_t *mat4_translation(mfloat_t * result, mfloat_t * m0, mfloat_t * v0) +{ + result[0] = m0[0]; + result[1] = m0[1]; + result[2] = m0[2]; + result[3] = m0[3]; + result[4] = m0[4]; + result[5] = m0[5]; + result[6] = m0[6]; + result[7] = m0[7]; + result[8] = m0[8]; + result[9] = m0[9]; + result[10] = m0[10]; + result[11] = m0[11]; + result[12] = v0[0]; + result[13] = v0[1]; + result[14] = v0[2]; + result[15] = m0[15]; + return result; +} + +mfloat_t *mat4_translate(mfloat_t * result, mfloat_t * m0, mfloat_t * v0) +{ + result[0] = m0[0]; + result[1] = m0[1]; + result[2] = m0[2]; + result[3] = m0[3]; + result[4] = m0[4]; + result[5] = m0[5]; + result[6] = m0[6]; + result[7] = m0[7]; + result[8] = m0[8]; + result[9] = m0[9]; + result[10] = m0[10]; + result[11] = m0[11]; + result[12] = m0[12] + v0[0]; + result[13] = m0[13] + v0[1]; + result[14] = m0[14] + v0[2]; + result[15] = m0[15]; + return result; +} + +mfloat_t *mat4_translate_vec2(mfloat_t * mat4, mfloat_t * vec2) +{ + mat4[12] += vec2[0]; + mat4[13] += vec2[1]; + return mat4; +} + +mfloat_t *mat4_translate_vec3(mfloat_t * mat4, mfloat_t * vec3) +{ + mat4[12] += vec3[0]; + mat4[13] += vec3[1]; + mat4[14] += vec3[2]; + return mat4; +} + + +mfloat_t *mat4_scaling(mfloat_t * result, mfloat_t * m0, mfloat_t * v0) +{ + result[0] = v0[0]; + result[1] = m0[1]; + result[2] = m0[2]; + result[3] = m0[3]; + result[4] = m0[4]; + result[5] = v0[1]; + result[6] = m0[6]; + result[7] = m0[7]; + result[8] = m0[8]; + result[9] = m0[9]; + result[10] = v0[2]; + result[11] = m0[11]; + result[12] = m0[12]; + result[13] = m0[13]; + result[14] = m0[14]; + result[15] = m0[15]; + return result; +} + +mfloat_t *mat4_scale(mfloat_t * result, mfloat_t * m0, mfloat_t * v0) +{ + result[0] = m0[0] * v0[0]; + result[1] = m0[1]; + result[2] = m0[2]; + result[3] = m0[3]; + result[4] = m0[4]; + result[5] = m0[5] * v0[1]; + result[6] = m0[6]; + result[7] = m0[7]; + result[8] = m0[8]; + result[9] = m0[9]; + result[10] = m0[10] * v0[2]; + result[11] = m0[11]; + result[12] = m0[12]; + result[13] = m0[13]; + result[14] = m0[14]; + result[15] = m0[15]; + return result; +} + +mfloat_t *mat4_scale_vec2(mfloat_t * mat4, mfloat_t * vec2) +{ + mat4[0] *= vec2[0]; + mat4[5] *= vec2[1]; + return mat4; +} + +mfloat_t *mat4_scale_vec2f(mfloat_t * mat4, mfloat_t f) +{ + mat4[0] *= f; + mat4[5] *= f; + return mat4; +} + +mfloat_t *mat4_scale_vec3(mfloat_t * mat4, mfloat_t * vec3) +{ + mat4[0] *= vec3[0]; + mat4[5] *= vec3[1]; + mat4[10] *= vec3[2]; + return mat4; +} + +mfloat_t *mat4_scale_vec3f(mfloat_t * mat4, mfloat_t f) +{ + mat4[0] *= f; + mat4[5] *= f; + mat4[10] *= f; + return mat4; +} + + +mfloat_t *mat4_multiply(mfloat_t * result, mfloat_t * m0, mfloat_t * m1) +{ + mfloat_t multiplied[MAT4_SIZE]; + multiplied[0] = + m0[0] * m1[0] + m0[4] * m1[1] + m0[8] * m1[2] + m0[12] * m1[3]; + multiplied[1] = + m0[1] * m1[0] + m0[5] * m1[1] + m0[9] * m1[2] + m0[13] * m1[3]; + multiplied[2] = + m0[2] * m1[0] + m0[6] * m1[1] + m0[10] * m1[2] + m0[14] * m1[3]; + multiplied[3] = + m0[3] * m1[0] + m0[7] * m1[1] + m0[11] * m1[2] + m0[15] * m1[3]; + multiplied[4] = + m0[0] * m1[4] + m0[4] * m1[5] + m0[8] * m1[6] + m0[12] * m1[7]; + multiplied[5] = + m0[1] * m1[4] + m0[5] * m1[5] + m0[9] * m1[6] + m0[13] * m1[7]; + multiplied[6] = + m0[2] * m1[4] + m0[6] * m1[5] + m0[10] * m1[6] + m0[14] * m1[7]; + multiplied[7] = + m0[3] * m1[4] + m0[7] * m1[5] + m0[11] * m1[6] + m0[15] * m1[7]; + multiplied[8] = + m0[0] * m1[8] + m0[4] * m1[9] + m0[8] * m1[10] + m0[12] * m1[11]; + multiplied[9] = + m0[1] * m1[8] + m0[5] * m1[9] + m0[9] * m1[10] + m0[13] * m1[11]; + multiplied[10] = + m0[2] * m1[8] + m0[6] * m1[9] + m0[10] * m1[10] + m0[14] * m1[11]; + multiplied[11] = + m0[3] * m1[8] + m0[7] * m1[9] + m0[11] * m1[10] + m0[15] * m1[11]; + multiplied[12] = + m0[0] * m1[12] + m0[4] * m1[13] + m0[8] * m1[14] + m0[12] * m1[15]; + multiplied[13] = + m0[1] * m1[12] + m0[5] * m1[13] + m0[9] * m1[14] + m0[13] * m1[15]; + multiplied[14] = + m0[2] * m1[12] + m0[6] * m1[13] + m0[10] * m1[14] + + m0[14] * m1[15]; + multiplied[15] = + m0[3] * m1[12] + m0[7] * m1[13] + m0[11] * m1[14] + + m0[15] * m1[15]; + result[0] = multiplied[0]; + result[1] = multiplied[1]; + result[2] = multiplied[2]; + result[3] = multiplied[3]; + result[4] = multiplied[4]; + result[5] = multiplied[5]; + result[6] = multiplied[6]; + result[7] = multiplied[7]; + result[8] = multiplied[8]; + result[9] = multiplied[9]; + result[10] = multiplied[10]; + result[11] = multiplied[11]; + result[12] = multiplied[12]; + result[13] = multiplied[13]; + result[14] = multiplied[14]; + result[15] = multiplied[15]; + return result; +} + +mfloat_t *mat4_multiply_f(mfloat_t * result, mfloat_t * m0, mfloat_t f) +{ + result[0] = m0[0] * f; + result[1] = m0[1] * f; + result[2] = m0[2] * f; + result[3] = m0[3] * f; + result[4] = m0[4] * f; + result[5] = m0[5] * f; + result[6] = m0[6] * f; + result[7] = m0[7] * f; + result[8] = m0[8] * f; + result[9] = m0[9] * f; + result[10] = m0[10] * f; + result[11] = m0[11] * f; + result[12] = m0[12] * f; + result[13] = m0[13] * f; + result[14] = m0[14] * f; + result[15] = m0[15] * f; + return result; +} + +mfloat_t *mat4_inverse(mfloat_t * result, mfloat_t * m0) +{ + mfloat_t inverse[MAT4_SIZE]; + mfloat_t inverted_determinant; + mfloat_t m11 = m0[0]; + mfloat_t m21 = m0[1]; + mfloat_t m31 = m0[2]; + mfloat_t m41 = m0[3]; + mfloat_t m12 = m0[4]; + mfloat_t m22 = m0[5]; + mfloat_t m32 = m0[6]; + mfloat_t m42 = m0[7]; + mfloat_t m13 = m0[8]; + mfloat_t m23 = m0[9]; + mfloat_t m33 = m0[10]; + mfloat_t m43 = m0[11]; + mfloat_t m14 = m0[12]; + mfloat_t m24 = m0[13]; + mfloat_t m34 = m0[14]; + mfloat_t m44 = m0[15]; + inverse[0] = m22 * m33 * m44 + - m22 * m43 * m34 + - m23 * m32 * m44 + + m23 * m42 * m34 + m24 * m32 * m43 - m24 * m42 * m33; + inverse[4] = -m12 * m33 * m44 + + m12 * m43 * m34 + + m13 * m32 * m44 + - m13 * m42 * m34 - m14 * m32 * m43 + m14 * m42 * m33; + inverse[8] = m12 * m23 * m44 + - m12 * m43 * m24 + - m13 * m22 * m44 + + m13 * m42 * m24 + m14 * m22 * m43 - m14 * m42 * m23; + inverse[12] = -m12 * m23 * m34 + + m12 * m33 * m24 + + m13 * m22 * m34 + - m13 * m32 * m24 - m14 * m22 * m33 + m14 * m32 * m23; + inverse[1] = -m21 * m33 * m44 + + m21 * m43 * m34 + + m23 * m31 * m44 + - m23 * m41 * m34 - m24 * m31 * m43 + m24 * m41 * m33; + inverse[5] = m11 * m33 * m44 + - m11 * m43 * m34 + - m13 * m31 * m44 + + m13 * m41 * m34 + m14 * m31 * m43 - m14 * m41 * m33; + inverse[9] = -m11 * m23 * m44 + + m11 * m43 * m24 + + m13 * m21 * m44 + - m13 * m41 * m24 - m14 * m21 * m43 + m14 * m41 * m23; + inverse[13] = m11 * m23 * m34 + - m11 * m33 * m24 + - m13 * m21 * m34 + + m13 * m31 * m24 + m14 * m21 * m33 - m14 * m31 * m23; + inverse[2] = m21 * m32 * m44 + - m21 * m42 * m34 + - m22 * m31 * m44 + + m22 * m41 * m34 + m24 * m31 * m42 - m24 * m41 * m32; + inverse[6] = -m11 * m32 * m44 + + m11 * m42 * m34 + + m12 * m31 * m44 + - m12 * m41 * m34 - m14 * m31 * m42 + m14 * m41 * m32; + inverse[10] = m11 * m22 * m44 + - m11 * m42 * m24 + - m12 * m21 * m44 + + m12 * m41 * m24 + m14 * m21 * m42 - m14 * m41 * m22; + inverse[14] = -m11 * m22 * m34 + + m11 * m32 * m24 + + m12 * m21 * m34 + - m12 * m31 * m24 - m14 * m21 * m32 + m14 * m31 * m22; + inverse[3] = -m21 * m32 * m43 + + m21 * m42 * m33 + + m22 * m31 * m43 + - m22 * m41 * m33 - m23 * m31 * m42 + m23 * m41 * m32; + inverse[7] = m11 * m32 * m43 + - m11 * m42 * m33 + - m12 * m31 * m43 + + m12 * m41 * m33 + m13 * m31 * m42 - m13 * m41 * m32; + inverse[11] = -m11 * m22 * m43 + + m11 * m42 * m23 + + m12 * m21 * m43 + - m12 * m41 * m23 - m13 * m21 * m42 + m13 * m41 * m22; + inverse[15] = m11 * m22 * m33 + - m11 * m32 * m23 + - m12 * m21 * m33 + + m12 * m31 * m23 + m13 * m21 * m32 - m13 * m31 * m22; + inverted_determinant = + MFLOAT_C(1.0) / (m11 * inverse[0] + m21 * inverse[4] + + m31 * inverse[8] + m41 * inverse[12]); + result[0] = inverse[0] * inverted_determinant; + result[1] = inverse[1] * inverted_determinant; + result[2] = inverse[2] * inverted_determinant; + result[3] = inverse[3] * inverted_determinant; + result[4] = inverse[4] * inverted_determinant; + result[5] = inverse[5] * inverted_determinant; + result[6] = inverse[6] * inverted_determinant; + result[7] = inverse[7] * inverted_determinant; + result[8] = inverse[8] * inverted_determinant; + result[9] = inverse[9] * inverted_determinant; + result[10] = inverse[10] * inverted_determinant; + result[11] = inverse[11] * inverted_determinant; + result[12] = inverse[12] * inverted_determinant; + result[13] = inverse[13] * inverted_determinant; + result[14] = inverse[14] * inverted_determinant; + result[15] = inverse[15] * inverted_determinant; + return result; +} + +mfloat_t *mat4_lerp(mfloat_t * result, mfloat_t * m0, mfloat_t * m1, + mfloat_t f) +{ + result[0] = m0[0] + (m1[0] - m0[0]) * f; + result[1] = m0[1] + (m1[1] - m0[1]) * f; + result[2] = m0[2] + (m1[2] - m0[2]) * f; + result[3] = m0[3] + (m1[3] - m0[3]) * f; + result[4] = m0[4] + (m1[4] - m0[4]) * f; + result[5] = m0[5] + (m1[5] - m0[5]) * f; + result[6] = m0[6] + (m1[6] - m0[6]) * f; + result[7] = m0[7] + (m1[7] - m0[7]) * f; + result[8] = m0[8] + (m1[8] - m0[8]) * f; + result[9] = m0[9] + (m1[9] - m0[9]) * f; + result[10] = m0[10] + (m1[10] - m0[10]) * f; + result[11] = m0[11] + (m1[11] - m0[11]) * f; + result[12] = m0[12] + (m1[12] - m0[12]) * f; + result[13] = m0[13] + (m1[13] - m0[13]) * f; + result[14] = m0[14] + (m1[14] - m0[14]) * f; + result[15] = m0[15] + (m1[15] - m0[15]) * f; + return result; +} + +mfloat_t *mat4_look_at(mfloat_t * result, const mfloat_t * position, + const mfloat_t * target, const mfloat_t * up) +{ + mfloat_t tmp_forward[VEC3_SIZE] = { 0.f }; + mfloat_t tmp_side[VEC3_SIZE] = { 0.f }; + mfloat_t tmp_up[VEC3_SIZE] = { 0.f }; + vec3_subtract(tmp_forward, target, position); + vec3_normalize(tmp_forward, tmp_forward); + vec3_cross(tmp_side, tmp_forward, up); + vec3_normalize(tmp_side, tmp_side); + vec3_cross(tmp_up, tmp_side, tmp_forward); + result[0] = tmp_side[0]; + result[1] = tmp_up[0]; + result[2] = -tmp_forward[0]; + result[3] = MFLOAT_C(0.0); + result[4] = tmp_side[1]; + result[5] = tmp_up[1]; + result[6] = -tmp_forward[1]; + result[7] = MFLOAT_C(0.0); + result[8] = tmp_side[2]; + result[9] = tmp_up[2]; + result[10] = -tmp_forward[2]; + result[11] = MFLOAT_C(0.0); + result[12] = -vec3_dot(tmp_side, position); + result[13] = -vec3_dot(tmp_up, position); + result[14] = vec3_dot(tmp_forward, position); + result[15] = MFLOAT_C(1.0); + return result; +} + +mfloat_t *mat4_ortho(mfloat_t * result, mfloat_t l, mfloat_t r, mfloat_t b, + mfloat_t t, mfloat_t n, mfloat_t f) +{ + result[0] = MFLOAT_C(2.0) / (r - l); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(0.0); + result[5] = MFLOAT_C(2.0) / (t - b); + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(0.0); + result[9] = MFLOAT_C(0.0); + result[10] = -MFLOAT_C(2.0) / (f - n); + result[11] = MFLOAT_C(0.0); + result[12] = -((r + l) / (r - l)); + result[13] = -((t + b) / (t - b)); + result[14] = -((f + n) / (f - n)); + result[15] = MFLOAT_C(1.0); + return result; +} + +mfloat_t *mat4_perspective(mfloat_t * result, mfloat_t fov_y, + mfloat_t aspect, mfloat_t n, mfloat_t f) +{ + mfloat_t tan_half_fov_y = MFLOAT_C(1.0) / MTAN(fov_y * MFLOAT_C(0.5)); + result[0] = MFLOAT_C(1.0) / aspect * tan_half_fov_y; + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(0.0); + result[5] = MFLOAT_C(1.0) / tan_half_fov_y; + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(0.0); + result[9] = MFLOAT_C(0.0); + result[10] = f / (n - f); + result[11] = -MFLOAT_C(1.0); + result[12] = MFLOAT_C(0.0); + result[13] = MFLOAT_C(0.0); + result[14] = -(f * n) / (f - n); + result[15] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *mat4_perspective_fov(mfloat_t * result, mfloat_t fov, mfloat_t w, + mfloat_t h, mfloat_t n, mfloat_t f) +{ + mfloat_t h2 = MCOS(fov * MFLOAT_C(0.5)) / MSIN(fov * MFLOAT_C(0.5)); + mfloat_t w2 = h2 * h / w; + result[0] = w2; + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(0.0); + result[5] = h2; + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(0.0); + result[9] = MFLOAT_C(0.0); + result[10] = f / (n - f); + result[11] = -MFLOAT_C(1.0); + result[12] = MFLOAT_C(0.0); + result[13] = MFLOAT_C(0.0); + result[14] = -(f * n) / (f - n); + result[15] = MFLOAT_C(0.0); + return result; +} + +mfloat_t *mat4_perspective_infinite(mfloat_t * result, mfloat_t fov_y, + mfloat_t aspect, mfloat_t n) +{ + mfloat_t range = MTAN(fov_y * MFLOAT_C(0.5)) * n; + mfloat_t left = -range * aspect; + mfloat_t right = range * aspect; + mfloat_t top = range; + mfloat_t bottom = -range; + result[0] = MFLOAT_C(2.0) * n / (right - left); + result[1] = MFLOAT_C(0.0); + result[2] = MFLOAT_C(0.0); + result[3] = MFLOAT_C(0.0); + result[4] = MFLOAT_C(0.0); + result[5] = MFLOAT_C(2.0) * n / (top - bottom); + result[6] = MFLOAT_C(0.0); + result[7] = MFLOAT_C(0.0); + result[8] = MFLOAT_C(0.0); + result[9] = MFLOAT_C(0.0); + result[10] = -MFLOAT_C(1.0); + result[11] = -MFLOAT_C(1.0); + result[12] = MFLOAT_C(0.0); + result[13] = MFLOAT_C(0.0); + result[14] = -MFLOAT_C(2.0) * n; + result[15] = MFLOAT_C(0.0); + return result; +} +#endif + +#if defined(MATHC_USE_STRUCT_FUNCTIONS) +#if defined(MATHC_USE_INT) +bool svec2i_is_zero(struct vec2i v0) +{ + return vec2i_is_zero((mint_t *) & v0); +} + +bool svec2i_is_equal(struct vec2i v0, struct vec2i v1) +{ + return vec2i_is_equal((mint_t *) & v0, (mint_t *) & v1); +} + +struct vec2i svec2i(mint_t x, mint_t y) +{ + struct vec2i result; + vec2i((mint_t *) & result, x, y); + return result; +} + +struct vec2i svec2i_assign(struct vec2i v0) +{ + struct vec2i result; + vec2i_assign((mint_t *) & result, (mint_t *) & v0); + return result; +} + +#if defined(MATHC_USE_FLOATING_POINT) +struct vec2i svec2i_assign_vec2(struct vec2 v0) +{ + struct vec2i result; + vec2i_assign_vec2((mint_t *) & result, (mfloat_t *) & v0); + return result; +} +#endif + +struct vec2i svec2i_zero(void) +{ + struct vec2i result; + vec2i_zero((mint_t *) & result); + return result; +} + +struct vec2i svec2i_one(void) +{ + struct vec2i result; + vec2i_one((mint_t *) & result); + return result; +} + +struct vec2i svec2i_sign(struct vec2i v0) +{ + struct vec2i result; + vec2i_sign((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec2i svec2i_add(struct vec2i v0, struct vec2i v1) +{ + struct vec2i result; + vec2i_add((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec2i svec2i_add_i(struct vec2i v0, mint_t i) +{ + struct vec2i result; + vec2i_add_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec2i svec2i_subtract(struct vec2i v0, struct vec2i v1) +{ + struct vec2i result; + vec2i_subtract((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec2i svec2i_subtract_i(struct vec2i v0, mint_t i) +{ + struct vec2i result; + vec2i_subtract_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec2i svec2i_multiply(struct vec2i v0, struct vec2i v1) +{ + struct vec2i result; + vec2i_multiply((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec2i svec2i_multiply_i(struct vec2i v0, mint_t i) +{ + struct vec2i result; + vec2i_multiply_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec2i svec2i_divide(struct vec2i v0, struct vec2i v1) +{ + struct vec2i result; + vec2i_divide((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec2i svec2i_divide_i(struct vec2i v0, mint_t i) +{ + struct vec2i result; + vec2i_divide_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec2i svec2i_snap(struct vec2i v0, struct vec2i v1) +{ + struct vec2i result; + vec2i_snap((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec2i svec2i_snap_i(struct vec2i v0, mint_t i) +{ + struct vec2i result; + vec2i_snap_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec2i svec2i_negative(struct vec2i v0) +{ + struct vec2i result; + vec2i_negative((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec2i svec2i_abs(struct vec2i v0) +{ + struct vec2i result; + vec2i_abs((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec2i svec2i_max(struct vec2i v0, struct vec2i v1) +{ + struct vec2i result; + vec2i_max((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec2i svec2i_min(struct vec2i v0, struct vec2i v1) +{ + struct vec2i result; + vec2i_min((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec2i svec2i_clamp(struct vec2i v0, struct vec2i v1, + struct vec2i v2) +{ + struct vec2i result; + vec2i_clamp((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1, + (mint_t *) & v2); + return result; +} + +struct vec2i svec2i_tangent(struct vec2i v0) +{ + struct vec2i result; + vec2i_tangent((mint_t *) & result, (mint_t *) & v0); + return result; +} + +bool svec3i_is_zero(struct vec3i v0) +{ + return vec3i_is_zero((mint_t *) & v0); +} + +bool svec3i_is_equal(struct vec3i v0, struct vec3i v1) +{ + return vec3i_is_equal((mint_t *) & v0, (mint_t *) & v1); +} + +struct vec3i svec3i(mint_t x, mint_t y, mint_t z) +{ + struct vec3i result; + vec3i((mint_t *) & result, x, y, z); + return result; +} + +struct vec3i svec3i_assign(struct vec3i v0) +{ + struct vec3i result; + vec3i_assign((mint_t *) & result, (mint_t *) & v0); + return result; +} + +#if defined(MATHC_USE_FLOATING_POINT) +struct vec3i svec3i_assign_vec3(struct vec3 v0) +{ + struct vec3i result; + vec3i_assign_vec3((mint_t *) & result, (mfloat_t *) & v0); + return result; +} +#endif + +struct vec3i svec3i_zero(void) +{ + struct vec3i result; + vec3i_zero((mint_t *) & result); + return result; +} + +struct vec3i svec3i_one(void) +{ + struct vec3i result; + vec3i_one((mint_t *) & result); + return result; +} + +struct vec3i svec3i_sign(struct vec3i v0) +{ + struct vec3i result; + vec3i_sign((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec3i svec3i_add(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_add((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_add_i(struct vec3i v0, mint_t i) +{ + struct vec3i result; + vec3i_add_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec3i svec3i_subtract(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_subtract((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_subtract_i(struct vec3i v0, mint_t i) +{ + struct vec3i result; + vec3i_subtract_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec3i svec3i_multiply(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_multiply((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_multiply_i(struct vec3i v0, mint_t i) +{ + struct vec3i result; + vec3i_multiply_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec3i svec3i_divide(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_divide((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_divide_i(struct vec3i v0, mint_t i) +{ + struct vec3i result; + vec3i_divide_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec3i svec3i_snap(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_snap((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_snap_i(struct vec3i v0, mint_t i) +{ + struct vec3i result; + vec3i_snap_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec3i svec3i_cross(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_cross((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_negative(struct vec3i v0) +{ + struct vec3i result; + vec3i_negative((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec3i svec3i_abs(struct vec3i v0) +{ + struct vec3i result; + vec3i_abs((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec3i svec3i_max(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_max((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_min(struct vec3i v0, struct vec3i v1) +{ + struct vec3i result; + vec3i_min((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec3i svec3i_clamp(struct vec3i v0, struct vec3i v1, + struct vec3i v2) +{ + struct vec3i result; + vec3i_clamp((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1, + (mint_t *) & v2); + return result; +} + +bool svec4i_is_zero(struct vec4i v0) +{ + return vec4i_is_zero((mint_t *) & v0); +} + +bool svec4i_is_equal(struct vec4i v0, struct vec4i v1) +{ + return vec4i_is_equal((mint_t *) & v0, (mint_t *) & v1); +} + +struct vec4i svec4i(mint_t x, mint_t y, mint_t z, mint_t w) +{ + struct vec4i result; + vec4i((mint_t *) & result, x, y, z, w); + return result; +} + +struct vec4i svec4i_assign(struct vec4i v0) +{ + struct vec4i result; + vec4i_assign((mint_t *) & result, (mint_t *) & v0); + return result; +} + +#if defined(MATHC_USE_FLOATING_POINT) +struct vec4i svec4i_assign_vec4(struct vec4 v0) +{ + struct vec4i result; + vec4i_assign_vec4((mint_t *) & result, (mfloat_t *) & v0); + return result; +} +#endif + +struct vec4i svec4i_zero(void) +{ + struct vec4i result; + vec4i_zero((mint_t *) & result); + return result; +} + +struct vec4i svec4i_one(void) +{ + struct vec4i result; + vec4i_one((mint_t *) & result); + return result; +} + +struct vec4i svec4i_sign(struct vec4i v0) +{ + struct vec4i result; + vec4i_sign((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec4i svec4i_add(struct vec4i v0, struct vec4i v1) +{ + struct vec4i result; + vec4i_add((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec4i svec4i_add_i(struct vec4i v0, mint_t i) +{ + struct vec4i result; + vec4i_add_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec4i svec4i_subtract(struct vec4i v0, struct vec4i v1) +{ + struct vec4i result; + vec4i_subtract((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec4i svec4i_subtract_i(struct vec4i v0, mint_t i) +{ + struct vec4i result; + vec4i_subtract_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec4i svec4i_multiply(struct vec4i v0, struct vec4i v1) +{ + struct vec4i result; + vec4i_multiply((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec4i svec4i_multiply_i(struct vec4i v0, mint_t i) +{ + struct vec4i result; + vec4i_multiply_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec4i svec4i_divide(struct vec4i v0, struct vec4i v1) +{ + struct vec4i result; + vec4i_divide((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec4i svec4i_divide_i(struct vec4i v0, mint_t i) +{ + struct vec4i result; + vec4i_divide_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec4i svec4i_snap(struct vec4i v0, struct vec4i v1) +{ + struct vec4i result; + vec4i_snap((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec4i svec4i_snap_i(struct vec4i v0, mint_t i) +{ + struct vec4i result; + vec4i_snap_i((mint_t *) & result, (mint_t *) & v0, i); + return result; +} + +struct vec4i svec4i_negative(struct vec4i v0) +{ + struct vec4i result; + vec4i_negative((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec4i svec4i_abs(struct vec4i v0) +{ + struct vec4i result; + vec4i_abs((mint_t *) & result, (mint_t *) & v0); + return result; +} + +struct vec4i svec4i_max(struct vec4i v0, struct vec4i v1) +{ + struct vec4i result; + vec4i_max((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec4i svec4i_min(struct vec4i v0, struct vec4i v1) +{ + struct vec4i result; + vec4i_min((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1); + return result; +} + +struct vec4i svec4i_clamp(struct vec4i v0, struct vec4i v1, + struct vec4i v2) +{ + struct vec4i result; + vec4i_clamp((mint_t *) & result, (mint_t *) & v0, (mint_t *) & v1, + (mint_t *) & v2); + return result; +} +#endif + +#if defined(MATHC_USE_FLOATING_POINT) +bool svec2_is_zero(struct vec2 v0) +{ + return vec2_is_zero((mfloat_t *) & v0); +} + +bool svec2_is_equal(struct vec2 v0, struct vec2 v1) +{ + return vec2_is_equal((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +struct vec2 svec2(mfloat_t x, mfloat_t y) +{ + struct vec2 result; + vec2((mfloat_t *) & result, x, y); + return result; +} + +struct vec2 svec2_assign(struct vec2 v0) +{ + struct vec2 result; + vec2_assign((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +#if defined(MATHC_USE_INT) +struct vec2 svec2_assign_vec2i(struct vec2i v0) +{ + struct vec2 result; + vec2_assign_vec2i((mfloat_t *) & result, (mint_t *) & v0); + return result; +} +#endif + +struct vec2 svec2_zero(void) +{ + struct vec2 result; + vec2_zero((mfloat_t *) & result); + return result; +} + +struct vec2 svec2_one(void) +{ + struct vec2 result; + vec2_one((mfloat_t *) & result); + return result; +} + +struct vec2 svec2_sign(struct vec2 v0) +{ + struct vec2 result; + vec2_sign((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec2 svec2_add(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_add((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_add_f(struct vec2 v0, mfloat_t f) +{ + struct vec2 result; + vec2_add_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec2 svec2_subtract(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_subtract((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_subtract_f(struct vec2 v0, mfloat_t f) +{ + struct vec2 result; + vec2_subtract_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec2 svec2_multiply(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_multiply((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_multiply_f(struct vec2 v0, mfloat_t f) +{ + struct vec2 result; + vec2_multiply_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec2 svec2_multiply_mat2(struct vec2 v0, struct mat2 m0) +{ + struct vec2 result; + vec2_multiply_mat2((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & m0); + return result; +} + +struct vec2 svec2_divide(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_divide((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_divide_f(struct vec2 v0, mfloat_t f) +{ + struct vec2 result; + vec2_divide_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec2 svec2_snap(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_snap((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_snap_f(struct vec2 v0, mfloat_t f) +{ + struct vec2 result; + vec2_snap_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec2 svec2_negative(struct vec2 v0) +{ + struct vec2 result; + vec2_negative((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec2 svec2_abs(struct vec2 v0) +{ + struct vec2 result; + vec2_abs((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec2 svec2_floor(struct vec2 v0) +{ + struct vec2 result; + vec2_floor((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec2 svec2_ceil(struct vec2 v0) +{ + struct vec2 result; + vec2_ceil((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec2 svec2_round(struct vec2 v0) +{ + struct vec2 result; + vec2_round((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec2 svec2_max(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_max((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_min(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_min((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_clamp(struct vec2 v0, struct vec2 v1, struct vec2 v2) +{ + struct vec2 result; + vec2_clamp((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1, + (mfloat_t *) & v2); + return result; +} + +struct vec2 svec2_normalize(struct vec2 v0) +{ + struct vec2 result; + vec2_normalize((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +mfloat_t svec2_dot(struct vec2 v0, struct vec2 v1) +{ + return vec2_dot((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +struct vec2 svec2_project(struct vec2 v0, struct vec2 v1) +{ + struct vec2 result; + vec2_project((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec2 svec2_slide(struct vec2 v0, struct vec2 normal) +{ + struct vec2 result; + vec2_slide((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & normal); + return result; +} + +struct vec2 svec2_reflect(struct vec2 v0, struct vec2 normal) +{ + struct vec2 result; + vec2_reflect((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & normal); + return result; +} + +struct vec2 svec2_tangent(struct vec2 v0) +{ + struct vec2 result; + vec2_tangent((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec2 svec2_rotate(struct vec2 v0, mfloat_t f) +{ + struct vec2 result; + vec2_rotate((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec2 svec2_lerp(struct vec2 v0, struct vec2 v1, mfloat_t f) +{ + struct vec2 result; + vec2_lerp((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1, + f); + return result; +} + +struct vec2 svec2_bezier3(struct vec2 v0, struct vec2 v1, struct vec2 v2, + mfloat_t f) +{ + struct vec2 result; + vec2_bezier3((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1, (mfloat_t *) & v2, f); + return result; +} + +struct vec2 svec2_bezier4(struct vec2 v0, struct vec2 v1, struct vec2 v2, + struct vec2 v3, mfloat_t f) +{ + struct vec2 result; + vec2_bezier4((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1, (mfloat_t *) & v2, (mfloat_t *) & v3, + f); + return result; +} + +mfloat_t svec2_angle(struct vec2 v0) +{ + return vec2_angle((mfloat_t *) & v0); +} + +mfloat_t svec2_length(struct vec2 v0) +{ + return vec2_length((mfloat_t *) & v0); +} + +mfloat_t svec2_length_squared(struct vec2 v0) +{ + return vec2_length_squared((mfloat_t *) & v0); +} + +mfloat_t svec2_distance(struct vec2 v0, struct vec2 v1) +{ + return vec2_distance((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +mfloat_t svec2_distance_squared(struct vec2 v0, struct vec2 v1) +{ + return vec2_distance_squared((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +bool svec3_is_zero(struct vec3 v0) +{ + return vec3_is_zero((mfloat_t *) & v0); +} + +bool svec3_is_equal(struct vec3 v0, struct vec3 v1) +{ + return vec3_is_equal((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +struct vec3 svec3(mfloat_t x, mfloat_t y, mfloat_t z) +{ + struct vec3 result; + vec3((mfloat_t *) & result, x, y, z); + return result; +} + +struct vec3 svec3_assign(struct vec3 v0) +{ + struct vec3 result; + vec3_assign((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +#if defined(MATHC_USE_INT) +struct vec3 svec3_assign_vec3i(struct vec3i v0) +{ + struct vec3 result; + vec3_assign_vec3i((mfloat_t *) & result, (mint_t *) & v0); + return result; +} +#endif + +struct vec3 svec3_zero(void) +{ + struct vec3 result; + vec3_zero((mfloat_t *) & result); + return result; +} + +struct vec3 svec3_one(void) +{ + struct vec3 result; + vec3_one((mfloat_t *) & result); + return result; +} + +struct vec3 svec3_sign(struct vec3 v0) +{ + struct vec3 result; + vec3_sign((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec3 svec3_add(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_add((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_add_f(struct vec3 v0, mfloat_t f) +{ + struct vec3 result; + vec3_add_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec3 svec3_subtract(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_subtract((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_subtract_f(struct vec3 v0, mfloat_t f) +{ + struct vec3 result; + vec3_subtract_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec3 svec3_multiply(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_multiply((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_multiply_f(struct vec3 v0, mfloat_t f) +{ + struct vec3 result; + vec3_multiply_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec3 svec3_multiply_mat3(struct vec3 v0, struct mat3 m0) +{ + struct vec3 result; + vec3_multiply_mat3((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & m0); + return result; +} + +struct vec3 svec3_divide(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_divide((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_divide_f(struct vec3 v0, mfloat_t f) +{ + struct vec3 result; + vec3_divide_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec3 svec3_snap(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_snap((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_snap_f(struct vec3 v0, mfloat_t f) +{ + struct vec3 result; + vec3_snap_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec3 svec3_negative(struct vec3 v0) +{ + struct vec3 result; + vec3_negative((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec3 svec3_abs(struct vec3 v0) +{ + struct vec3 result; + vec3_abs((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec3 svec3_floor(struct vec3 v0) +{ + struct vec3 result; + vec3_floor((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec3 svec3_ceil(struct vec3 v0) +{ + struct vec3 result; + vec3_ceil((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec3 svec3_round(struct vec3 v0) +{ + struct vec3 result; + vec3_round((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec3 svec3_max(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_max((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_min(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_min((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_clamp(struct vec3 v0, struct vec3 v1, struct vec3 v2) +{ + struct vec3 result; + vec3_clamp((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1, + (mfloat_t *) & v2); + return result; +} + +struct vec3 svec3_cross(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_cross((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_normalize(struct vec3 v0) +{ + struct vec3 result; + vec3_normalize((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +mfloat_t svec3_dot(struct vec3 v0, struct vec3 v1) +{ + return vec3_dot((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +struct vec3 svec3_project(struct vec3 v0, struct vec3 v1) +{ + struct vec3 result; + vec3_project((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec3 svec3_slide(struct vec3 v0, struct vec3 normal) +{ + struct vec3 result; + vec3_slide((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & normal); + return result; +} + +struct vec3 svec3_reflect(struct vec3 v0, struct vec3 normal) +{ + struct vec3 result; + vec3_reflect((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & normal); + return result; +} + +struct vec3 svec3_rotate(struct vec3 v0, struct vec3 ra, mfloat_t f) +{ + struct vec3 result; + vec3_lerp((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & ra, + f); + return result; +} + +struct vec3 svec3_lerp(struct vec3 v0, struct vec3 v1, mfloat_t f) +{ + struct vec3 result; + vec3_lerp((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1, + f); + return result; +} + +struct vec3 svec3_bezier3(struct vec3 v0, struct vec3 v1, struct vec3 v2, + mfloat_t f) +{ + struct vec3 result; + vec3_bezier3((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1, (mfloat_t *) & v2, f); + return result; +} + +struct vec3 svec3_bezier4(struct vec3 v0, struct vec3 v1, struct vec3 v2, + struct vec3 v3, mfloat_t f) +{ + struct vec3 result; + vec3_bezier4((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1, (mfloat_t *) & v2, (mfloat_t *) & v3, + f); + return result; +} + +mfloat_t svec3_length(struct vec3 v0) +{ + return vec3_length((mfloat_t *) & v0); +} + +mfloat_t svec3_length_squared(struct vec3 v0) +{ + return vec3_length_squared((mfloat_t *) & v0); +} + +mfloat_t svec3_distance(struct vec3 v0, struct vec3 v1) +{ + return vec3_distance((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +mfloat_t svec3_distance_squared(struct vec3 v0, struct vec3 v1) +{ + return vec3_distance_squared((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +bool svec4_is_zero(struct vec4 v0) +{ + return vec4_is_zero((mfloat_t *) & v0); +} + +bool svec4_is_equal(struct vec4 v0, struct vec4 v1) +{ + return vec4_is_equal((mfloat_t *) & v0, (mfloat_t *) & v1); +} + +struct vec4 svec4(mfloat_t x, mfloat_t y, mfloat_t z, mfloat_t w) +{ + struct vec4 result; + vec4((mfloat_t *) & result, x, y, z, w); + return result; +} + +struct vec4 svec4_assign(struct vec4 v0) +{ + struct vec4 result; + vec4_assign((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +#if defined(MATHC_USE_INT) +struct vec4 svec4_assign_vec4i(struct vec4i v0) +{ + struct vec4 result; + vec4_assign_vec4i((mfloat_t *) & result, (mint_t *) & v0); + return result; +} +#endif + +struct vec4 svec4_zero(void) +{ + struct vec4 result; + vec4_zero((mfloat_t *) & result); + return result; +} + +struct vec4 svec4_one(void) +{ + struct vec4 result; + vec4_one((mfloat_t *) & result); + return result; +} + +struct vec4 svec4_sign(struct vec4 v0) +{ + struct vec4 result; + vec4_sign((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec4 svec4_add(struct vec4 v0, struct vec4 v1) +{ + struct vec4 result; + vec4_add((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec4 svec4_add_f(struct vec4 v0, mfloat_t f) +{ + struct vec4 result; + vec4_add_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec4 svec4_subtract(struct vec4 v0, struct vec4 v1) +{ + struct vec4 result; + vec4_subtract((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec4 svec4_subtract_f(struct vec4 v0, mfloat_t f) +{ + struct vec4 result; + vec4_subtract_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec4 svec4_multiply(struct vec4 v0, struct vec4 v1) +{ + struct vec4 result; + vec4_multiply((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec4 svec4_multiply_f(struct vec4 v0, mfloat_t f) +{ + struct vec4 result; + vec4_multiply_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec4 svec4_multiply_mat4(struct vec4 v0, struct mat4 m0) +{ + struct vec4 result; + vec4_multiply_mat4((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & m0); + return result; +} + +struct vec4 svec4_divide(struct vec4 v0, struct vec4 v1) +{ + struct vec4 result; + vec4_divide((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct vec4 svec4_divide_f(struct vec4 v0, mfloat_t f) +{ + struct vec4 result; + vec4_divide_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec4 svec4_snap(struct vec4 v0, struct vec4 v1) +{ + struct vec4 result; + vec4_snap((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec4 svec4_snap_f(struct vec4 v0, mfloat_t f) +{ + struct vec4 result; + vec4_snap_f((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct vec4 svec4_negative(struct vec4 v0) +{ + struct vec4 result; + vec4_negative((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec4 svec4_abs(struct vec4 v0) +{ + struct vec4 result; + vec4_abs((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec4 svec4_floor(struct vec4 v0) +{ + struct vec4 result; + vec4_floor((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec4 svec4_ceil(struct vec4 v0) +{ + struct vec4 result; + vec4_ceil((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec4 svec4_round(struct vec4 v0) +{ + struct vec4 result; + vec4_round((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec4 svec4_max(struct vec4 v0, struct vec4 v1) +{ + struct vec4 result; + vec4_max((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec4 svec4_min(struct vec4 v0, struct vec4 v1) +{ + struct vec4 result; + vec4_min((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1); + return result; +} + +struct vec4 svec4_clamp(struct vec4 v0, struct vec4 v1, struct vec4 v2) +{ + struct vec4 result; + vec4_clamp((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1, + (mfloat_t *) & v2); + return result; +} + +struct vec4 svec4_normalize(struct vec4 v0) +{ + struct vec4 result; + vec4_normalize((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct vec4 svec4_lerp(struct vec4 v0, struct vec4 v1, mfloat_t f) +{ + struct vec4 result; + vec4_lerp((mfloat_t *) & result, (mfloat_t *) & v0, (mfloat_t *) & v1, + f); + return result; +} + +bool squat_is_zero(struct quat q0) +{ + return quat_is_zero((mfloat_t *) & q0); +} + +bool squat_is_equal(struct quat q0, struct quat q1) +{ + return quat_is_equal((mfloat_t *) & q0, (mfloat_t *) & q1); +} + +struct quat squat_from_euler(mfloat_t x, mfloat_t y, mfloat_t z) +{ + struct quat result; + + return result; +} + +struct quat squat(mfloat_t x, mfloat_t y, mfloat_t z, mfloat_t w) +{ + struct quat result; + quat((mfloat_t *) & result, x, y, z, w); + return result; +} + +struct quat squat_assign(struct quat q0) +{ + struct quat result; + quat_assign((mfloat_t *) & result, (mfloat_t *) & q0); + return result; +} + +struct quat squat_zero(void) +{ + struct quat result; + quat_zero((mfloat_t *) & result); + return result; +} + +struct quat squat_null(void) +{ + struct quat result; + quat_null((mfloat_t *) & result); + return result; +} + +struct quat squat_multiply(struct quat q0, struct quat q1) +{ + struct quat result; + quat_multiply((mfloat_t *) & result, (mfloat_t *) & q0, + (mfloat_t *) & q1); + return result; +} + +struct quat squat_multiply_f(struct quat q0, mfloat_t f) +{ + struct quat result; + quat_multiply_f((mfloat_t *) & result, (mfloat_t *) & q0, f); + return result; +} + +struct quat squat_divide(struct quat q0, struct quat q1) +{ + struct quat result; + quat_divide((mfloat_t *) & result, (mfloat_t *) & q0, + (mfloat_t *) & q1); + return result; +} + +struct quat squat_divide_f(struct quat q0, mfloat_t f) +{ + struct quat result; + quat_divide_f((mfloat_t *) & result, (mfloat_t *) & q0, f); + return result; +} + +struct quat squat_negative(struct quat q0) +{ + struct quat result; + quat_negative((mfloat_t *) & result, (mfloat_t *) & q0); + return result; +} + +struct quat squat_conjugate(struct quat q0) +{ + struct quat result; + quat_conjugate((mfloat_t *) & result, (mfloat_t *) & q0); + return result; +} + +struct quat squat_inverse(struct quat q0) +{ + struct quat result; + quat_inverse((mfloat_t *) & result, (mfloat_t *) & q0); + return result; +} + +struct quat squat_normalize(struct quat q0) +{ + struct quat result; + quat_normalize((mfloat_t *) & result, (mfloat_t *) & q0); + return result; +} + +mfloat_t squat_dot(struct quat q0, struct quat q1) +{ + return quat_dot((mfloat_t *) & q0, (mfloat_t *) & q1); +} + +struct quat squat_power(struct quat q0, mfloat_t exponent) +{ + struct quat result; + quat_power((mfloat_t *) & result, (mfloat_t *) & q0, exponent); + return result; +} + +struct quat squat_from_axis_angle(struct vec3 v0, mfloat_t angle) +{ + struct quat result; + quat_from_axis_angle((mfloat_t *) & result, (mfloat_t *) & v0, angle); + return result; +} + +struct quat squat_from_vec3(struct vec3 v0, struct vec3 v1) +{ + struct quat result; + quat_from_vec3((mfloat_t *) & result, (mfloat_t *) & v0, + (mfloat_t *) & v1); + return result; +} + +struct quat squat_from_mat4(struct mat4 m0) +{ + struct quat result; + quat_from_mat4((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct quat squat_lerp(struct quat q0, struct quat q1, mfloat_t f) +{ + struct quat result; + quat_lerp((mfloat_t *) & result, (mfloat_t *) & q0, (mfloat_t *) & q1, + f); + return result; +} + +struct quat squat_slerp(struct quat q0, struct quat q1, mfloat_t f) +{ + struct quat result; + quat_slerp((mfloat_t *) & result, (mfloat_t *) & q0, (mfloat_t *) & q1, + f); + return result; +} + +mfloat_t squat_length(struct quat q0) +{ + return quat_length((mfloat_t *) & q0); +} + +mfloat_t squat_length_squared(struct quat q0) +{ + return quat_length_squared((mfloat_t *) & q0); +} + +mfloat_t squat_angle(struct quat q0, struct quat q1) +{ + return quat_angle((mfloat_t *) & q0, (mfloat_t *) & q1); +} + +struct mat2 smat2(mfloat_t m11, mfloat_t m12, mfloat_t m21, mfloat_t m22) +{ + struct mat2 result; + mat2((mfloat_t *) & result, m11, m12, m21, m22); + return result; +} + +struct mat2 smat2_zero(void) +{ + struct mat2 result; + mat2_zero((mfloat_t *) & result); + return result; +} + +struct mat2 smat2_identity(void) +{ + struct mat2 result; + mat2_identity((mfloat_t *) & result); + return result; +} + +mfloat_t smat2_determinant(struct mat2 m0) +{ + return mat2_determinant((mfloat_t *) & m0); +} + +struct mat2 smat2_assign(struct mat2 m0) +{ + struct mat2 result; + mat2_assign((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat2 smat2_negative(struct mat2 m0) +{ + struct mat2 result; + mat2_negative((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat2 smat2_transpose(struct mat2 m0) +{ + struct mat2 result; + mat2_transpose((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat2 smat2_cofactor(struct mat2 m0) +{ + struct mat2 result; + mat2_cofactor((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat2 smat2_adjugate(struct mat2 m0) +{ + struct mat2 result; + mat2_adjugate((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat2 smat2_multiply(struct mat2 m0, struct mat2 m1) +{ + struct mat2 result; + mat2_multiply((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & m1); + return result; +} + +struct mat2 smat2_multiply_f(struct mat2 m0, mfloat_t f) +{ + struct mat2 result; + mat2_multiply_f((mfloat_t *) & result, (mfloat_t *) & m0, f); + return result; +} + +struct mat2 smat2_inverse(struct mat2 m0) +{ + struct mat2 result; + mat2_inverse((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat2 smat2_scaling(struct vec2 v0) +{ + struct mat2 result; + mat2_scaling((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct mat2 smat2_scale(struct mat2 m0, struct vec2 v0) +{ + struct mat2 result; + mat2_scale((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & v0); + return result; +} + +struct mat2 smat2_rotation_z(mfloat_t f) +{ + struct mat2 result; + mat2_rotation_z((mfloat_t *) & result, f); + return result; +} + +struct mat2 smat2_lerp(struct mat2 m0, struct mat2 m1, mfloat_t f) +{ + struct mat2 result; + mat2_lerp((mfloat_t *) & result, (mfloat_t *) & m0, (mfloat_t *) & m1, + f); + return result; +} + +struct mat3 smat3(mfloat_t m11, mfloat_t m12, mfloat_t m13, mfloat_t m21, + mfloat_t m22, mfloat_t m23, mfloat_t m31, mfloat_t m32, + mfloat_t m33) +{ + struct mat3 result; + mat3((mfloat_t *) & result, m11, m12, m13, m21, m22, m23, m31, m32, + m33); + return result; +} + +struct mat3 smat3_zero(void) +{ + struct mat3 result; + mat3_zero((mfloat_t *) & result); + return result; +} + +struct mat3 smat3_identity(void) +{ + struct mat3 result; + mat3_identity((mfloat_t *) & result); + return result; +} + +mfloat_t smat3_determinant(struct mat3 m0) +{ + return mat3_determinant((mfloat_t *) & m0); +} + +struct mat3 smat3_assign(struct mat3 m0) +{ + struct mat3 result; + mat3_assign((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat3 smat3_negative(struct mat3 m0) +{ + struct mat3 result; + mat3_negative((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat3 smat3_transpose(struct mat3 m0) +{ + struct mat3 result; + mat3_transpose((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat3 smat3_cofactor(struct mat3 m0) +{ + struct mat3 result; + mat3_cofactor((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat3 smat3_multiply(struct mat3 m0, struct mat3 m1) +{ + struct mat3 result; + mat3_multiply((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & m1); + return result; +} + +struct mat3 smat3_multiply_f(struct mat3 m0, mfloat_t f) +{ + struct mat3 result; + mat3_multiply_f((mfloat_t *) & result, (mfloat_t *) & m0, f); + return result; +} + +struct mat3 smat3_inverse(struct mat3 m0) +{ + struct mat3 result; + mat3_inverse((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat3 smat3_scaling(struct vec3 v0) +{ + struct mat3 result; + mat3_scaling((mfloat_t *) & result, (mfloat_t *) & v0); + return result; +} + +struct mat3 smat3_scale(struct mat3 m0, struct vec3 v0) +{ + struct mat3 result; + mat3_scale((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & v0); + return result; +} + +struct mat3 smat3_rotation_x(mfloat_t f) +{ + struct mat3 result; + mat3_rotation_x((mfloat_t *) & result, f); + return result; +} + +struct mat3 smat3_rotation_y(mfloat_t f) +{ + struct mat3 result; + mat3_rotation_y((mfloat_t *) & result, f); + return result; +} + +struct mat3 smat3_rotation_z(mfloat_t f) +{ + struct mat3 result; + mat3_rotation_z((mfloat_t *) & result, f); + return result; +} + +struct mat3 smat3_rotation_axis(struct vec3 v0, mfloat_t f) +{ + struct mat3 result; + mat3_rotation_axis((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct mat3 smat3_rotation_quat(struct quat q0) +{ + struct mat3 result; + mat3_rotation_quat((mfloat_t *) & result, (mfloat_t *) & q0); + return result; +} + +struct mat3 smat3_lerp(struct mat3 m0, struct mat3 m1, mfloat_t f) +{ + struct mat3 result; + mat3_lerp((mfloat_t *) & result, (mfloat_t *) & m0, (mfloat_t *) & m1, + f); + return result; +} + +struct mat4 smat4(mfloat_t m11, mfloat_t m12, mfloat_t m13, mfloat_t m14, + mfloat_t m21, mfloat_t m22, mfloat_t m23, mfloat_t m24, + mfloat_t m31, mfloat_t m32, mfloat_t m33, mfloat_t m34, + mfloat_t m41, mfloat_t m42, mfloat_t m43, mfloat_t m44) +{ + struct mat4 result; + mat4((mfloat_t *) & result, m11, m12, m13, m14, m21, m22, m23, m24, + m31, m32, m33, m34, m41, m42, m43, m44); + return result; +} + +struct mat4 smat4_zero(void) +{ + struct mat4 result; + mat4_zero((mfloat_t *) & result); + return result; +} + +struct mat4 smat4_identity(void) +{ + struct mat4 result; + mat4_identity((mfloat_t *) & result); + return result; +} + +mfloat_t smat4_determinant(struct mat4 m0) +{ + return mat4_determinant((mfloat_t *) & m0); +} + +struct mat4 smat4_assign(struct mat4 m0) +{ + struct mat4 result; + mat4_assign((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat4 smat4_negative(struct mat4 m0) +{ + struct mat4 result; + mat4_negative((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat4 smat4_transpose(struct mat4 m0) +{ + struct mat4 result; + mat4_transpose((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat4 smat4_cofactor(struct mat4 m0) +{ + struct mat4 result; + mat4_cofactor((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat4 smat4_rotation_x(mfloat_t f) +{ + struct mat4 result; + mat4_rotation_x((mfloat_t *) & result, f); + return result; +} + +struct mat4 smat4_rotation_y(mfloat_t f) +{ + struct mat4 result; + mat4_rotation_y((mfloat_t *) & result, f); + return result; +} + +struct mat4 smat4_rotation_z(mfloat_t f) +{ + struct mat4 result; + mat4_rotation_z((mfloat_t *) & result, f); + return result; +} + +struct mat4 smat4_rotation_axis(struct vec3 v0, mfloat_t f) +{ + struct mat4 result; + mat4_rotation_axis((mfloat_t *) & result, (mfloat_t *) & v0, f); + return result; +} + +struct mat4 smat4_rotation_quat(struct quat q0) +{ + struct mat4 result; + mat4_rotation_quat((mfloat_t *) & result, (mfloat_t *) & q0); + return result; +} + +struct mat4 smat4_translation(struct mat4 m0, struct vec3 v0) +{ + struct mat4 result; + mat4_translation((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & v0); + return result; +} + +struct mat4 smat4_translate(struct mat4 m0, struct vec3 v0) +{ + struct mat4 result; + mat4_translate((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & v0); + return result; +} + +struct mat4 smat4_scaling(struct mat4 m0, struct vec3 v0) +{ + struct mat4 result; + mat4_scaling((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & v0); + return result; +} + +struct mat4 smat4_scale(struct mat4 m0, struct vec3 v0) +{ + struct mat4 result; + mat4_scale((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & v0); + return result; +} + +struct mat4 smat4_multiply(struct mat4 m0, struct mat4 m1) +{ + struct mat4 result; + mat4_multiply((mfloat_t *) & result, (mfloat_t *) & m0, + (mfloat_t *) & m1); + return result; +} + +struct mat4 smat4_multiply_f(struct mat4 m0, mfloat_t f) +{ + struct mat4 result; + mat4_multiply_f((mfloat_t *) & result, (mfloat_t *) & m0, f); + return result; +} + +struct mat4 smat4_inverse(struct mat4 m0) +{ + struct mat4 result; + mat4_inverse((mfloat_t *) & result, (mfloat_t *) & m0); + return result; +} + +struct mat4 smat4_lerp(struct mat4 m0, struct mat4 m1, mfloat_t f) +{ + struct mat4 result; + mat4_lerp((mfloat_t *) & result, (mfloat_t *) & m0, (mfloat_t *) & m1, + f); + return result; +} + +struct mat4 smat4_look_at(struct vec3 position, struct vec3 target, + struct vec3 up) +{ + struct mat4 result; + mat4_look_at((mfloat_t *) & result, (mfloat_t *) & position, + (mfloat_t *) & target, (mfloat_t *) & up); + return result; +} + +struct mat4 smat4_ortho(mfloat_t l, mfloat_t r, mfloat_t b, mfloat_t t, + mfloat_t n, mfloat_t f) +{ + struct mat4 result; + mat4_ortho((mfloat_t *) & result, l, r, b, t, n, f); + return result; +} + +struct mat4 smat4_perspective(mfloat_t fov_y, mfloat_t aspect, mfloat_t n, + mfloat_t f) +{ + struct mat4 result; + mat4_perspective((mfloat_t *) & result, fov_y, aspect, n, f); + return result; +} + +struct mat4 smat4_perspective_fov(mfloat_t fov, mfloat_t w, mfloat_t h, + mfloat_t n, mfloat_t f) +{ + struct mat4 result; + mat4_perspective_fov((mfloat_t *) & result, fov, w, h, n, f); + return result; +} + +struct mat4 smat4_perspective_infinite(mfloat_t fov_y, mfloat_t aspect, + mfloat_t n) +{ + struct mat4 result; + mat4_perspective_infinite((mfloat_t *) & result, fov_y, aspect, n); + return result; +} +#endif +#endif + +#if defined(MATHC_USE_POINTER_STRUCT_FUNCTIONS) +#if defined(MATHC_USE_INT) +bool psvec2i_is_zero(struct vec2i *v0) +{ + return vec2i_is_zero((mint_t *) v0); +} + +bool psvec2i_is_equal(struct vec2i *v0, struct vec2i *v1) +{ + return vec2i_is_equal((mint_t *) v0, (mint_t *) v1); +} + +struct vec2i *psvec2i(struct vec2i *result, mint_t x, mint_t y) +{ + return (struct vec2i *) vec2i((mint_t *) result, x, y); +} + +struct vec2i *psvec2i_assign(struct vec2i *result, struct vec2i *v0) +{ + return (struct vec2i *) vec2i_assign((mint_t *) result, (mint_t *) v0); +} + +#if defined(MATHC_USE_FLOATING_POINT) +struct vec2i *psvec2i_assign_vec2(struct vec2i *result, struct vec2 *v0) +{ + return (struct vec2i *) vec2i_assign_vec2((mint_t *) result, + (mfloat_t *) v0); +} +#endif + +struct vec2i *psvec2i_zero(struct vec2i *result) +{ + return (struct vec2i *) vec2i_zero((mint_t *) result); +} + +struct vec2i *psvec2i_one(struct vec2i *result) +{ + return (struct vec2i *) vec2i_one((mint_t *) result); +} + +struct vec2i *psvec2i_sign(struct vec2i *result, struct vec2i *v0) +{ + return (struct vec2i *) vec2i_sign((mint_t *) result, (mint_t *) v0); +} + +struct vec2i *psvec2i_add(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1) +{ + return (struct vec2i *) vec2i_add((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec2i *psvec2i_add_i(struct vec2i *result, struct vec2i *v0, + mint_t i) +{ + return (struct vec2i *) vec2i_add_i((mint_t *) result, (mint_t *) v0, + i); +} + +struct vec2i *psvec2i_subtract(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1) +{ + return (struct vec2i *) vec2i_subtract((mint_t *) result, + (mint_t *) v0, (mint_t *) v1); +} + +struct vec2i *psvec2i_subtract_i(struct vec2i *result, struct vec2i *v0, + mint_t i) +{ + return (struct vec2i *) vec2i_subtract_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec2i *psvec2i_multiply(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1) +{ + return (struct vec2i *) vec2i_multiply((mint_t *) result, + (mint_t *) v0, (mint_t *) v1); +} + +struct vec2i *psvec2i_multiply_i(struct vec2i *result, struct vec2i *v0, + mint_t i) +{ + return (struct vec2i *) vec2i_multiply_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec2i *psvec2i_divide(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1) +{ + return (struct vec2i *) vec2i_divide((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec2i *psvec2i_divide_i(struct vec2i *result, struct vec2i *v0, + mint_t i) +{ + return (struct vec2i *) vec2i_divide_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec2i *psvec2i_snap(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1) +{ + return (struct vec2i *) vec2i_snap((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec2i *psvec2i_snap_i(struct vec2i *result, struct vec2i *v0, + mint_t i) +{ + return (struct vec2i *) vec2i_snap_i((mint_t *) result, (mint_t *) v0, + i); +} + +struct vec2i *psvec2i_negative(struct vec2i *result, struct vec2i *v0) +{ + return (struct vec2i *) vec2i_negative((mint_t *) result, + (mint_t *) v0); +} + +struct vec2i *psvec2i_abs(struct vec2i *result, struct vec2i *v0) +{ + return (struct vec2i *) vec2i_abs((mint_t *) result, (mint_t *) v0); +} + +struct vec2i *psvec2i_max(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1) +{ + return (struct vec2i *) vec2i_max((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec2i *psvec2i_min(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1) +{ + return (struct vec2i *) vec2i_min((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec2i *psvec2i_clamp(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1, struct vec2i *v2) +{ + return (struct vec2i *) vec2i_clamp((mint_t *) result, (mint_t *) v0, + (mint_t *) v1, (mint_t *) v2); +} + +struct vec2i *psvec2i_tangent(struct vec2i *result, struct vec2i *v0) +{ + return (struct vec2i *) vec2i_tangent((mint_t *) result, + (mint_t *) v0); +} + +bool psvec3i_is_zero(struct vec3i *v0) +{ + return vec3i_is_zero((mint_t *) v0); +} + +bool psvec3i_is_equal(struct vec3i *v0, struct vec3i *v1) +{ + return vec3i_is_equal((mint_t *) v0, (mint_t *) v1); +} + +struct vec3i *psvec3i(struct vec3i *result, mint_t x, mint_t y, mint_t z) +{ + return (struct vec3i *) vec3i((mint_t *) result, x, y, z); +} + +struct vec3i *psvec3i_assign(struct vec3i *result, struct vec3i *v0) +{ + return (struct vec3i *) vec3i_assign((mint_t *) result, (mint_t *) v0); +} + +#if defined(MATHC_USE_FLOATING_POINT) +struct vec3i *psvec3i_assign_vec3(struct vec3i *result, struct vec3 *v0) +{ + return (struct vec3i *) vec3i_assign_vec3((mint_t *) result, + (mfloat_t *) v0); +} +#endif + +struct vec3i *psvec3i_zero(struct vec3i *result) +{ + return (struct vec3i *) vec3i_zero((mint_t *) result); +} + +struct vec3i *psvec3i_one(struct vec3i *result) +{ + return (struct vec3i *) vec3i_one((mint_t *) result); +} + +struct vec3i *psvec3i_sign(struct vec3i *result, struct vec3i *v0) +{ + return (struct vec3i *) vec3i_sign((mint_t *) result, (mint_t *) v0); +} + +struct vec3i *psvec3i_add(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_add((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec3i *psvec3i_add_i(struct vec3i *result, struct vec3i *v0, + mint_t i) +{ + return (struct vec3i *) vec3i_add_i((mint_t *) result, (mint_t *) v0, + i); +} + +struct vec3i *psvec3i_subtract(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_subtract((mint_t *) result, + (mint_t *) v0, (mint_t *) v1); +} + +struct vec3i *psvec3i_subtract_i(struct vec3i *result, struct vec3i *v0, + mint_t i) +{ + return (struct vec3i *) vec3i_subtract_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec3i *psvec3i_multiply(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_multiply((mint_t *) result, + (mint_t *) v0, (mint_t *) v1); +} + +struct vec3i *psvec3i_multiply_i(struct vec3i *result, struct vec3i *v0, + mint_t i) +{ + return (struct vec3i *) vec3i_multiply_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec3i *psvec3i_divide(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_divide((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec3i *psvec3i_divide_i(struct vec3i *result, struct vec3i *v0, + mint_t i) +{ + return (struct vec3i *) vec3i_divide_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec3i *psvec3i_snap(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_snap((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec3i *psvec3i_snap_i(struct vec3i *result, struct vec3i *v0, + mint_t i) +{ + return (struct vec3i *) vec3i_snap_i((mint_t *) result, (mint_t *) v0, + i); +} + +struct vec3i *psvec3i_cross(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_cross((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec3i *psvec3i_negative(struct vec3i *result, struct vec3i *v0) +{ + return (struct vec3i *) vec3i_negative((mint_t *) result, + (mint_t *) v0); +} + +struct vec3i *psvec3i_abs(struct vec3i *result, struct vec3i *v0) +{ + return (struct vec3i *) vec3i_abs((mint_t *) result, (mint_t *) v0); +} + +struct vec3i *psvec3i_max(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_max((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec3i *psvec3i_min(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1) +{ + return (struct vec3i *) vec3i_min((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec3i *psvec3i_clamp(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1, struct vec3i *v2) +{ + return (struct vec3i *) vec3i_clamp((mint_t *) result, (mint_t *) v0, + (mint_t *) v1, (mint_t *) v2); +} + +bool psvec4i_is_zero(struct vec4i *v0) +{ + return vec4i_is_zero((mint_t *) v0); +} + +bool psvec4i_is_equal(struct vec4i *v0, struct vec4i *v1) +{ + return vec4i_is_equal((mint_t *) v0, (mint_t *) v1); +} + +struct vec4i *psvec4i(struct vec4i *result, mint_t x, mint_t y, mint_t z, + mint_t w) +{ + return (struct vec4i *) vec4i((mint_t *) result, x, y, z, w); +} + +struct vec4i *psvec4i_assign(struct vec4i *result, struct vec4i *v0) +{ + return (struct vec4i *) vec4i_assign((mint_t *) result, (mint_t *) v0); +} + +#if defined(MATHC_USE_FLOATING_POINT) +struct vec4i *psvec4i_assign_vec4(struct vec4i *result, struct vec4 *v0) +{ + return (struct vec4i *) vec4i_assign_vec4((mint_t *) result, + (mfloat_t *) v0); +} +#endif + +struct vec4i *psvec4i_zero(struct vec4i *result) +{ + return (struct vec4i *) vec4i_zero((mint_t *) result); +} + +struct vec4i *psvec4i_one(struct vec4i *result) +{ + return (struct vec4i *) vec4i_one((mint_t *) result); +} + +struct vec4i *psvec4i_sign(struct vec4i *result, struct vec4i *v0) +{ + return (struct vec4i *) vec4i_sign((mint_t *) result, (mint_t *) v0); +} + +struct vec4i *psvec4i_add(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1) +{ + return (struct vec4i *) vec4i_add((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec4i *psvec4i_add_i(struct vec4i *result, struct vec4i *v0, + mint_t i) +{ + return (struct vec4i *) vec4i_add_i((mint_t *) result, (mint_t *) v0, + i); +} + +struct vec4i *psvec4i_subtract(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1) +{ + return (struct vec4i *) vec4i_subtract((mint_t *) result, + (mint_t *) v0, (mint_t *) v1); +} + +struct vec4i *psvec4i_subtract_i(struct vec4i *result, struct vec4i *v0, + mint_t i) +{ + return (struct vec4i *) vec4i_subtract_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec4i *psvec4i_multiply(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1) +{ + return (struct vec4i *) vec4i_multiply((mint_t *) result, + (mint_t *) v0, (mint_t *) v1); +} + +struct vec4i *psvec4i_multiply_i(struct vec4i *result, struct vec4i *v0, + mint_t i) +{ + return (struct vec4i *) vec4i_multiply_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec4i *psvec4i_divide(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1) +{ + return (struct vec4i *) vec4i_divide((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec4i *psvec4i_divide_i(struct vec4i *result, struct vec4i *v0, + mint_t i) +{ + return (struct vec4i *) vec4i_divide_i((mint_t *) result, + (mint_t *) v0, i); +} + +struct vec4i *psvec4i_snap(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1) +{ + return (struct vec4i *) vec4i_snap((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec4i *psvec4i_snap_i(struct vec4i *result, struct vec4i *v0, + mint_t i) +{ + return (struct vec4i *) vec4i_snap_i((mint_t *) result, (mint_t *) v0, + i); +} + +struct vec4i *psvec4i_negative(struct vec4i *result, struct vec4i *v0) +{ + return (struct vec4i *) vec4i_negative((mint_t *) result, + (mint_t *) v0); +} + +struct vec4i *psvec4i_abs(struct vec4i *result, struct vec4i *v0) +{ + return (struct vec4i *) vec4i_abs((mint_t *) result, (mint_t *) v0); +} + +struct vec4i *psvec4i_max(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1) +{ + return (struct vec4i *) vec4i_max((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec4i *psvec4i_min(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1) +{ + return (struct vec4i *) vec4i_min((mint_t *) result, (mint_t *) v0, + (mint_t *) v1); +} + +struct vec4i *psvec4i_clamp(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1, struct vec4i *v2) +{ + return (struct vec4i *) vec4i_clamp((mint_t *) result, (mint_t *) v0, + (mint_t *) v1, (mint_t *) v2); +} +#endif + +#if defined(MATHC_USE_FLOATING_POINT) +bool psvec2_is_zero(struct vec2 *v0) +{ + return vec2_is_zero((mfloat_t *) v0); +} + +bool psvec2_is_equal(struct vec2 *v0, struct vec2 *v1) +{ + return vec2_is_equal((mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec2 *psvec2(struct vec2 *result, mfloat_t x, mfloat_t y) +{ + return (struct vec2 *) vec2((mfloat_t *) result, x, y); +} + +struct vec2 *psvec2_assign(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_assign((mfloat_t *) result, + (mfloat_t *) v0); +} + +#if defined(MATHC_USE_INT) +struct vec2 *psvec2_assign_vec2i(struct vec2 *result, struct vec2i *v0) +{ + return (struct vec2 *) vec2_assign_vec2i((mfloat_t *) result, + (mint_t *) v0); +} +#endif + +struct vec2 *psvec2_zero(struct vec2 *result) +{ + return (struct vec2 *) vec2_zero((mfloat_t *) result); +} + +struct vec2 *psvec2_one(struct vec2 *result) +{ + return (struct vec2 *) vec2_one((mfloat_t *) result); +} + +struct vec2 *psvec2_sign(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_sign((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec2 *psvec2_add(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_add((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec2 *psvec2_add_f(struct vec2 *result, struct vec2 *v0, mfloat_t f) +{ + return (struct vec2 *) vec2_add_f((mfloat_t *) result, (mfloat_t *) v0, + f); +} + +struct vec2 *psvec2_subtract(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_subtract((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec2 *psvec2_subtract_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f) +{ + return (struct vec2 *) vec2_subtract_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec2 *psvec2_multiply(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_multiply((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec2 *psvec2_multiply_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f) +{ + return (struct vec2 *) vec2_multiply_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec2 *psvec2_multiply_mat2(struct vec2 *result, struct vec2 *v0, + struct mat2 *m0) +{ + return (struct vec2 *) vec2_multiply_mat2((mfloat_t *) result, + (mfloat_t *) v0, + (mfloat_t *) m0); +} + +struct vec2 *psvec2_divide(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_divide((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec2 *psvec2_divide_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f) +{ + return (struct vec2 *) vec2_divide_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec2 *psvec2_snap(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_snap((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec2 *psvec2_snap_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f) +{ + return (struct vec2 *) vec2_snap_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec2 *psvec2_negative(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_negative((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec2 *psvec2_abs(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_abs((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec2 *psvec2_floor(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_floor((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec2 *psvec2_ceil(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_ceil((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec2 *psvec2_round(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_round((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec2 *psvec2_max(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_max((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec2 *psvec2_min(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_min((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec2 *psvec2_clamp(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, struct vec2 *v2) +{ + return (struct vec2 *) vec2_clamp((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1, (mfloat_t *) v2); +} + +struct vec2 *psvec2_normalize(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_normalize((mfloat_t *) result, + (mfloat_t *) v0); +} + +mfloat_t psvec2_dot(struct vec2 *v0, struct vec2 *v1) +{ + return vec2_dot((mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec2 *psvec2_project(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1) +{ + return (struct vec2 *) vec2_project((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec2 *psvec2_slide(struct vec2 *result, struct vec2 *v0, + struct vec2 *normal) +{ + return (struct vec2 *) vec2_slide((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) normal); +} + +struct vec2 *psvec2_reflect(struct vec2 *result, struct vec2 *v0, + struct vec2 *normal) +{ + return (struct vec2 *) vec2_reflect((mfloat_t *) result, + (mfloat_t *) v0, + (mfloat_t *) normal); +} + +struct vec2 *psvec2_tangent(struct vec2 *result, struct vec2 *v0) +{ + return (struct vec2 *) vec2_tangent((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec2 *psvec2_rotate(struct vec2 *result, struct vec2 *v0, + mfloat_t f) +{ + return (struct vec2 *) vec2_rotate((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec2 *psvec2_lerp(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, mfloat_t f) +{ + return (struct vec2 *) vec2_lerp((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1, f); +} + +struct vec2 *psvec2_bezier3(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, struct vec2 *v2, mfloat_t f) +{ + return (struct vec2 *) vec2_bezier3((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1, + (mfloat_t *) v2, f); +} + +struct vec2 *psvec2_bezier4(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, struct vec2 *v2, + struct vec2 *v3, mfloat_t f) +{ + return (struct vec2 *) vec2_bezier4((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1, + (mfloat_t *) v2, (mfloat_t *) v3, + f); +} + +mfloat_t psvec2_angle(struct vec2 *v0) +{ + return vec2_angle((mfloat_t *) v0); +} + +mfloat_t psvec2_length(struct vec2 *v0) +{ + return vec2_length((mfloat_t *) v0); +} + +mfloat_t psvec2_length_squared(struct vec2 *v0) +{ + return vec2_length_squared((mfloat_t *) v0); +} + +mfloat_t psvec2_distance(struct vec2 *v0, struct vec2 *v1) +{ + return vec2_distance((mfloat_t *) v0, (mfloat_t *) v1); +} + +mfloat_t psvec2_distance_squared(struct vec2 *v0, struct vec2 *v1) +{ + return vec2_distance_squared((mfloat_t *) v0, (mfloat_t *) v1); +} + +bool psvec3_is_zero(struct vec3 *v0) +{ + return vec3_is_zero((mfloat_t *) v0); +} + +bool psvec3_is_equal(struct vec3 *v0, struct vec3 *v1) +{ + return vec3_is_equal((mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec3 *psvec3(struct vec3 *result, mfloat_t x, mfloat_t y, + mfloat_t z) +{ + return (struct vec3 *) vec3((mfloat_t *) result, x, y, z); +} + +struct vec3 *psvec3_assign(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_assign((mfloat_t *) result, + (mfloat_t *) v0); +} + +#if defined(MATHC_USE_INT) +struct vec3 *psvec3_assign_vec3i(struct vec3 *result, struct vec3i *v0) +{ + return (struct vec3 *) vec3_assign_vec3i((mfloat_t *) result, + (mint_t *) v0); +} +#endif + +struct vec3 *psvec3_zero(struct vec3 *result) +{ + return (struct vec3 *) vec3_zero((mfloat_t *) result); +} + +struct vec3 *psvec3_one(struct vec3 *result) +{ + return (struct vec3 *) vec3_one((mfloat_t *) result); +} + +struct vec3 *psvec3_sign(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_sign((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec3 *psvec3_add(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_add((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec3 *psvec3_add_f(struct vec3 *result, struct vec3 *v0, mfloat_t f) +{ + return (struct vec3 *) vec3_add_f((mfloat_t *) result, (mfloat_t *) v0, + f); +} + +struct vec3 *psvec3_subtract(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_subtract((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec3 *psvec3_subtract_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f) +{ + return (struct vec3 *) vec3_subtract_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec3 *psvec3_multiply(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_multiply((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec3 *psvec3_multiply_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f) +{ + return (struct vec3 *) vec3_multiply_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec3 *psvec3_multiply_mat3(struct vec3 *result, struct vec3 *v0, + struct mat3 *m0) +{ + return (struct vec3 *) vec3_multiply_mat3((mfloat_t *) result, + (mfloat_t *) v0, + (mfloat_t *) m0); +} + +struct vec3 *psvec3_divide(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_divide((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec3 *psvec3_divide_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f) +{ + return (struct vec3 *) vec3_divide_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec3 *psvec3_snap(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_snap((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec3 *psvec3_snap_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f) +{ + return (struct vec3 *) vec3_snap_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec3 *psvec3_negative(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_negative((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec3 *psvec3_abs(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_abs((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec3 *psvec3_floor(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_floor((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec3 *psvec3_ceil(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_ceil((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec3 *psvec3_round(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_round((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec3 *psvec3_max(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_max((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec3 *psvec3_min(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_min((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec3 *psvec3_clamp(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, struct vec3 *v2) +{ + return (struct vec3 *) vec3_clamp((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1, (mfloat_t *) v2); +} + +struct vec3 *psvec3_cross(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_cross((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec3 *psvec3_normalize(struct vec3 *result, struct vec3 *v0) +{ + return (struct vec3 *) vec3_normalize((mfloat_t *) result, + (mfloat_t *) v0); +} + +mfloat_t psvec3_dot(struct vec3 *v0, struct vec3 *v1) +{ + return vec3_dot((mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec3 *psvec3_project(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct vec3 *) vec3_project((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec3 *psvec3_slide(struct vec3 *result, struct vec3 *v0, + struct vec3 *normal) +{ + return (struct vec3 *) vec3_slide((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) normal); +} + +struct vec3 *psvec3_reflect(struct vec3 *result, struct vec3 *v0, + struct vec3 *normal) +{ + return (struct vec3 *) vec3_reflect((mfloat_t *) result, + (mfloat_t *) v0, + (mfloat_t *) normal); +} + +struct vec3 *psvec3_rotate(struct vec3 *result, struct vec3 *v0, + struct vec3 *ra, mfloat_t f) +{ + return (struct vec3 *) vec3_lerp((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) ra, f); +} + +struct vec3 *psvec3_lerp(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, mfloat_t f) +{ + return (struct vec3 *) vec3_lerp((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1, f); +} + +struct vec3 *psvec3_bezier3(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, struct vec3 *v2, mfloat_t f) +{ + return (struct vec3 *) vec3_bezier3((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1, + (mfloat_t *) v2, f); +} + +struct vec3 *psvec3_bezier4(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, struct vec3 *v2, + struct vec3 *v3, mfloat_t f) +{ + return (struct vec3 *) vec3_bezier4((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1, + (mfloat_t *) v2, (mfloat_t *) v3, + f); +} + +mfloat_t psvec3_length(struct vec3 *v0) +{ + return vec3_length((mfloat_t *) v0); +} + +mfloat_t psvec3_length_squared(struct vec3 *v0) +{ + return vec3_length_squared((mfloat_t *) v0); +} + +mfloat_t psvec3_distance(struct vec3 *v0, struct vec3 *v1) +{ + return vec3_distance((mfloat_t *) v0, (mfloat_t *) v1); +} + +mfloat_t psvec3_distance_squared(struct vec3 *v0, struct vec3 *v1) +{ + return vec3_distance_squared((mfloat_t *) v0, (mfloat_t *) v1); +} + +bool psvec4_is_zero(struct vec4 *v0) +{ + return vec4_is_zero((mfloat_t *) v0); +} + +bool psvec4_is_equal(struct vec4 *v0, struct vec4 *v1) +{ + return vec4_is_equal((mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec4 *psvec4(struct vec4 *result, mfloat_t x, mfloat_t y, + mfloat_t z, mfloat_t w) +{ + return (struct vec4 *) vec4((mfloat_t *) result, x, y, z, w); +} + +struct vec4 *psvec4_assign(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_assign((mfloat_t *) result, + (mfloat_t *) v0); +} + +#if defined(MATHC_USE_INT) +struct vec4 *psvec4_assign_vec4i(struct vec4 *result, struct vec4i *v0) +{ + return (struct vec4 *) vec4_assign_vec4i((mfloat_t *) result, + (mint_t *) v0); +} +#endif + +struct vec4 *psvec4_zero(struct vec4 *result) +{ + return (struct vec4 *) vec4_zero((mfloat_t *) result); +} + +struct vec4 *psvec4_one(struct vec4 *result) +{ + return (struct vec4 *) vec4_one((mfloat_t *) result); +} + +struct vec4 *psvec4_sign(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_sign((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec4 *psvec4_add(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1) +{ + return (struct vec4 *) vec4_add((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec4 *psvec4_add_f(struct vec4 *result, struct vec4 *v0, mfloat_t f) +{ + return (struct vec4 *) vec4_add_f((mfloat_t *) result, (mfloat_t *) v0, + f); +} + +struct vec4 *psvec4_subtract(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1) +{ + return (struct vec4 *) vec4_subtract((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec4 *psvec4_subtract_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f) +{ + return (struct vec4 *) vec4_subtract_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec4 *psvec4_multiply(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1) +{ + return (struct vec4 *) vec4_multiply((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec4 *psvec4_multiply_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f) +{ + return (struct vec4 *) vec4_multiply_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec4 *psvec4_multiply_mat4(struct vec4 *result, struct vec4 *v0, + struct mat4 *m0) +{ + return (struct vec4 *) vec4_multiply_mat4((mfloat_t *) result, + (mfloat_t *) v0, + (mfloat_t *) m0); +} + +struct vec4 *psvec4_divide(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1) +{ + return (struct vec4 *) vec4_divide((mfloat_t *) result, + (mfloat_t *) v0, (mfloat_t *) v1); +} + +struct vec4 *psvec4_divide_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f) +{ + return (struct vec4 *) vec4_divide_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec4 *psvec4_snap(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1) +{ + return (struct vec4 *) vec4_snap((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec4 *psvec4_snap_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f) +{ + return (struct vec4 *) vec4_snap_f((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct vec4 *psvec4_negative(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_negative((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec4 *psvec4_abs(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_abs((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec4 *psvec4_floor(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_floor((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec4 *psvec4_ceil(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_ceil((mfloat_t *) result, (mfloat_t *) v0); +} + +struct vec4 *psvec4_round(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_round((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec4 *psvec4_max(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1) +{ + return (struct vec4 *) vec4_max((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec4 *psvec4_min(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1) +{ + return (struct vec4 *) vec4_min((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct vec4 *psvec4_clamp(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1, struct vec4 *v2) +{ + return (struct vec4 *) vec4_clamp((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1, (mfloat_t *) v2); +} + +struct vec4 *psvec4_normalize(struct vec4 *result, struct vec4 *v0) +{ + return (struct vec4 *) vec4_normalize((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct vec4 *psvec4_lerp(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1, mfloat_t f) +{ + return (struct vec4 *) vec4_lerp((mfloat_t *) result, (mfloat_t *) v0, + (mfloat_t *) v1, f); +} + +bool psquat_is_zero(struct quat *q0) +{ + return quat_is_zero((mfloat_t *) q0); +} + +bool psquat_is_equal(struct quat *q0, struct quat *q1) +{ + return quat_is_equal((mfloat_t *) q0, (mfloat_t *) q1); +} + +struct quat *psquat(struct quat *result, mfloat_t x, mfloat_t y, + mfloat_t z, mfloat_t w) +{ + return (struct quat *) quat((mfloat_t *) result, x, y, z, w); +} + +struct quat *psquat_assign(struct quat *result, struct quat *q0) +{ + return (struct quat *) quat_assign((mfloat_t *) result, + (mfloat_t *) q0); +} + +struct quat *psquat_zero(struct quat *result) +{ + return (struct quat *) quat_zero((mfloat_t *) result); +} + +struct quat *psquat_null(struct quat *result) +{ + return (struct quat *) quat_null((mfloat_t *) result); +} + +struct quat *psquat_multiply(struct quat *result, struct quat *q0, + struct quat *q1) +{ + return (struct quat *) quat_multiply((mfloat_t *) result, + (mfloat_t *) q0, (mfloat_t *) q1); +} + +struct quat *psquat_multiply_f(struct quat *result, struct quat *q0, + mfloat_t f) +{ + return (struct quat *) quat_multiply_f((mfloat_t *) result, + (mfloat_t *) q0, f); +} + +struct quat *psquat_divide(struct quat *result, struct quat *q0, + struct quat *q1) +{ + return (struct quat *) quat_divide((mfloat_t *) result, + (mfloat_t *) q0, (mfloat_t *) q1); +} + +struct quat *psquat_divide_f(struct quat *result, struct quat *q0, + mfloat_t f) +{ + return (struct quat *) quat_divide_f((mfloat_t *) result, + (mfloat_t *) q0, f); +} + +struct quat *psquat_negative(struct quat *result, struct quat *q0) +{ + return (struct quat *) quat_negative((mfloat_t *) result, + (mfloat_t *) q0); +} + +struct quat *psquat_conjugate(struct quat *result, struct quat *q0) +{ + return (struct quat *) quat_conjugate((mfloat_t *) result, + (mfloat_t *) q0); +} + +struct quat *psquat_inverse(struct quat *result, struct quat *q0) +{ + return (struct quat *) quat_inverse((mfloat_t *) result, + (mfloat_t *) q0); +} + +struct quat *psquat_normalize(struct quat *result, struct quat *q0) +{ + return (struct quat *) quat_normalize((mfloat_t *) result, + (mfloat_t *) q0); +} + +mfloat_t psquat_dot(struct quat *q0, struct quat *q1) +{ + return quat_dot((mfloat_t *) q0, (mfloat_t *) q1); +} + +struct quat *psquat_power(struct quat *result, struct quat *q0, + mfloat_t exponent) +{ + return (struct quat *) quat_power((mfloat_t *) result, (mfloat_t *) q0, + exponent); +} + +struct quat *psquat_from_axis_angle(struct quat *result, struct vec3 *v0, + mfloat_t angle) +{ + return (struct quat *) quat_from_axis_angle((mfloat_t *) result, + (mfloat_t *) v0, angle); +} + +struct quat *psquat_from_vec3(struct quat *result, struct vec3 *v0, + struct vec3 *v1) +{ + return (struct quat *) quat_from_vec3((mfloat_t *) result, + (mfloat_t *) v0, + (mfloat_t *) v1); +} + +struct quat *psquat_from_mat4(struct quat *result, struct mat4 *m0) +{ + return (struct quat *) quat_from_mat4((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct quat *psquat_lerp(struct quat *result, struct quat *q0, + struct quat *q1, mfloat_t f) +{ + return (struct quat *) quat_lerp((mfloat_t *) result, (mfloat_t *) q0, + (mfloat_t *) q1, f); +} + +struct quat *psquat_slerp(struct quat *result, struct quat *q0, + struct quat *q1, mfloat_t f) +{ + return (struct quat *) quat_slerp((mfloat_t *) result, (mfloat_t *) q0, + (mfloat_t *) q1, f); +} + +mfloat_t psquat_length(struct quat *q0) +{ + return quat_length((mfloat_t *) q0); +} + +mfloat_t psquat_length_squared(struct quat *q0) +{ + return quat_length_squared((mfloat_t *) q0); +} + +mfloat_t psquat_angle(struct quat *q0, struct quat *q1) +{ + return quat_angle((mfloat_t *) q0, (mfloat_t *) q1); +} + +struct mat2 *psmat2(struct mat2 *result, mfloat_t m11, mfloat_t m12, + mfloat_t m21, mfloat_t m22) +{ + return (struct mat2 *) mat2((mfloat_t *) result, m11, m12, m21, m22); +} + +struct mat2 *psmat2_zero(struct mat2 *result) +{ + return (struct mat2 *) mat2_zero((mfloat_t *) result); +} + +struct mat2 *psmat2_identity(struct mat2 *result) +{ + return (struct mat2 *) mat2_identity((mfloat_t *) result); +} + +mfloat_t psmat2_determinant(struct mat2 *m0) +{ + return mat2_determinant((mfloat_t *) m0); +} + +struct mat2 *psmat2_assign(struct mat2 *result, struct mat2 *m0) +{ + return (struct mat2 *) mat2_assign((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat2 *psmat2_negative(struct mat2 *result, struct mat2 *m0) +{ + return (struct mat2 *) mat2_negative((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat2 *psmat2_transpose(struct mat2 *result, struct mat2 *m0) +{ + return (struct mat2 *) mat2_transpose((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat2 *psmat2_cofactor(struct mat2 *result, struct mat2 *m0) +{ + return (struct mat2 *) mat2_cofactor((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat2 *psmat2_adjugate(struct mat2 *result, struct mat2 *m0) +{ + return (struct mat2 *) mat2_adjugate((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat2 *psmat2_multiply(struct mat2 *result, struct mat2 *m0, + struct mat2 *m1) +{ + return (struct mat2 *) mat2_multiply((mfloat_t *) result, + (mfloat_t *) m0, (mfloat_t *) m1); +} + +struct mat2 *psmat2_multiply_f(struct mat2 *result, struct mat2 *m0, + mfloat_t f) +{ + return (struct mat2 *) mat2_multiply_f((mfloat_t *) result, + (mfloat_t *) m0, f); +} + +struct mat2 *psmat2_inverse(struct mat2 *result, struct mat2 *m0) +{ + return (struct mat2 *) mat2_inverse((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat2 *psmat2_scaling(struct mat2 *result, struct vec2 *v0) +{ + return (struct mat2 *) mat2_scaling((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct mat2 *psmat2_scale(struct mat2 *result, struct mat2 *m0, + struct vec2 *v0) +{ + return (struct mat2 *) mat2_scale((mfloat_t *) result, (mfloat_t *) m0, + (mfloat_t *) v0); +} + +struct mat2 *psmat2_rotation_z(struct mat2 *result, mfloat_t f) +{ + return (struct mat2 *) mat2_rotation_z((mfloat_t *) result, f); +} + +struct mat2 *psmat2_lerp(struct mat2 *result, struct mat2 *m0, + struct mat2 *m1, mfloat_t f) +{ + return (struct mat2 *) mat2_lerp((mfloat_t *) result, (mfloat_t *) m0, + (mfloat_t *) m1, f); +} + +struct mat3 *psmat3(struct mat3 *result, mfloat_t m11, mfloat_t m12, + mfloat_t m13, mfloat_t m21, mfloat_t m22, mfloat_t m23, + mfloat_t m31, mfloat_t m32, mfloat_t m33) +{ + return (struct mat3 *) mat3((mfloat_t *) result, m11, m12, m13, m21, + m22, m23, m31, m32, m33); +} + +struct mat3 *psmat3_zero(struct mat3 *result) +{ + return (struct mat3 *) mat3_zero((mfloat_t *) result); +} + +struct mat3 *psmat3_identity(struct mat3 *result) +{ + return (struct mat3 *) mat3_identity((mfloat_t *) result); +} + +mfloat_t psmat3_determinant(struct mat3 *m0) +{ + return mat3_determinant((mfloat_t *) m0); +} + +struct mat3 *psmat3_assign(struct mat3 *result, struct mat3 *m0) +{ + return (struct mat3 *) mat3_assign((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat3 *psmat3_negative(struct mat3 *result, struct mat3 *m0) +{ + return (struct mat3 *) mat3_negative((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat3 *psmat3_transpose(struct mat3 *result, struct mat3 *m0) +{ + return (struct mat3 *) mat3_transpose((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat3 *psmat3_cofactor(struct mat3 *result, struct mat3 *m0) +{ + return (struct mat3 *) mat3_cofactor((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat3 *psmat3_multiply(struct mat3 *result, struct mat3 *m0, + struct mat3 *m1) +{ + return (struct mat3 *) mat3_multiply((mfloat_t *) result, + (mfloat_t *) m0, (mfloat_t *) m1); +} + +struct mat3 *psmat3_multiply_f(struct mat3 *result, struct mat3 *m0, + mfloat_t f) +{ + return (struct mat3 *) mat3_multiply_f((mfloat_t *) result, + (mfloat_t *) m0, f); +} + +struct mat3 *psmat3_inverse(struct mat3 *result, struct mat3 *m0) +{ + return (struct mat3 *) mat3_inverse((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat3 *psmat3_scaling(struct mat3 *result, struct vec3 *v0) +{ + return (struct mat3 *) mat3_scaling((mfloat_t *) result, + (mfloat_t *) v0); +} + +struct mat3 *psmat3_scale(struct mat3 *result, struct mat3 *m0, + struct vec3 *v0) +{ + return (struct mat3 *) mat3_scale((mfloat_t *) result, (mfloat_t *) m0, + (mfloat_t *) v0); +} + +struct mat3 *psmat3_rotation_x(struct mat3 *result, mfloat_t f) +{ + return (struct mat3 *) mat3_rotation_x((mfloat_t *) result, f); +} + +struct mat3 *psmat3_rotation_y(struct mat3 *result, mfloat_t f) +{ + return (struct mat3 *) mat3_rotation_y((mfloat_t *) result, f); +} + +struct mat3 *psmat3_rotation_z(struct mat3 *result, mfloat_t f) +{ + return (struct mat3 *) mat3_rotation_z((mfloat_t *) result, f); +} + +struct mat3 *psmat3_rotation_axis(struct mat3 *result, struct vec3 *v0, + mfloat_t f) +{ + return (struct mat3 *) mat3_rotation_axis((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct mat3 *psmat3_rotation_quat(struct mat3 *result, struct quat *q0) +{ + return (struct mat3 *) mat3_rotation_quat((mfloat_t *) result, + (mfloat_t *) q0); +} + +struct mat3 *psmat3_lerp(struct mat3 *result, struct mat3 *m0, + struct mat3 *m1, mfloat_t f) +{ + return (struct mat3 *) mat3_lerp((mfloat_t *) result, (mfloat_t *) m0, + (mfloat_t *) m1, f); +} + +struct mat4 *psmat4(struct mat4 *result, mfloat_t m11, mfloat_t m12, + mfloat_t m13, mfloat_t m14, mfloat_t m21, mfloat_t m22, + mfloat_t m23, mfloat_t m24, mfloat_t m31, mfloat_t m32, + mfloat_t m33, mfloat_t m34, mfloat_t m41, mfloat_t m42, + mfloat_t m43, mfloat_t m44) +{ + return (struct mat4 *) mat4((mfloat_t *) result, m11, m12, m13, m14, + m21, m22, m23, m24, m31, m32, m33, m34, + m41, m42, m43, m44); +} + +struct mat4 *psmat4_zero(struct mat4 *result) +{ + return (struct mat4 *) mat4_zero((mfloat_t *) result); +} + +struct mat4 *psmat4_identity(struct mat4 *result) +{ + return (struct mat4 *) mat4_identity((mfloat_t *) result); +} + +mfloat_t psmat4_determinant(struct mat4 *m0) +{ + return mat4_determinant((mfloat_t *) m0); +} + +struct mat4 *psmat4_assign(struct mat4 *result, struct mat4 *m0) +{ + return (struct mat4 *) mat4_assign((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat4 *psmat4_negative(struct mat4 *result, struct mat4 *m0) +{ + return (struct mat4 *) mat4_negative((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat4 *psmat4_transpose(struct mat4 *result, struct mat4 *m0) +{ + return (struct mat4 *) mat4_transpose((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat4 *psmat4_cofactor(struct mat4 *result, struct mat4 *m0) +{ + return (struct mat4 *) mat4_cofactor((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat4 *psmat4_rotation_x(struct mat4 *result, mfloat_t f) +{ + return (struct mat4 *) mat4_rotation_x((mfloat_t *) result, f); +} + +struct mat4 *psmat4_rotation_y(struct mat4 *result, mfloat_t f) +{ + return (struct mat4 *) mat4_rotation_y((mfloat_t *) result, f); +} + +struct mat4 *psmat4_rotation_z(struct mat4 *result, mfloat_t f) +{ + return (struct mat4 *) mat4_rotation_z((mfloat_t *) result, f); +} + +struct mat4 *psmat4_rotation_axis(struct mat4 *result, struct vec3 *v0, + mfloat_t f) +{ + return (struct mat4 *) mat4_rotation_axis((mfloat_t *) result, + (mfloat_t *) v0, f); +} + +struct mat4 *psmat4_rotation_quat(struct mat4 *result, struct quat *q0) +{ + return (struct mat4 *) mat4_rotation_quat((mfloat_t *) result, + (mfloat_t *) q0); +} + +struct mat4 *psmat4_translation(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0) +{ + return (struct mat4 *) mat4_translation((mfloat_t *) result, + (mfloat_t *) m0, + (mfloat_t *) v0); +} + +struct mat4 *psmat4_translate(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0) +{ + return (struct mat4 *) mat4_translate((mfloat_t *) result, + (mfloat_t *) m0, + (mfloat_t *) v0); +} + +struct mat4 *psmat4_scaling(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0) +{ + return (struct mat4 *) mat4_scaling((mfloat_t *) result, + (mfloat_t *) m0, (mfloat_t *) v0); +} + +struct mat4 *psmat4_scale(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0) +{ + return (struct mat4 *) mat4_scale((mfloat_t *) result, (mfloat_t *) m0, + (mfloat_t *) v0); +} + +struct mat4 *psmat4_multiply(struct mat4 *result, struct mat4 *m0, + struct mat4 *m1) +{ + return (struct mat4 *) mat4_multiply((mfloat_t *) result, + (mfloat_t *) m0, (mfloat_t *) m1); +} + +struct mat4 *psmat4_multiply_f(struct mat4 *result, struct mat4 *m0, + mfloat_t f) +{ + return (struct mat4 *) mat4_multiply_f((mfloat_t *) result, + (mfloat_t *) m0, f); +} + +struct mat4 *psmat4_inverse(struct mat4 *result, struct mat4 *m0) +{ + return (struct mat4 *) mat4_inverse((mfloat_t *) result, + (mfloat_t *) m0); +} + +struct mat4 *psmat4_lerp(struct mat4 *result, struct mat4 *m0, + struct mat4 *m1, mfloat_t f) +{ + return (struct mat4 *) mat4_lerp((mfloat_t *) result, (mfloat_t *) m0, + (mfloat_t *) m1, f); +} + +struct mat4 *psmat4_look_at(struct mat4 *result, struct vec3 *position, + struct vec3 *target, struct vec3 *up) +{ + return (struct mat4 *) mat4_look_at((mfloat_t *) result, + (mfloat_t *) position, + (mfloat_t *) target, + (mfloat_t *) up); +} + +struct mat4 *psmat4_ortho(struct mat4 *result, mfloat_t l, mfloat_t r, + mfloat_t b, mfloat_t t, mfloat_t n, mfloat_t f) +{ + return (struct mat4 *) mat4_ortho((mfloat_t *) result, l, r, b, t, n, + f); +} + +struct mat4 *psmat4_perspective(struct mat4 *result, mfloat_t fov_y, + mfloat_t aspect, mfloat_t n, mfloat_t f) +{ + return (struct mat4 *) mat4_perspective((mfloat_t *) result, fov_y, + aspect, n, f); +} + +struct mat4 *psmat4_perspective_fov(struct mat4 *result, mfloat_t fov, + mfloat_t w, mfloat_t h, mfloat_t n, + mfloat_t f) +{ + return (struct mat4 *) mat4_perspective_fov((mfloat_t *) result, fov, + w, h, n, f); +} + +struct mat4 *psmat4_perspective_infinite(struct mat4 *result, + mfloat_t fov_y, mfloat_t aspect, + mfloat_t n) +{ + return (struct mat4 *) mat4_perspective_infinite((mfloat_t *) result, + fov_y, aspect, n); +} +#endif +#endif + +#if defined(MATHC_USE_FLOATING_POINT) && defined(MATHC_USE_EASING_FUNCTIONS) +mfloat_t quadratic_ease_out(mfloat_t f) +{ + return -f * (f - MFLOAT_C(2.0)); +} + +mfloat_t quadratic_ease_in(mfloat_t f) +{ + return f * f; +} + +mfloat_t quadratic_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(2.0) * f * f; + } else { + a = -MFLOAT_C(2.0) * f * f + MFLOAT_C(4.0) * f - MFLOAT_C(1.0); + } + return a; +} + +mfloat_t cubic_ease_out(mfloat_t f) +{ + mfloat_t a = f - MFLOAT_C(1.0); + return a * a * a + MFLOAT_C(1.0); +} + +mfloat_t cubic_ease_in(mfloat_t f) +{ + return f * f * f; +} + +mfloat_t cubic_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(4.0) * f * f * f; + } else { + a = MFLOAT_C(2.0) * f - MFLOAT_C(2.0); + a = MFLOAT_C(0.5) * a * a * a + MFLOAT_C(1.0); + } + return a; +} + +mfloat_t quartic_ease_out(mfloat_t f) +{ + mfloat_t a = f - MFLOAT_C(1.0); + return a * a * a * (MFLOAT_C(1.0) - f) + MFLOAT_C(1.0); +} + +mfloat_t quartic_ease_in(mfloat_t f) +{ + return f * f * f * f; +} + +mfloat_t quartic_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(8.0) * f * f * f * f; + } else { + a = f - MFLOAT_C(1.0); + a = -MFLOAT_C(8.0) * a * a * a * a + MFLOAT_C(1.0); + } + return a; +} + +mfloat_t quintic_ease_out(mfloat_t f) +{ + mfloat_t a = f - MFLOAT_C(1.0); + return a * a * a * a * a + MFLOAT_C(1.0); +} + +mfloat_t quintic_ease_in(mfloat_t f) +{ + return f * f * f * f * f; +} + +mfloat_t quintic_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(16.0) * f * f * f * f * f; + } else { + a = MFLOAT_C(2.0) * f - MFLOAT_C(2.0); + a = MFLOAT_C(0.5) * a * a * a * a * a + MFLOAT_C(1.0); + } + return a; +} + +mfloat_t sine_ease_out(mfloat_t f) +{ + return MSIN(f * MPI_2); +} + +mfloat_t sine_ease_in(mfloat_t f) +{ + return MSIN((f - MFLOAT_C(1.0)) * MPI_2) + MFLOAT_C(1.0); +} + +mfloat_t sine_ease_in_out(mfloat_t f) +{ + return MFLOAT_C(0.5) * (MFLOAT_C(1.0) - MCOS(f * MPI)); +} + +mfloat_t circular_ease_out(mfloat_t f) +{ + return MSQRT((MFLOAT_C(2.0) - f) * f); +} + +mfloat_t circular_ease_in(mfloat_t f) +{ + return MFLOAT_C(1.0) - MSQRT(MFLOAT_C(1.0) - (f * f)); +} + +mfloat_t circular_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(0.5) * (MFLOAT_C(1.0) - + MSQRT(MFLOAT_C(1.0) - MFLOAT_C(4.0) * f * f)); + } else { + a = MFLOAT_C(0.5) * + (MSQRT + (-(MFLOAT_C(2.0) * f - MFLOAT_C(3.0)) * + (MFLOAT_C(2.0) * f - MFLOAT_C(1.0))) + MFLOAT_C(1.0)); + } + return a; +} + +mfloat_t exponential_ease_out(mfloat_t f) +{ + mfloat_t a = f; + if (MFABS(a) > MFLT_EPSILON) { + a = MFLOAT_C(1.0) - MPOW(MFLOAT_C(2.0), -MFLOAT_C(10.0) * f); + } + return a; +} + +mfloat_t exponential_ease_in(mfloat_t f) +{ + mfloat_t a = f; + if (MFABS(a) > MFLT_EPSILON) { + a = MPOW(MFLOAT_C(2.0), MFLOAT_C(10.0) * (f - MFLOAT_C(1.0))); + } + return a; +} + +mfloat_t exponential_ease_in_out(mfloat_t f) +{ + mfloat_t a = f; + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(0.5) * MPOW(MFLOAT_C(2.0), + (MFLOAT_C(20.0) * f) - MFLOAT_C(10.0)); + } else { + a = -MFLOAT_C(0.5) * MPOW(MFLOAT_C(2.0), + -MFLOAT_C(20.0) * f + MFLOAT_C(10.0)) + + MFLOAT_C(1.0); + } + return a; +} + +mfloat_t elastic_ease_out(mfloat_t f) +{ + return MSIN(-MFLOAT_C(13.0) * MPI_2 * (f + MFLOAT_C(1.0))) * + MPOW(MFLOAT_C(2.0), -MFLOAT_C(10.0) * f) + MFLOAT_C(1.0); +} + +mfloat_t elastic_ease_in(mfloat_t f) +{ + return MSIN(MFLOAT_C(13.0) * MPI_2 * f) * MPOW(MFLOAT_C(2.0), + MFLOAT_C(10.0) * (f - + MFLOAT_C + (1.0))); +} + +mfloat_t elastic_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(0.5) * MSIN(MFLOAT_C(13.0) * MPI_2 * + (MFLOAT_C(2.0) * f)) * MPOW(MFLOAT_C(2.0), + MFLOAT_C(10.0) + * + ((MFLOAT_C + (2.0) * f) - + MFLOAT_C + (1.0))); + } else { + a = MFLOAT_C(0.5) * + (MSIN + (-MFLOAT_C(13.0) * MPI_2 * + ((MFLOAT_C(2.0) * f - MFLOAT_C(1.0)) + + MFLOAT_C(1.0))) * MPOW(MFLOAT_C(2.0), + -MFLOAT_C(10.0) * (MFLOAT_C(2.0) * + f - + MFLOAT_C(1.0))) + + MFLOAT_C(2.0)); + } + return a; +} + +mfloat_t back_ease_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(1.0) - f; + return MFLOAT_C(1.0) - (a * a * a - a * MSIN(a * MPI)); +} + +mfloat_t back_ease_in(mfloat_t f) +{ + return f * f * f - f * MSIN(f * MPI); +} + +mfloat_t back_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(2.0) * f; + a = MFLOAT_C(0.5) * (a * a * a - a * MSIN(a * MPI)); + } else { + a = (MFLOAT_C(1.0) - (MFLOAT_C(2.0) * f - MFLOAT_C(1.0))); + a = MFLOAT_C(0.5) * (MFLOAT_C(1.0) - + (a * a * a - a * MSIN(f * MPI))) + + MFLOAT_C(0.5); + } + return a; +} + +mfloat_t bounce_ease_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(4.0) / MFLOAT_C(11.0)) { + a = (MFLOAT_C(121.0) * f * f) / MFLOAT_C(16.0); + } else if (f < MFLOAT_C(8.0) / MFLOAT_C(11.0)) { + a = (MFLOAT_C(363.0) / MFLOAT_C(40.0) * f * f) - + (MFLOAT_C(99.0) / MFLOAT_C(10.0) * f) + + MFLOAT_C(17.0) / MFLOAT_C(5.0); + } else if (f < MFLOAT_C(9.0) / MFLOAT_C(10.0)) { + a = (MFLOAT_C(4356.0) / MFLOAT_C(361.0) * f * f) - + (MFLOAT_C(35442.0) / MFLOAT_C(1805.0) * f) + + MFLOAT_C(16061.0) / MFLOAT_C(1805.0); + } else { + a = (MFLOAT_C(54.0) / MFLOAT_C(5.0) * f * f) - + (MFLOAT_C(513.0) / MFLOAT_C(25.0) * f) + + MFLOAT_C(268.0) / MFLOAT_C(25.0); + } + return a; +} + +mfloat_t bounce_ease_in(mfloat_t f) +{ + return MFLOAT_C(1.0) - bounce_ease_out(MFLOAT_C(1.0) - f); +} + +mfloat_t bounce_ease_in_out(mfloat_t f) +{ + mfloat_t a = MFLOAT_C(0.0); + if (f < MFLOAT_C(0.5)) { + a = MFLOAT_C(0.5) * bounce_ease_in(f * MFLOAT_C(2.0)); + } else { + a = MFLOAT_C(0.5) * bounce_ease_out(f * MFLOAT_C(2.0) - + MFLOAT_C(1.0)) + MFLOAT_C(0.5); + } + return a; +} +#endif diff --git a/source/engine/mathc.h b/source/engine/mathc.h new file mode 100644 index 0000000..b58cfc7 --- /dev/null +++ b/source/engine/mathc.h @@ -0,0 +1,1659 @@ +/* +Copyright © 2018 Felipe Ferreira da Silva + +This software is provided 'as-is', without any express or implied warranty. In +no event will the authors be held liable for any damages arising from the use of +this software. + +Permission is granted to anyone to use this software for any purpose, including +commercial applications, and to alter it and redistribute it freely, subject to +the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be +n appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MATHC_H +#define MATHC_H + + + +// CONFIG +#define MATHC_USE_INT32 +#define MATHC_USE_SINGLE_FLOATING_POINT + + + +#include +#include + +#define MATHC_VERSION_YYYY 2019 +#define MATHC_VERSION_MM 02 +#define MATHC_VERSION_DD 16 +#define MATHC_VERSION_MICRO 0 + +#if !defined(MATHC_NO_INT) +#define MATHC_USE_INT +#endif + +#if !defined(MATHC_NO_FLOATING_POINT) +#define MATHC_USE_FLOATING_POINT +#endif + +#if !defined(MATHC_NO_POINTER_STRUCT_FUNCTIONS) +#define MATHC_USE_POINTER_STRUCT_FUNCTIONS +#endif + +#if !defined(MATHC_NO_STRUCT_FUNCTIONS) +#define MATHC_USE_STRUCT_FUNCTIONS +#endif + +#if !defined(MATHC_NO_EASING_FUNCTIONS) +#define MATHC_USE_EASING_FUNCTIONS +#endif + +#if defined(MATHC_USE_INT) +#include +#endif +#if defined(MATHC_USE_FLOATING_POINT) +#include +#endif + +#define VEC2_SIZE 2 +#define VEC3_SIZE 3 +#define VEC4_SIZE 4 +#define QUAT_SIZE 4 +#define MAT2_SIZE 4 +#define MAT3_SIZE 9 +#define MAT4_SIZE 16 + +extern const float UNITMAT4[16]; + +#if defined(MATHC_USE_INT) +#if defined(MATHC_INT_TYPE) + typedef MATHC_INT_TYPE mint_t; +#endif +#if !defined(MATHC_USE_INT8) && !defined(MATHC_USE_INT16) && !defined(MATHC_USE_INT32) && !defined(MATHC_USE_INT64) +#define MATHC_USE_INT32 +#endif +#if defined(MATHC_USE_INT8) +#if !defined(MATHC_INT_TYPE) + typedef int8_t mint_t; +#endif +#define MINT_MAX INT8_MAX +#define MINT_MIN INT8_MIN +#endif +#if defined(MATHC_USE_INT16) +#if !defined(MATHC_INT_TYPE) + typedef int16_t mint_t; +#endif +#define MINT_MAX INT16_MAX +#define MINT_MIN INT16_MIN +#endif +#if defined(MATHC_USE_INT32) +#if !defined(MATHC_INT_TYPE) + typedef int32_t mint_t; +#endif +#define MINT_MAX INT32_MAX +#define MINT_MIN INT32_MIN +#endif +#if defined(MATHC_USE_INT64) +#if !defined(MATHC_INT_TYPE) + typedef int64_t mint_t; +#endif +#define MINT_MAX INT64_MAX +#define MINT_MIN INT64_MIN +#endif +#endif + +#if defined(MATHC_USE_FLOATING_POINT) +#if defined(MATHC_FLOATING_POINT_TYPE) + typedef MATHC_FLOATING_POINT_TYPE mfloat_t; +#endif +#if !defined(MATHC_USE_SINGLE_FLOATING_POINT) && !defined(MATHC_USE_DOUBLE_FLOATING_POINT) +#define MATHC_USE_SINGLE_FLOATING_POINT +#endif +#if defined(MATHC_USE_SINGLE_FLOATING_POINT) +#if !defined(MATHC_FLOATING_POINT_TYPE) + typedef float mfloat_t; +#endif + + + + +#define MPI 3.1415926536f +#define MPI_2 1.5707963268f +#define MPI_4 0.7853981634f +#define MFLT_EPSILON FLT_EPSILON +#define MFABS fabsf +#define MFMIN fminf +#define MFMAX fmaxf +#define MSQRT sqrtf +#define MSIN sinf +#define MCOS cosf +#define MACOS acosf +#define MASIN asinf +#define MTAN tanf +#define MATAN2 atan2f +#define MPOW powf +#define MFLOOR floorf +#define MCEIL ceilf +#define MROUND roundf +#define MFLOAT_C(c) c ## f +#endif +#if defined(MATHC_USE_DOUBLE_FLOATING_POINT) +#if !defined(MATHC_FLOATING_POINT_TYPE) + typedef double mfloat_t; +#endif +#define MPI 3.14159265358979323846 +#define MPI_2 1.57079632679489661923 +#define MPI_4 0.78539816339744830962 +#define MFLT_EPSILON DBL_EPSILON +#define MFABS fabs +#define MFMIN fmin +#define MFMAX fmax +#define MSQRT sqrt +#define MSIN sin +#define MCOS cos +#define MACOS acos +#define MASIN asin +#define MTAN tan +#define MATAN2 atan2 +#define MPOW pow +#define MFLOOR floor +#define MCEIL ceil +#define MROUND round +#define MFLOAT_C(c) c +#endif +#endif + + +/* World constants */ + extern const mfloat_t VEC3ZERO[3]; + extern const mfloat_t UP[3]; + extern const mfloat_t DOWN[3]; + extern const mfloat_t FORWARD[3]; + extern const mfloat_t BACK[3]; + extern const mfloat_t RIGHT[3]; + extern const mfloat_t LEFT[3]; + + + + + +#if defined(MATHC_USE_STRUCT_FUNCTIONS) || defined(MATHC_USE_POINTER_STRUCT_FUNCTIONS) +#if defined(MATHC_USE_INT) + struct vec2i { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mint_t x; + mint_t y; + }; + mint_t v[VEC2_SIZE]; + }; +#else + mint_t x; + mint_t y; +#endif + }; + + struct vec3i { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mint_t x; + mint_t y; + mint_t z; + }; + mint_t v[VEC3_SIZE]; + }; +#else + mint_t x; + mint_t y; + mint_t z; +#endif + }; + + struct vec4i { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mint_t x; + mint_t y; + mint_t z; + mint_t w; + }; + mint_t v[VEC4_SIZE]; + }; +#else + mint_t x; + mint_t y; + mint_t z; + mint_t w; +#endif + }; +#endif + +#if defined(MATHC_USE_FLOATING_POINT) + struct vec2 { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mfloat_t x; + mfloat_t y; + }; + mfloat_t v[VEC2_SIZE]; + }; +#else + mfloat_t x; + mfloat_t y; +#endif + }; + + struct vec3 { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mfloat_t x; + mfloat_t y; + mfloat_t z; + }; + mfloat_t v[VEC3_SIZE]; + }; +#else + mfloat_t x; + mfloat_t y; + mfloat_t z; +#endif + }; + + struct vec4 { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mfloat_t x; + mfloat_t y; + mfloat_t z; + mfloat_t w; + }; + mfloat_t v[VEC4_SIZE]; + }; +#else + mfloat_t x; + mfloat_t y; + mfloat_t z; + mfloat_t w; +#endif + }; + + struct quat { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mfloat_t x; + mfloat_t y; + mfloat_t z; + mfloat_t w; + }; + mfloat_t v[QUAT_SIZE]; + }; +#else + mfloat_t x; + mfloat_t y; + mfloat_t z; + mfloat_t w; +#endif + }; + +/* +Matrix 2×2 representation: +0/m11 2/m12 +1/m21 3/m22 +*/ + struct mat2 { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mfloat_t m11; + mfloat_t m21; + mfloat_t m12; + mfloat_t m22; + }; + mfloat_t v[MAT2_SIZE]; + }; +#else + mfloat_t m11; + mfloat_t m21; + mfloat_t m12; + mfloat_t m22; +#endif + }; + +/* +Matrix 3×3 representation: +0/m11 3/m12 6/m13 +1/m21 4/m22 7/m23 +2/m31 5/m32 8/m33 +*/ + struct mat3 { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mfloat_t m11; + mfloat_t m21; + mfloat_t m31; + mfloat_t m12; + mfloat_t m22; + mfloat_t m32; + mfloat_t m13; + mfloat_t m23; + mfloat_t m33; + }; + mfloat_t v[MAT3_SIZE]; + }; +#else + mfloat_t m11; + mfloat_t m21; + mfloat_t m31; + mfloat_t m12; + mfloat_t m22; + mfloat_t m32; + mfloat_t m13; + mfloat_t m23; + mfloat_t m33; +#endif + }; + +/* +Matrix 4×4 representation: +0/m11 4/m12 8/m13 12/m14 +1/m21 5/m22 9/m23 13/m24 +2/m31 6/m32 10/m33 14/m34 +3/m41 7/m42 11/m43 15/m44 +*/ + struct mat4 { +#if defined(MATHC_USE_UNIONS) + union { + struct { + mfloat_t m11; + mfloat_t m21; + mfloat_t m31; + mfloat_t m41; + mfloat_t m12; + mfloat_t m22; + mfloat_t m32; + mfloat_t m42; + mfloat_t m13; + mfloat_t m23; + mfloat_t m33; + mfloat_t m43; + mfloat_t m14; + mfloat_t m24; + mfloat_t m34; + mfloat_t m44; + }; + mfloat_t v[MAT4_SIZE]; + }; +#else + mfloat_t m11; + mfloat_t m21; + mfloat_t m31; + mfloat_t m41; + mfloat_t m12; + mfloat_t m22; + mfloat_t m32; + mfloat_t m42; + mfloat_t m13; + mfloat_t m23; + mfloat_t m33; + mfloat_t m43; + mfloat_t m14; + mfloat_t m24; + mfloat_t m34; + mfloat_t m44; +#endif + }; +#endif +#endif + +#if defined(MATHC_USE_INT) + mint_t clampi(mint_t value, mint_t min, mint_t max); +#endif + + /* Standards for easy using */ + + extern const mfloat_t VEC2_ZERO[2]; + extern const mint_t VEC2I_ZERO[2]; + extern const mfloat_t VEC3_ZERO[3]; + extern const mint_t VEC3I_ZERO[3]; + + extern const mfloat_t VEC2_ONE[2]; + extern const mint_t VEC2I_ONE[2]; + extern const mfloat_t VEC3_ONE[3]; + extern const mint_t VEC3I_ONE[3]; + +#if defined(MATHC_USE_FLOATING_POINT) +#define MRADIANS(degrees) (degrees * MPI / MFLOAT_C(180.0)) +#define MDEGREES(radians) (radians * MFLOAT_C(180.0) / MPI) + bool nearly_equal(mfloat_t a, mfloat_t b, mfloat_t epsilon); + mfloat_t to_radians(mfloat_t degrees); + mfloat_t to_degrees(mfloat_t radians); + mfloat_t clampf(mfloat_t value, mfloat_t min, mfloat_t max); +#endif + +#if defined(MATHC_USE_INT) + bool vec2i_is_zero(mint_t * v0); + bool vec2i_is_equal(mint_t * v0, mint_t * v1); + mint_t *vec2i(mint_t * result, mint_t x, mint_t y); + mint_t *vec2i_assign(mint_t * result, mint_t * v0); +#if defined(MATHC_USE_FLOATING_POINT) + mint_t *vec2i_assign_vec2(mint_t * result, mfloat_t * v0); +#endif + mint_t *vec2i_zero(mint_t * result); + mint_t *vec2i_one(mint_t * result); + mint_t *vec2i_sign(mint_t * result, mint_t * v0); + mint_t *vec2i_add(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec2i_add_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec2i_subtract(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec2i_subtract_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec2i_multiply(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec2i_multiply_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec2i_divide(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec2i_divide_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec2i_snap(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec2i_snap_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec2i_negative(mint_t * result, mint_t * v0); + mint_t *vec2i_abs(mint_t * result, mint_t * v0); + mint_t *vec2i_max(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec2i_min(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec2i_clamp(mint_t * result, mint_t * v0, mint_t * v1, + mint_t * v2); + mint_t *vec2i_tangent(mint_t * result, mint_t * v0); + bool vec3i_is_zero(mint_t * v0); + bool vec3i_is_equal(mint_t * v0, mint_t * v1); + mint_t *vec3i(mint_t * result, mint_t x, mint_t y, mint_t z); + mint_t *vec3i_assign(mint_t * result, mint_t * v0); +#if defined(MATHC_USE_FLOATING_POINT) + mint_t *vec3i_assign_vec3(mint_t * result, mfloat_t * v0); +#endif + mint_t *vec3i_zero(mint_t * result); + mint_t *vec3i_one(mint_t * result); + mint_t *vec3i_sign(mint_t * result, mint_t * v0); + mint_t *vec3i_add(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_add_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec3i_subtract(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_subtract_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec3i_multiply(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_multiply_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec3i_divide(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_divide_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec3i_snap(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_snap_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec3i_cross(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_negative(mint_t * result, mint_t * v0); + mint_t *vec3i_abs(mint_t * result, mint_t * v0); + mint_t *vec3i_max(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_min(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec3i_clamp(mint_t * result, mint_t * v0, mint_t * v1, + mint_t * v2); + bool vec4i_is_zero(mint_t * v0); + bool vec4i_is_equal(mint_t * v0, mint_t * v1); + mint_t *vec4i(mint_t * result, mint_t x, mint_t y, mint_t z, mint_t w); + mint_t *vec4i_assign(mint_t * result, mint_t * v0); +#if defined(MATHC_USE_FLOATING_POINT) + mint_t *vec4i_assign_vec4(mint_t * result, mfloat_t * v0); +#endif + mint_t *vec4i_zero(mint_t * result); + mint_t *vec4i_one(mint_t * result); + mint_t *vec4i_sign(mint_t * result, mint_t * v0); + mint_t *vec4i_add(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec4i_add_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec4i_subtract(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec4i_subtract_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec4i_multiply(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec4i_multiply_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec4i_divide(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec4i_divide_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec4i_snap(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec4i_snap_i(mint_t * result, mint_t * v0, mint_t i); + mint_t *vec4i_negative(mint_t * result, mint_t * v0); + mint_t *vec4i_abs(mint_t * result, mint_t * v0); + mint_t *vec4i_max(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec4i_min(mint_t * result, mint_t * v0, mint_t * v1); + mint_t *vec4i_clamp(mint_t * result, mint_t * v0, mint_t * v1, + mint_t * v2); +#endif +#if defined(MATHC_USE_FLOATING_POINT) + bool vec2_is_zero(mfloat_t * v0); + bool vec2_is_equal(mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec2(mfloat_t * result, mfloat_t x, mfloat_t y); + mfloat_t *vec2_assign(mfloat_t * result, mfloat_t * v0); +#if defined(MATHC_USE_INT) + mfloat_t *vec2_assign_vec2i(mfloat_t * result, mint_t * v0); +#endif + mfloat_t *vec2_zero(mfloat_t * result); + mfloat_t *vec2_one(mfloat_t * result); + mfloat_t *vec2_sign(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec2_add(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec2_add_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec2_subtract(mfloat_t * result, mfloat_t * v0, + mfloat_t * v1); + mfloat_t *vec2_subtract_f(mfloat_t * result, mfloat_t * v0, + mfloat_t f); + mfloat_t *vec2_multiply(mfloat_t * result, mfloat_t * v0, + mfloat_t * v1); + mfloat_t *vec2_multiply_f(mfloat_t * result, mfloat_t * v0, + mfloat_t f); + mfloat_t *vec2_multiply_mat2(mfloat_t * result, mfloat_t * v0, + mfloat_t * m0); + mfloat_t *vec2_divide(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec2_divide_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec2_snap(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec2_snap_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec2_negative(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec2_abs(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec2_floor(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec2_ceil(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec2_round(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec2_max(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec2_min(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec2_clamp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2); + mfloat_t *vec2_normalize(mfloat_t * result, mfloat_t * v0); + mfloat_t vec2_dot(mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec2_project(mfloat_t * result, mfloat_t * v0, + mfloat_t * v1); + mfloat_t *vec2_slide(mfloat_t * result, mfloat_t * v0, + mfloat_t * normal); + mfloat_t *vec2_reflect(mfloat_t * result, mfloat_t * v0, + mfloat_t * normal); + mfloat_t *vec2_tangent(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec2_rotate(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec2_lerp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t f); + mfloat_t *vec2_bezier3(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t f); + mfloat_t *vec2_bezier4(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t * v3, mfloat_t f); + mfloat_t vec2_angle(mfloat_t * v0); + mfloat_t vec2_length(mfloat_t * v0); + mfloat_t vec2_length_squared(mfloat_t * v0); + mfloat_t vec2_distance(mfloat_t * v0, mfloat_t * v1); + mfloat_t vec2_distance_squared(mfloat_t * v0, mfloat_t * v1); + bool vec2_linear_independent(mfloat_t * v0, mfloat_t * v1); + mfloat_t **vec2_orthonormalization(mfloat_t result[2][2], + mfloat_t basis[2][2]); + bool vec3_is_zero(mfloat_t * v0); + bool vec3_is_equal(mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec3(mfloat_t * result, mfloat_t x, mfloat_t y, mfloat_t z); + mfloat_t *vec3_assign(mfloat_t * result, mfloat_t * v0); +#if defined(MATHC_USE_INT) + mfloat_t *vec3_assign_vec3i(mfloat_t * result, mint_t * v0); +#endif + mfloat_t *vec3_zero(mfloat_t * result); + mfloat_t *vec3_one(mfloat_t * result); + mfloat_t *vec3_sign(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec3_add(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1); + mfloat_t *vec3_add_f(mfloat_t * result, const mfloat_t * v0, + const mfloat_t f); + mfloat_t *vec3_subtract(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1); + mfloat_t *vec3_subtract_f(mfloat_t * result, const mfloat_t * v0, + const mfloat_t f); + mfloat_t *vec3_multiply(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1); + mfloat_t *vec3_multiply_f(mfloat_t * result, const mfloat_t * v0, + const mfloat_t f); + mfloat_t *vec3_multiply_mat3(mfloat_t * result, mfloat_t * v0, + mfloat_t * m0); + mfloat_t *vec3_divide(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec3_divide_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec3_snap(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec3_snap_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec3_negative(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec3_abs(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec3_floor(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec3_ceil(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec3_round(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec3_max(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec3_min(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec3_clamp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2); + mfloat_t *vec3_cross(mfloat_t * result, const mfloat_t * v0, + const mfloat_t * v1); + mfloat_t *vec3_normalize(mfloat_t * result, mfloat_t * v0); + mfloat_t vec3_dot(const mfloat_t * v0, const mfloat_t * v1); + mfloat_t *vec3_project(mfloat_t * result, mfloat_t * v0, + mfloat_t * v1); + mfloat_t *vec3_slide(mfloat_t * result, mfloat_t * v0, + mfloat_t * normal); + mfloat_t *vec3_reflect(mfloat_t * result, mfloat_t * v0, + mfloat_t * normal); + mfloat_t *vec3_rotate(mfloat_t * result, mfloat_t * v0, mfloat_t * ra, + mfloat_t f); + mfloat_t *vec3_lerp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t f); + mfloat_t *vec3_bezier3(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t f); + mfloat_t *vec3_bezier4(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2, mfloat_t * v3, mfloat_t f); + mfloat_t vec3_length(mfloat_t * v0); + mfloat_t vec3_length_squared(mfloat_t * v0); + mfloat_t vec3_distance(mfloat_t * v0, mfloat_t * v1); + mfloat_t vec3_distance_squared(mfloat_t * v0, mfloat_t * v1); + bool vec3_linear_independent(mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2); + mfloat_t **vec3_orthonormalization(mfloat_t result[3][3], + mfloat_t basis[3][3]); + + + mfloat_t *vec3_rotate_quat(mfloat_t * result, const mfloat_t * v, + const mfloat_t * q); + + struct vec3 psvec3_rotate_quat(const struct vec3 *v, struct quat *q); + + + bool vec4_is_zero(mfloat_t * v0); + bool vec4_is_equal(mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec4(mfloat_t * result, mfloat_t x, mfloat_t y, mfloat_t z, + mfloat_t w); + mfloat_t *vec4_assign(mfloat_t * result, mfloat_t * v0); + + + + + +#if defined(MATHC_USE_INT) + mfloat_t *vec4_assign_vec4i(mfloat_t * result, mint_t * v0); +#endif + mfloat_t *vec4_zero(mfloat_t * result); + mfloat_t *vec4_one(mfloat_t * result); + mfloat_t *vec4_sign(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec4_add(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec4_add_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec4_subtract(mfloat_t * result, mfloat_t * v0, + mfloat_t * v1); + mfloat_t *vec4_subtract_f(mfloat_t * result, mfloat_t * v0, + mfloat_t f); + mfloat_t *vec4_multiply(mfloat_t * result, mfloat_t * v0, + mfloat_t * v1); + mfloat_t *vec4_multiply_f(mfloat_t * result, mfloat_t * v0, + mfloat_t f); + mfloat_t *vec4_multiply_mat4(mfloat_t * result, mfloat_t * v0, + mfloat_t * m0); + mfloat_t *vec4_divide(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec4_divide_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec4_snap(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec4_snap_f(mfloat_t * result, mfloat_t * v0, mfloat_t f); + mfloat_t *vec4_negative(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec4_abs(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec4_floor(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec4_ceil(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec4_round(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec4_max(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec4_min(mfloat_t * result, mfloat_t * v0, mfloat_t * v1); + mfloat_t *vec4_clamp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t * v2); + mfloat_t *vec4_normalize(mfloat_t * result, mfloat_t * v0); + mfloat_t *vec4_lerp(mfloat_t * result, mfloat_t * v0, mfloat_t * v1, + mfloat_t f); + + + bool quat_is_zero(mfloat_t * q0); + bool quat_is_equal(mfloat_t * q0, mfloat_t * q1); + mfloat_t *quat(mfloat_t * result, mfloat_t x, mfloat_t y, mfloat_t z, + mfloat_t w); + + + + + mfloat_t *quat_assign(mfloat_t * result, mfloat_t * q0); + mfloat_t *quat_zero(mfloat_t * result); + mfloat_t *quat_null(mfloat_t * result); + mfloat_t *quat_multiply(mfloat_t * result, const mfloat_t * q0, + const mfloat_t * q1); + mfloat_t *quat_mult_dir3(mfloat_t * result, const mfloat_t * q, + const mfloat_t * v); + mfloat_t *quat_mult_3d(mfloat_t * result, const mfloat_t * q, + const mfloat_t * p); + mfloat_t *quat_multiply_f(mfloat_t * result, mfloat_t * q0, + mfloat_t f); + mfloat_t *quat_divide(mfloat_t * result, mfloat_t * q0, mfloat_t * q1); + mfloat_t *quat_divide_f(mfloat_t * result, mfloat_t * q0, mfloat_t f); + mfloat_t *quat_negative(mfloat_t * result, mfloat_t * q0); + mfloat_t *quat_conjugate(mfloat_t * result, const mfloat_t * q0); + mfloat_t *quat_inverse(mfloat_t * result, mfloat_t * q0); + mfloat_t *quat_normalize(mfloat_t * result, mfloat_t * q0); + mfloat_t quat_dot(mfloat_t * q0, mfloat_t * q1); + mfloat_t *quat_power(mfloat_t * result, mfloat_t * q0, + mfloat_t exponent); + mfloat_t *quat_from_axis_angle(mfloat_t * result, const mfloat_t * v0, + const mfloat_t angle); + mfloat_t *quat_from_vec3(mfloat_t * result, mfloat_t * v0, + mfloat_t * v1); + mfloat_t *quat_from_mat4(mfloat_t * result, mfloat_t * m0); + mfloat_t *quat_lerp(mfloat_t * result, mfloat_t * q0, mfloat_t * q1, + mfloat_t f); + mfloat_t *quat_slerp(mfloat_t * result, mfloat_t * q0, mfloat_t * q1, + mfloat_t f); + mfloat_t quat_length(mfloat_t * q0); + mfloat_t quat_length_squared(mfloat_t * q0); + mfloat_t quat_angle(mfloat_t * q0, mfloat_t * q1); + + mfloat_t *quat_from_euler(mfloat_t * q, const mfloat_t * euler); + + + mfloat_t *mat2(mfloat_t * result, mfloat_t m11, mfloat_t m12, + mfloat_t m21, mfloat_t m22); + mfloat_t *mat2_zero(mfloat_t * result); + mfloat_t *mat2_identity(mfloat_t * result); + mfloat_t mat2_determinant(mfloat_t * m0); + mfloat_t *mat2_assign(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat2_negative(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat2_transpose(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat2_cofactor(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat2_adjugate(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat2_multiply(mfloat_t * result, mfloat_t * m0, + mfloat_t * m1); + mfloat_t *mat2_multiply_f(mfloat_t * result, mfloat_t * m0, + mfloat_t f); + mfloat_t *mat2_inverse(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat2_scaling(mfloat_t * result, mfloat_t * v0); + mfloat_t *mat2_scale(mfloat_t * result, mfloat_t * m0, mfloat_t * v0); + mfloat_t *mat2_rotation_z(mfloat_t * result, mfloat_t f); + mfloat_t *mat2_lerp(mfloat_t * result, mfloat_t * m0, mfloat_t * m1, + mfloat_t f); + mfloat_t *mat3(mfloat_t * result, mfloat_t m11, mfloat_t m12, + mfloat_t m13, mfloat_t m21, mfloat_t m22, mfloat_t m23, + mfloat_t m31, mfloat_t m32, mfloat_t m33); + mfloat_t *mat3_zero(mfloat_t * result); + mfloat_t *mat3_identity(mfloat_t * result); + mfloat_t mat3_determinant(mfloat_t * m0); + mfloat_t *mat3_assign(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat3_negative(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat3_transpose(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat3_cofactor(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat3_multiply(mfloat_t * result, mfloat_t * m0, + mfloat_t * m1); + mfloat_t *mat3_multiply_f(mfloat_t * result, mfloat_t * m0, + mfloat_t f); + mfloat_t *mat3_inverse(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat3_scaling(mfloat_t * result, mfloat_t * v0); + mfloat_t *mat3_scale(mfloat_t * result, mfloat_t * m0, mfloat_t * v0); + mfloat_t *mat3_rotation_x(mfloat_t * result, mfloat_t f); + mfloat_t *mat3_rotation_y(mfloat_t * result, mfloat_t f); + mfloat_t *mat3_rotation_z(mfloat_t * result, mfloat_t f); + mfloat_t *mat3_rotation_axis(mfloat_t * result, mfloat_t * v0, + mfloat_t f); + mfloat_t *mat3_rotation_quat(mfloat_t * result, mfloat_t * q0); + mfloat_t *mat3_lerp(mfloat_t * result, mfloat_t * m0, mfloat_t * m1, + mfloat_t f); + mfloat_t *mat4(mfloat_t * result, mfloat_t m11, mfloat_t m12, + mfloat_t m13, mfloat_t m14, mfloat_t m21, mfloat_t m22, + mfloat_t m23, mfloat_t m24, mfloat_t m31, mfloat_t m32, + mfloat_t m33, mfloat_t m34, mfloat_t m41, mfloat_t m42, + mfloat_t m43, mfloat_t m44); + mfloat_t *mat4_zero(mfloat_t * result); + mfloat_t *mat4_identity(mfloat_t * result); + mfloat_t mat4_determinant(mfloat_t * m0); + mfloat_t *mat4_assign(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat4_negative(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat4_transpose(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat4_cofactor(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat4_rotation_x(mfloat_t * result, mfloat_t f); + mfloat_t *mat4_rotation_y(mfloat_t * result, mfloat_t f); + mfloat_t *mat4_rotation_z(mfloat_t * result, mfloat_t f); + mfloat_t *mat4_rotation_axis(mfloat_t * result, mfloat_t * v0, + mfloat_t f); + mfloat_t *mat4_rotation_quat(mfloat_t * result, mfloat_t * q0); + mfloat_t *mat4_translation(mfloat_t * result, mfloat_t * m0, + mfloat_t * v0); + + + mfloat_t *mat4_translate(mfloat_t * result, mfloat_t * m0, + mfloat_t * v0); + mfloat_t *mat4_translate_vec3(mfloat_t * mat4, mfloat_t * vec3); + mfloat_t *mat4_translate_vec2(mfloat_t * mat4, mfloat_t * vec2); + + mfloat_t *mat4_scaling(mfloat_t * result, mfloat_t * m0, + mfloat_t * v0); + mfloat_t *mat4_scale(mfloat_t * result, mfloat_t * m0, mfloat_t * v0); + + mfloat_t *mat4_scale_vec2(mfloat_t * mat4, mfloat_t * vec2); + mfloat_t *mat4_scale_vec3(mfloat_t * mat4, mfloat_t * vec3); + + mfloat_t *mat4_scale_vec2f(mfloat_t * mat4, mfloat_t f); + mfloat_t *mat4_scale_vec3f(mfloat_t * mat4, mfloat_t f); + + + mfloat_t *mat4_multiply(mfloat_t * result, mfloat_t * m0, + mfloat_t * m1); + mfloat_t *mat4_multiply_f(mfloat_t * result, mfloat_t * m0, + mfloat_t f); + mfloat_t *mat4_inverse(mfloat_t * result, mfloat_t * m0); + mfloat_t *mat4_lerp(mfloat_t * result, mfloat_t * m0, mfloat_t * m1, + mfloat_t f); + mfloat_t *mat4_look_at(mfloat_t * result, const mfloat_t * position, + const mfloat_t * target, const mfloat_t * up); + mfloat_t *mat4_ortho(mfloat_t * result, mfloat_t l, mfloat_t r, + mfloat_t b, mfloat_t t, mfloat_t n, mfloat_t f); + mfloat_t *mat4_perspective(mfloat_t * result, mfloat_t fov_y, + mfloat_t aspect, mfloat_t n, mfloat_t f); + mfloat_t *mat4_perspective_fov(mfloat_t * result, mfloat_t fov, + mfloat_t w, mfloat_t h, mfloat_t n, + mfloat_t f); + mfloat_t *mat4_perspective_infinite(mfloat_t * result, mfloat_t fov_y, + mfloat_t aspect, mfloat_t n); +#endif + +#if defined(MATHC_USE_STRUCT_FUNCTIONS) +#if defined(MATHC_USE_INT) + bool svec2i_is_zero(struct vec2i v0); + bool svec2i_is_equal(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i(mint_t x, mint_t y); + struct vec2i svec2i_assign(struct vec2i v0); +#if defined(MATHC_USE_FLOATING_POINT) + struct vec2i svec2i_assign_vec2(struct vec2 v0); +#endif + struct vec2i svec2i_zero(void); + struct vec2i svec2i_one(void); + struct vec2i svec2i_sign(struct vec2i v0); + struct vec2i svec2i_add(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i_add_i(struct vec2i v0, mint_t i); + struct vec2i svec2i_subtract(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i_subtract_i(struct vec2i v0, mint_t i); + struct vec2i svec2i_multiply(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i_multiply_i(struct vec2i v0, mint_t i); + struct vec2i svec2i_divide(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i_divide_i(struct vec2i v0, mint_t i); + struct vec2i svec2i_snap(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i_snap_i(struct vec2i v0, mint_t i); + struct vec2i svec2i_negative(struct vec2i v0); + struct vec2i svec2i_abs(struct vec2i v0); + struct vec2i svec2i_max(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i_min(struct vec2i v0, struct vec2i v1); + struct vec2i svec2i_clamp(struct vec2i v0, struct vec2i v1, + struct vec2i v2); + struct vec2i svec2i_tangent(struct vec2i v0); + bool svec3i_is_zero(struct vec3i v0); + bool svec3i_is_equal(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i(mint_t x, mint_t y, mint_t z); + struct vec3i svec3i_assign(struct vec3i v0); +#if defined(MATHC_USE_FLOATING_POINT) + struct vec3i svec3i_assign_vec3(struct vec3 v0); +#endif + struct vec3i svec3i_zero(void); + struct vec3i svec3i_one(void); + struct vec3i svec3i_sign(struct vec3i v0); + struct vec3i svec3i_add(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_add_i(struct vec3i v0, mint_t i); + struct vec3i svec3i_subtract(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_subtract_i(struct vec3i v0, mint_t i); + struct vec3i svec3i_multiply(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_multiply_i(struct vec3i v0, mint_t i); + struct vec3i svec3i_divide(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_divide_i(struct vec3i v0, mint_t i); + struct vec3i svec3i_snap(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_snap_i(struct vec3i v0, mint_t i); + struct vec3i svec3i_cross(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_negative(struct vec3i v0); + struct vec3i svec3i_abs(struct vec3i v0); + struct vec3i svec3i_max(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_min(struct vec3i v0, struct vec3i v1); + struct vec3i svec3i_clamp(struct vec3i v0, struct vec3i v1, + struct vec3i v2); + bool svec4i_is_zero(struct vec4i v0); + bool svec4i_is_equal(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i(mint_t x, mint_t y, mint_t z, mint_t w); + struct vec4i svec4i_assign(struct vec4i v0); +#if defined(MATHC_USE_FLOATING_POINT) + struct vec4i svec4i_assign_vec4(struct vec4 v0); +#endif + struct vec4i svec4i_zero(void); + struct vec4i svec4i_one(void); + struct vec4i svec4i_sign(struct vec4i v0); + struct vec4i svec4i_add(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i_add_i(struct vec4i v0, mint_t i); + struct vec4i svec4i_subtract(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i_subtract_i(struct vec4i v0, mint_t i); + struct vec4i svec4i_multiply(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i_multiply_i(struct vec4i v0, mint_t i); + struct vec4i svec4i_divide(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i_divide_i(struct vec4i v0, mint_t i); + struct vec4i svec4i_snap(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i_snap_i(struct vec4i v0, mint_t i); + struct vec4i svec4i_negative(struct vec4i v0); + struct vec4i svec4i_abs(struct vec4i v0); + struct vec4i svec4i_max(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i_min(struct vec4i v0, struct vec4i v1); + struct vec4i svec4i_clamp(struct vec4i v0, struct vec4i v1, + struct vec4i v2); +#endif +#if defined(MATHC_USE_FLOATING_POINT) + bool svec2_is_zero(struct vec2 v0); + bool svec2_is_equal(struct vec2 v0, struct vec2 v1); + struct vec2 svec2(mfloat_t x, mfloat_t y); + struct vec2 svec2_assign(struct vec2 v0); +#if defined(MATHC_USE_INT) + struct vec2 svec2_assign_vec2i(struct vec2i v0); +#endif + struct vec2 svec2_zero(void); + struct vec2 svec2_one(void); + struct vec2 svec2_sign(struct vec2 v0); + struct vec2 svec2_add(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_add_f(struct vec2 v0, mfloat_t f); + struct vec2 svec2_subtract(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_subtract_f(struct vec2 v0, mfloat_t f); + struct vec2 svec2_multiply(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_multiply_f(struct vec2 v0, mfloat_t f); + struct vec2 svec2_multiply_mat2(struct vec2 v0, struct mat2 m0); + struct vec2 svec2_divide(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_divide_f(struct vec2 v0, mfloat_t f); + struct vec2 svec2_snap(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_snap_f(struct vec2 v0, mfloat_t f); + struct vec2 svec2_negative(struct vec2 v0); + struct vec2 svec2_abs(struct vec2 v0); + struct vec2 svec2_floor(struct vec2 v0); + struct vec2 svec2_ceil(struct vec2 v0); + struct vec2 svec2_round(struct vec2 v0); + struct vec2 svec2_max(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_min(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_clamp(struct vec2 v0, struct vec2 v1, + struct vec2 v2); + struct vec2 svec2_normalize(struct vec2 v0); + mfloat_t svec2_dot(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_project(struct vec2 v0, struct vec2 v1); + struct vec2 svec2_slide(struct vec2 v0, struct vec2 normal); + struct vec2 svec2_reflect(struct vec2 v0, struct vec2 normal); + struct vec2 svec2_tangent(struct vec2 v0); + struct vec2 svec2_rotate(struct vec2 v0, mfloat_t f); + struct vec2 svec2_lerp(struct vec2 v0, struct vec2 v1, mfloat_t f); + struct vec2 svec2_bezier3(struct vec2 v0, struct vec2 v1, + struct vec2 v2, mfloat_t f); + struct vec2 svec2_bezier4(struct vec2 v0, struct vec2 v1, + struct vec2 v2, struct vec2 v3, mfloat_t f); + mfloat_t svec2_angle(struct vec2 v0); + mfloat_t svec2_length(struct vec2 v0); + mfloat_t svec2_length_squared(struct vec2 v0); + mfloat_t svec2_distance(struct vec2 v0, struct vec2 v1); + mfloat_t svec2_distance_squared(struct vec2 v0, struct vec2 v1); + bool svec3_is_zero(struct vec3 v0); + bool svec3_is_equal(struct vec3 v0, struct vec3 v1); + struct vec3 svec3(mfloat_t x, mfloat_t y, mfloat_t z); + struct vec3 svec3_assign(struct vec3 v0); +#if defined(MATHC_USE_INT) + struct vec3 svec3_assign_vec3i(struct vec3i v0); +#endif + struct vec3 svec3_zero(void); + struct vec3 svec3_one(void); + struct vec3 svec3_sign(struct vec3 v0); + struct vec3 svec3_add(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_add_f(struct vec3 v0, mfloat_t f); + struct vec3 svec3_subtract(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_subtract_f(struct vec3 v0, mfloat_t f); + struct vec3 svec3_multiply(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_multiply_f(struct vec3 v0, mfloat_t f); + struct vec3 svec3_multiply_mat3(struct vec3 v0, struct mat3 m0); + struct vec3 svec3_divide(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_divide_f(struct vec3 v0, mfloat_t f); + struct vec3 svec3_snap(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_snap_f(struct vec3 v0, mfloat_t f); + struct vec3 svec3_negative(struct vec3 v0); + struct vec3 svec3_abs(struct vec3 v0); + struct vec3 svec3_floor(struct vec3 v0); + struct vec3 svec3_ceil(struct vec3 v0); + struct vec3 svec3_round(struct vec3 v0); + struct vec3 svec3_max(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_min(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_clamp(struct vec3 v0, struct vec3 v1, + struct vec3 v2); + struct vec3 svec3_cross(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_normalize(struct vec3 v0); + mfloat_t svec3_dot(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_project(struct vec3 v0, struct vec3 v1); + struct vec3 svec3_slide(struct vec3 v0, struct vec3 normal); + struct vec3 svec3_reflect(struct vec3 v0, struct vec3 normal); + struct vec3 svec3_rotate(struct vec3 v0, struct vec3 ra, mfloat_t f); + struct vec3 svec3_lerp(struct vec3 v0, struct vec3 v1, mfloat_t f); + struct vec3 svec3_bezier3(struct vec3 v0, struct vec3 v1, + struct vec3 v2, mfloat_t f); + struct vec3 svec3_bezier4(struct vec3 v0, struct vec3 v1, + struct vec3 v2, struct vec3 v3, mfloat_t f); + mfloat_t svec3_length(struct vec3 v0); + mfloat_t svec3_length_squared(struct vec3 v0); + mfloat_t svec3_distance(struct vec3 v0, struct vec3 v1); + mfloat_t svec3_distance_squared(struct vec3 v0, struct vec3 v1); + bool svec4_is_zero(struct vec4 v0); + bool svec4_is_equal(struct vec4 v0, struct vec4 v1); + struct vec4 svec4(mfloat_t x, mfloat_t y, mfloat_t z, mfloat_t w); + struct vec4 svec4_assign(struct vec4 v0); +#if defined(MATHC_USE_INT) + struct vec4 svec4_assign_vec4i(struct vec4i v0); +#endif + struct vec4 svec4_zero(void); + struct vec4 svec4_one(void); + struct vec4 svec4_sign(struct vec4 v0); + struct vec4 svec4_add(struct vec4 v0, struct vec4 v1); + struct vec4 svec4_add_f(struct vec4 v0, mfloat_t f); + struct vec4 svec4_subtract(struct vec4 v0, struct vec4 v1); + struct vec4 svec4_subtract_f(struct vec4 v0, mfloat_t f); + struct vec4 svec4_multiply(struct vec4 v0, struct vec4 v1); + struct vec4 svec4_multiply_f(struct vec4 v0, mfloat_t f); + struct vec4 svec4_multiply_mat4(struct vec4 v0, struct mat4 m0); + struct vec4 svec4_divide(struct vec4 v0, struct vec4 v1); + struct vec4 svec4_divide_f(struct vec4 v0, mfloat_t f); + struct vec4 svec4_snap(struct vec4 v0, struct vec4 v1); + struct vec4 svec4_snap_f(struct vec4 v0, mfloat_t f); + struct vec4 svec4_negative(struct vec4 v0); + struct vec4 svec4_abs(struct vec4 v0); + struct vec4 svec4_floor(struct vec4 v0); + struct vec4 svec4_ceil(struct vec4 v0); + struct vec4 svec4_round(struct vec4 v0); + struct vec4 svec4_max(struct vec4 v0, struct vec4 v1); + struct vec4 svec4_min(struct vec4 v0, struct vec4 v1); + struct vec4 svec4_clamp(struct vec4 v0, struct vec4 v1, + struct vec4 v2); + struct vec4 svec4_normalize(struct vec4 v0); + struct vec4 svec4_lerp(struct vec4 v0, struct vec4 v1, mfloat_t f); + bool squat_is_zero(struct quat q0); + bool squat_is_equal(struct quat q0, struct quat q1); + + + struct quat squat(mfloat_t x, mfloat_t y, mfloat_t z, mfloat_t w); + struct quat squat_assign(struct quat q0); + struct quat squat_zero(void); + struct quat squat_null(void); + struct quat squat_multiply(struct quat q0, struct quat q1); + struct quat squat_multiply_f(struct quat q0, mfloat_t f); + struct quat squat_divide(struct quat q0, struct quat q1); + struct quat squat_divide_f(struct quat q0, mfloat_t f); + struct quat squat_negative(struct quat q0); + struct quat squat_conjugate(struct quat q0); + struct quat squat_inverse(struct quat q0); + struct quat squat_normalize(struct quat q0); + mfloat_t squat_dot(struct quat q0, struct quat q1); + struct quat squat_power(struct quat q0, mfloat_t exponent); + struct quat squat_from_axis_angle(struct vec3 v0, mfloat_t angle); + struct quat squat_from_vec3(struct vec3 v0, struct vec3 v1); + struct quat squat_from_mat4(struct mat4 m0); + struct quat squat_lerp(struct quat q0, struct quat q1, mfloat_t f); + struct quat squat_slerp(struct quat q0, struct quat q1, mfloat_t f); + + struct quat squat_from_euler(mfloat_t x, mfloat_t y, mfloat_t z); + + + mfloat_t squat_length(struct quat q0); + mfloat_t squat_length_squared(struct quat q0); + mfloat_t squat_angle(struct quat q0, struct quat q1); + struct mat2 smat2(mfloat_t m11, mfloat_t m12, mfloat_t m21, + mfloat_t m22); + struct mat2 smat2_zero(void); + struct mat2 smat2_identity(void); + mfloat_t smat2_determinant(struct mat2 m0); + struct mat2 smat2_assign(struct mat2 m0); + struct mat2 smat2_negative(struct mat2 m0); + struct mat2 smat2_transpose(struct mat2 m0); + struct mat2 smat2_cofactor(struct mat2 m0); + struct mat2 smat2_adjugate(struct mat2 m0); + struct mat2 smat2_multiply(struct mat2 m0, struct mat2 m1); + struct mat2 smat2_multiply_f(struct mat2 m0, mfloat_t f); + struct mat2 smat2_inverse(struct mat2 m0); + struct mat2 smat2_scaling(struct vec2 v0); + struct mat2 smat2_scale(struct mat2 m0, struct vec2 v0); + struct mat2 smat2_rotation_z(mfloat_t f); + struct mat2 smat2_lerp(struct mat2 m0, struct mat2 m1, mfloat_t f); + struct mat3 smat3(mfloat_t m11, mfloat_t m12, mfloat_t m13, + mfloat_t m21, mfloat_t m22, mfloat_t m23, + mfloat_t m31, mfloat_t m32, mfloat_t m33); + struct mat3 smat3_zero(void); + struct mat3 smat3_identity(void); + mfloat_t smat3_determinant(struct mat3 m0); + struct mat3 smat3_assign(struct mat3 m0); + struct mat3 smat3_negative(struct mat3 m0); + struct mat3 smat3_transpose(struct mat3 m0); + struct mat3 smat3_cofactor(struct mat3 m0); + struct mat3 smat3_multiply(struct mat3 m0, struct mat3 m1); + struct mat3 smat3_multiply_f(struct mat3 m0, mfloat_t f); + struct mat3 smat3_inverse(struct mat3 m0); + struct mat3 smat3_scaling(struct vec3 v0); + struct mat3 smat3_scale(struct mat3 m0, struct vec3 v0); + struct mat3 smat3_rotation_x(mfloat_t f); + struct mat3 smat3_rotation_y(mfloat_t f); + struct mat3 smat3_rotation_z(mfloat_t f); + struct mat3 smat3_rotation_axis(struct vec3 v0, mfloat_t f); + struct mat3 smat3_rotation_quat(struct quat q0); + struct mat3 smat3_lerp(struct mat3 m0, struct mat3 m1, mfloat_t f); + struct mat4 smat4(mfloat_t m11, mfloat_t m12, mfloat_t m13, + mfloat_t m14, mfloat_t m21, mfloat_t m22, + mfloat_t m23, mfloat_t m24, mfloat_t m31, + mfloat_t m32, mfloat_t m33, mfloat_t m34, + mfloat_t m41, mfloat_t m42, mfloat_t m43, + mfloat_t m44); + struct mat4 smat4_zero(void); + struct mat4 smat4_identity(void); + mfloat_t smat4_determinant(struct mat4 m0); + struct mat4 smat4_assign(struct mat4 m0); + struct mat4 smat4_negative(struct mat4 m0); + struct mat4 smat4_transpose(struct mat4 m0); + struct mat4 smat4_cofactor(struct mat4 m0); + struct mat4 smat4_rotation_x(mfloat_t f); + struct mat4 smat4_rotation_y(mfloat_t f); + struct mat4 smat4_rotation_z(mfloat_t f); + struct mat4 smat4_rotation_axis(struct vec3 v0, mfloat_t f); + struct mat4 smat4_rotation_quat(struct quat q0); + struct mat4 smat4_translation(struct mat4 m0, struct vec3 v0); + struct mat4 smat4_translate(struct mat4 m0, struct vec3 v0); + struct mat4 smat4_scaling(struct mat4 m0, struct vec3 v0); + struct mat4 smat4_scale(struct mat4 m0, struct vec3 v0); + struct mat4 smat4_multiply(struct mat4 m0, struct mat4 m1); + struct mat4 smat4_multiply_f(struct mat4 m0, mfloat_t f); + struct mat4 smat4_inverse(struct mat4 m0); + struct mat4 smat4_lerp(struct mat4 m0, struct mat4 m1, mfloat_t f); + struct mat4 smat4_look_at(struct vec3 position, struct vec3 target, + struct vec3 up); + struct mat4 smat4_ortho(mfloat_t l, mfloat_t r, mfloat_t b, mfloat_t t, + mfloat_t n, mfloat_t f); + struct mat4 smat4_perspective(mfloat_t fov_y, mfloat_t aspect, + mfloat_t n, mfloat_t f); + struct mat4 smat4_perspective_fov(mfloat_t fov, mfloat_t w, mfloat_t h, + mfloat_t n, mfloat_t f); + struct mat4 smat4_perspective_infinite(mfloat_t fov_y, mfloat_t aspect, + mfloat_t n); +#endif +#endif + +#if defined(MATHC_USE_POINTER_STRUCT_FUNCTIONS) +#if defined(MATHC_USE_INT) + bool psvec2i_is_zero(struct vec2i *v0); + bool psvec2i_is_equal(struct vec2i *v0, struct vec2i *v1); + struct vec2i *psvec2i(struct vec2i *result, mint_t x, mint_t y); + struct vec2i *psvec2i_assign(struct vec2i *result, struct vec2i *v0); +#if defined(MATHC_USE_FLOATING_POINT) + struct vec2i *psvec2i_assign_vec2(struct vec2i *result, + struct vec2 *v0); +#endif + struct vec2i *psvec2i_zero(struct vec2i *result); + struct vec2i *psvec2i_one(struct vec2i *result); + struct vec2i *psvec2i_sign(struct vec2i *result, struct vec2i *v0); + struct vec2i *psvec2i_add(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1); + struct vec2i *psvec2i_add_i(struct vec2i *result, struct vec2i *v0, + mint_t i); + struct vec2i *psvec2i_subtract(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1); + struct vec2i *psvec2i_subtract_i(struct vec2i *result, + struct vec2i *v0, mint_t i); + struct vec2i *psvec2i_multiply(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1); + struct vec2i *psvec2i_multiply_i(struct vec2i *result, + struct vec2i *v0, mint_t i); + struct vec2i *psvec2i_divide(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1); + struct vec2i *psvec2i_divide_i(struct vec2i *result, struct vec2i *v0, + mint_t i); + struct vec2i *psvec2i_snap(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1); + struct vec2i *psvec2i_snap_i(struct vec2i *result, struct vec2i *v0, + mint_t i); + struct vec2i *psvec2i_negative(struct vec2i *result, struct vec2i *v0); + struct vec2i *psvec2i_abs(struct vec2i *result, struct vec2i *v0); + struct vec2i *psvec2i_max(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1); + struct vec2i *psvec2i_min(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1); + struct vec2i *psvec2i_clamp(struct vec2i *result, struct vec2i *v0, + struct vec2i *v1, struct vec2i *v2); + struct vec2i *psvec2i_tangent(struct vec2i *result, struct vec2i *v0); + bool psvec3i_is_zero(struct vec3i *v0); + bool psvec3i_is_equal(struct vec3i *v0, struct vec3i *v1); + struct vec3i *psvec3i(struct vec3i *result, mint_t x, mint_t y, + mint_t z); + struct vec3i *psvec3i_assign(struct vec3i *result, struct vec3i *v0); +#if defined(MATHC_USE_FLOATING_POINT) + struct vec3i *psvec3i_assign_vec3(struct vec3i *result, + struct vec3 *v0); +#endif + struct vec3i *psvec3i_zero(struct vec3i *result); + struct vec3i *psvec3i_one(struct vec3i *result); + struct vec3i *psvec3i_sign(struct vec3i *result, struct vec3i *v0); + struct vec3i *psvec3i_add(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_add_i(struct vec3i *result, struct vec3i *v0, + mint_t i); + struct vec3i *psvec3i_subtract(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_subtract_i(struct vec3i *result, + struct vec3i *v0, mint_t i); + struct vec3i *psvec3i_multiply(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_multiply_i(struct vec3i *result, + struct vec3i *v0, mint_t i); + struct vec3i *psvec3i_divide(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_divide_i(struct vec3i *result, struct vec3i *v0, + mint_t i); + struct vec3i *psvec3i_snap(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_snap_i(struct vec3i *result, struct vec3i *v0, + mint_t i); + struct vec3i *psvec3i_cross(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_negative(struct vec3i *result, struct vec3i *v0); + struct vec3i *psvec3i_abs(struct vec3i *result, struct vec3i *v0); + struct vec3i *psvec3i_max(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_min(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1); + struct vec3i *psvec3i_clamp(struct vec3i *result, struct vec3i *v0, + struct vec3i *v1, struct vec3i *v2); + bool psvec4i_is_zero(struct vec4i *v0); + bool psvec4i_is_equal(struct vec4i *v0, struct vec4i *v1); + struct vec4i *psvec4i(struct vec4i *result, mint_t x, mint_t y, + mint_t z, mint_t w); + struct vec4i *psvec4i_assign(struct vec4i *result, struct vec4i *v0); +#if defined(MATHC_USE_FLOATING_POINT) + struct vec4i *psvec4i_assign_vec4(struct vec4i *result, + struct vec4 *v0); +#endif + struct vec4i *psvec4i_zero(struct vec4i *result); + struct vec4i *psvec4i_one(struct vec4i *result); + struct vec4i *psvec4i_sign(struct vec4i *result, struct vec4i *v0); + struct vec4i *psvec4i_add(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1); + struct vec4i *psvec4i_add_i(struct vec4i *result, struct vec4i *v0, + mint_t i); + struct vec4i *psvec4i_subtract(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1); + struct vec4i *psvec4i_subtract_i(struct vec4i *result, + struct vec4i *v0, mint_t i); + struct vec4i *psvec4i_multiply(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1); + struct vec4i *psvec4i_multiply_i(struct vec4i *result, + struct vec4i *v0, mint_t i); + struct vec4i *psvec4i_divide(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1); + struct vec4i *psvec4i_divide_i(struct vec4i *result, struct vec4i *v0, + mint_t i); + struct vec4i *psvec4i_snap(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1); + struct vec4i *psvec4i_snap_i(struct vec4i *result, struct vec4i *v0, + mint_t i); + struct vec4i *psvec4i_negative(struct vec4i *result, struct vec4i *v0); + struct vec4i *psvec4i_abs(struct vec4i *result, struct vec4i *v0); + struct vec4i *psvec4i_max(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1); + struct vec4i *psvec4i_min(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1); + struct vec4i *psvec4i_clamp(struct vec4i *result, struct vec4i *v0, + struct vec4i *v1, struct vec4i *v2); +#endif +#if defined(MATHC_USE_FLOATING_POINT) + bool psvec2_is_zero(struct vec2 *v0); + bool psvec2_is_equal(struct vec2 *v0, struct vec2 *v1); + struct vec2 *psvec2(struct vec2 *result, mfloat_t x, mfloat_t y); + struct vec2 *psvec2_assign(struct vec2 *result, struct vec2 *v0); +#if defined(MATHC_USE_INT) + struct vec2 *psvec2_assign_vec2i(struct vec2 *result, + struct vec2i *v0); +#endif + struct vec2 *psvec2_zero(struct vec2 *result); + struct vec2 *psvec2_one(struct vec2 *result); + struct vec2 *psvec2_sign(struct vec2 *result, struct vec2 *v0); + struct vec2 *psvec2_add(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_add_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f); + struct vec2 *psvec2_subtract(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_subtract_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f); + struct vec2 *psvec2_multiply(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_multiply_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f); + struct vec2 *psvec2_multiply_mat2(struct vec2 *result, struct vec2 *v0, + struct mat2 *m0); + struct vec2 *psvec2_divide(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_divide_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f); + struct vec2 *psvec2_snap(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_snap_f(struct vec2 *result, struct vec2 *v0, + mfloat_t f); + struct vec2 *psvec2_negative(struct vec2 *result, struct vec2 *v0); + struct vec2 *psvec2_abs(struct vec2 *result, struct vec2 *v0); + struct vec2 *psvec2_floor(struct vec2 *result, struct vec2 *v0); + struct vec2 *psvec2_ceil(struct vec2 *result, struct vec2 *v0); + struct vec2 *psvec2_round(struct vec2 *result, struct vec2 *v0); + struct vec2 *psvec2_max(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_min(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_clamp(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, struct vec2 *v2); + struct vec2 *psvec2_normalize(struct vec2 *result, struct vec2 *v0); + mfloat_t psvec2_dot(struct vec2 *v0, struct vec2 *v1); + struct vec2 *psvec2_project(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1); + struct vec2 *psvec2_slide(struct vec2 *result, struct vec2 *v0, + struct vec2 *normal); + struct vec2 *psvec2_reflect(struct vec2 *result, struct vec2 *v0, + struct vec2 *normal); + struct vec2 *psvec2_tangent(struct vec2 *result, struct vec2 *v0); + struct vec2 *psvec2_rotate(struct vec2 *result, struct vec2 *v0, + mfloat_t f); + struct vec2 *psvec2_lerp(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, mfloat_t f); + struct vec2 *psvec2_bezier3(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, struct vec2 *v2, + mfloat_t f); + struct vec2 *psvec2_bezier4(struct vec2 *result, struct vec2 *v0, + struct vec2 *v1, struct vec2 *v2, + struct vec2 *v3, mfloat_t f); + mfloat_t psvec2_angle(struct vec2 *v0); + mfloat_t psvec2_length(struct vec2 *v0); + mfloat_t psvec2_length_squared(struct vec2 *v0); + mfloat_t psvec2_distance(struct vec2 *v0, struct vec2 *v1); + mfloat_t psvec2_distance_squared(struct vec2 *v0, struct vec2 *v1); + bool psvec3_is_zero(struct vec3 *v0); + bool psvec3_is_equal(struct vec3 *v0, struct vec3 *v1); + struct vec3 *psvec3(struct vec3 *result, mfloat_t x, mfloat_t y, + mfloat_t z); + struct vec3 *psvec3_assign(struct vec3 *result, struct vec3 *v0); +#if defined(MATHC_USE_INT) + struct vec3 *psvec3_assign_vec3i(struct vec3 *result, + struct vec3i *v0); +#endif + struct vec3 *psvec3_zero(struct vec3 *result); + struct vec3 *psvec3_one(struct vec3 *result); + struct vec3 *psvec3_sign(struct vec3 *result, struct vec3 *v0); + struct vec3 *psvec3_add(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_add_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f); + struct vec3 *psvec3_subtract(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_subtract_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f); + struct vec3 *psvec3_multiply(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_multiply_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f); + struct vec3 *psvec3_multiply_mat3(struct vec3 *result, struct vec3 *v0, + struct mat3 *m0); + struct vec3 *psvec3_divide(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_divide_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f); + struct vec3 *psvec3_snap(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_snap_f(struct vec3 *result, struct vec3 *v0, + mfloat_t f); + struct vec3 *psvec3_negative(struct vec3 *result, struct vec3 *v0); + struct vec3 *psvec3_abs(struct vec3 *result, struct vec3 *v0); + struct vec3 *psvec3_floor(struct vec3 *result, struct vec3 *v0); + struct vec3 *psvec3_ceil(struct vec3 *result, struct vec3 *v0); + struct vec3 *psvec3_round(struct vec3 *result, struct vec3 *v0); + struct vec3 *psvec3_max(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_min(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_clamp(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, struct vec3 *v2); + struct vec3 *psvec3_cross(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_normalize(struct vec3 *result, struct vec3 *v0); + mfloat_t psvec3_dot(struct vec3 *v0, struct vec3 *v1); + struct vec3 *psvec3_project(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1); + struct vec3 *psvec3_slide(struct vec3 *result, struct vec3 *v0, + struct vec3 *normal); + struct vec3 *psvec3_reflect(struct vec3 *result, struct vec3 *v0, + struct vec3 *normal); + struct vec3 *psvec3_rotate(struct vec3 *result, struct vec3 *v0, + struct vec3 *ra, mfloat_t f); + struct vec3 *psvec3_lerp(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, mfloat_t f); + struct vec3 *psvec3_bezier3(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, struct vec3 *v2, + mfloat_t f); + struct vec3 *psvec3_bezier4(struct vec3 *result, struct vec3 *v0, + struct vec3 *v1, struct vec3 *v2, + struct vec3 *v3, mfloat_t f); + mfloat_t psvec3_length(struct vec3 *v0); + mfloat_t psvec3_length_squared(struct vec3 *v0); + mfloat_t psvec3_distance(struct vec3 *v0, struct vec3 *v1); + mfloat_t psvec3_distance_squared(struct vec3 *v0, struct vec3 *v1); + bool psvec4_is_zero(struct vec4 *v0); + bool psvec4_is_equal(struct vec4 *v0, struct vec4 *v1); + struct vec4 *psvec4(struct vec4 *result, mfloat_t x, mfloat_t y, + mfloat_t z, mfloat_t w); + struct vec4 *psvec4_assign(struct vec4 *result, struct vec4 *v0); +#if defined(MATHC_USE_INT) + struct vec4 *psvec4_assign_vec4i(struct vec4 *result, + struct vec4i *v0); +#endif + struct vec4 *psvec4_zero(struct vec4 *result); + struct vec4 *psvec4_one(struct vec4 *result); + struct vec4 *psvec4_sign(struct vec4 *result, struct vec4 *v0); + struct vec4 *psvec4_add(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1); + struct vec4 *psvec4_add_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f); + struct vec4 *psvec4_subtract(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1); + struct vec4 *psvec4_subtract_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f); + struct vec4 *psvec4_multiply(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1); + struct vec4 *psvec4_multiply_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f); + struct vec4 *psvec4_multiply_mat4(struct vec4 *result, struct vec4 *v0, + struct mat4 *m0); + struct vec4 *psvec4_divide(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1); + struct vec4 *psvec4_divide_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f); + struct vec4 *psvec4_snap(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1); + struct vec4 *psvec4_snap_f(struct vec4 *result, struct vec4 *v0, + mfloat_t f); + struct vec4 *psvec4_negative(struct vec4 *result, struct vec4 *v0); + struct vec4 *psvec4_abs(struct vec4 *result, struct vec4 *v0); + struct vec4 *psvec4_floor(struct vec4 *result, struct vec4 *v0); + struct vec4 *psvec4_ceil(struct vec4 *result, struct vec4 *v0); + struct vec4 *psvec4_round(struct vec4 *result, struct vec4 *v0); + struct vec4 *psvec4_max(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1); + struct vec4 *psvec4_min(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1); + struct vec4 *psvec4_clamp(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1, struct vec4 *v2); + struct vec4 *psvec4_normalize(struct vec4 *result, struct vec4 *v0); + struct vec4 *psvec4_lerp(struct vec4 *result, struct vec4 *v0, + struct vec4 *v1, mfloat_t f); + bool psquat_is_zero(struct quat *q0); + bool psquat_is_equal(struct quat *q0, struct quat *q1); + struct quat *psquat(struct quat *result, mfloat_t x, mfloat_t y, + mfloat_t z, mfloat_t w); + struct quat *psquat_assign(struct quat *result, struct quat *q0); + struct quat *psquat_zero(struct quat *result); + struct quat *psquat_null(struct quat *result); + struct quat *psquat_multiply(struct quat *result, struct quat *q0, + struct quat *q1); + struct quat *psquat_multiply_f(struct quat *result, struct quat *q0, + mfloat_t f); + struct quat *psquat_divide(struct quat *result, struct quat *q0, + struct quat *q1); + struct quat *psquat_divide_f(struct quat *result, struct quat *q0, + mfloat_t f); + struct quat *psquat_negative(struct quat *result, struct quat *q0); + struct quat *psquat_conjugate(struct quat *result, struct quat *q0); + struct quat *psquat_inverse(struct quat *result, struct quat *q0); + struct quat *psquat_normalize(struct quat *result, struct quat *q0); + mfloat_t psquat_dot(struct quat *q0, struct quat *q1); + struct quat *psquat_power(struct quat *result, struct quat *q0, + mfloat_t exponent); + struct quat *psquat_from_axis_angle(struct quat *result, + struct vec3 *v0, mfloat_t angle); + struct quat *psquat_from_vec3(struct quat *result, struct vec3 *v0, + struct vec3 *v1); + struct quat *psquat_from_mat4(struct quat *result, struct mat4 *m0); + struct quat *psquat_lerp(struct quat *result, struct quat *q0, + struct quat *q1, mfloat_t f); + struct quat *psquat_slerp(struct quat *result, struct quat *q0, + struct quat *q1, mfloat_t f); + mfloat_t psquat_length(struct quat *q0); + mfloat_t psquat_length_squared(struct quat *q0); + mfloat_t psquat_angle(struct quat *q0, struct quat *q1); + struct mat2 *psmat2(struct mat2 *result, mfloat_t m11, mfloat_t m12, + mfloat_t m21, mfloat_t m22); + struct mat2 *psmat2_zero(struct mat2 *result); + struct mat2 *psmat2_identity(struct mat2 *result); + mfloat_t psmat2_determinant(struct mat2 *m0); + struct mat2 *psmat2_assign(struct mat2 *result, struct mat2 *m0); + struct mat2 *psmat2_negative(struct mat2 *result, struct mat2 *m0); + struct mat2 *psmat2_transpose(struct mat2 *result, struct mat2 *m0); + struct mat2 *psmat2_cofactor(struct mat2 *result, struct mat2 *m0); + struct mat2 *psmat2_adjugate(struct mat2 *result, struct mat2 *m0); + struct mat2 *psmat2_multiply(struct mat2 *result, struct mat2 *m0, + struct mat2 *m1); + struct mat2 *psmat2_multiply_f(struct mat2 *result, struct mat2 *m0, + mfloat_t f); + struct mat2 *psmat2_inverse(struct mat2 *result, struct mat2 *m0); + struct mat2 *psmat2_scaling(struct mat2 *result, struct vec2 *v0); + struct mat2 *psmat2_scale(struct mat2 *result, struct mat2 *m0, + struct vec2 *v0); + struct mat2 *psmat2_rotation_z(struct mat2 *result, mfloat_t f); + struct mat2 *psmat2_lerp(struct mat2 *result, struct mat2 *m0, + struct mat2 *m1, mfloat_t f); + struct mat3 *psmat3(struct mat3 *result, mfloat_t m11, mfloat_t m12, + mfloat_t m13, mfloat_t m21, mfloat_t m22, + mfloat_t m23, mfloat_t m31, mfloat_t m32, + mfloat_t m33); + struct mat3 *psmat3_zero(struct mat3 *result); + struct mat3 *psmat3_identity(struct mat3 *result); + mfloat_t psmat3_determinant(struct mat3 *m0); + struct mat3 *psmat3_assign(struct mat3 *result, struct mat3 *m0); + struct mat3 *psmat3_negative(struct mat3 *result, struct mat3 *m0); + struct mat3 *psmat3_transpose(struct mat3 *result, struct mat3 *m0); + struct mat3 *psmat3_cofactor(struct mat3 *result, struct mat3 *m0); + struct mat3 *psmat3_multiply(struct mat3 *result, struct mat3 *m0, + struct mat3 *m1); + struct mat3 *psmat3_multiply_f(struct mat3 *result, struct mat3 *m0, + mfloat_t f); + struct mat3 *psmat3_inverse(struct mat3 *result, struct mat3 *m0); + struct mat3 *psmat3_scaling(struct mat3 *result, struct vec3 *v0); + struct mat3 *psmat3_scale(struct mat3 *result, struct mat3 *m0, + struct vec3 *v0); + struct mat3 *psmat3_rotation_x(struct mat3 *result, mfloat_t f); + struct mat3 *psmat3_rotation_y(struct mat3 *result, mfloat_t f); + struct mat3 *psmat3_rotation_z(struct mat3 *result, mfloat_t f); + struct mat3 *psmat3_rotation_axis(struct mat3 *result, struct vec3 *v0, + mfloat_t f); + struct mat3 *psmat3_rotation_quat(struct mat3 *result, + struct quat *q0); + struct mat3 *psmat3_lerp(struct mat3 *result, struct mat3 *m0, + struct mat3 *m1, mfloat_t f); + struct mat4 *psmat4(struct mat4 *result, mfloat_t m11, mfloat_t m12, + mfloat_t m13, mfloat_t m14, mfloat_t m21, + mfloat_t m22, mfloat_t m23, mfloat_t m24, + mfloat_t m31, mfloat_t m32, mfloat_t m33, + mfloat_t m34, mfloat_t m41, mfloat_t m42, + mfloat_t m43, mfloat_t m44); + struct mat4 *psmat4_zero(struct mat4 *result); + struct mat4 *psmat4_identity(struct mat4 *result); + mfloat_t psmat4_determinant(struct mat4 *m0); + struct mat4 *psmat4_assign(struct mat4 *result, struct mat4 *m0); + struct mat4 *psmat4_negative(struct mat4 *result, struct mat4 *m0); + struct mat4 *psmat4_transpose(struct mat4 *result, struct mat4 *m0); + struct mat4 *psmat4_cofactor(struct mat4 *result, struct mat4 *m0); + struct mat4 *psmat4_rotation_x(struct mat4 *result, mfloat_t f); + struct mat4 *psmat4_rotation_y(struct mat4 *result, mfloat_t f); + struct mat4 *psmat4_rotation_z(struct mat4 *result, mfloat_t f); + struct mat4 *psmat4_rotation_axis(struct mat4 *result, struct vec3 *v0, + mfloat_t f); + struct mat4 *psmat4_rotation_quat(struct mat4 *result, + struct quat *q0); + struct mat4 *psmat4_translation(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0); + struct mat4 *psmat4_translate(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0); + struct mat4 *psmat4_scaling(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0); + struct mat4 *psmat4_scale(struct mat4 *result, struct mat4 *m0, + struct vec3 *v0); + struct mat4 *psmat4_multiply(struct mat4 *result, struct mat4 *m0, + struct mat4 *m1); + struct mat4 *psmat4_multiply_f(struct mat4 *result, struct mat4 *m0, + mfloat_t f); + struct mat4 *psmat4_inverse(struct mat4 *result, struct mat4 *m0); + struct mat4 *psmat4_lerp(struct mat4 *result, struct mat4 *m0, + struct mat4 *m1, mfloat_t f); + struct mat4 *psmat4_look_at(struct mat4 *result, struct vec3 *position, + struct vec3 *target, struct vec3 *up); + struct mat4 *psmat4_ortho(struct mat4 *result, mfloat_t l, mfloat_t r, + mfloat_t b, mfloat_t t, mfloat_t n, + mfloat_t f); + struct mat4 *psmat4_perspective(struct mat4 *result, mfloat_t fov_y, + mfloat_t aspect, mfloat_t n, + mfloat_t f); + struct mat4 *psmat4_perspective_fov(struct mat4 *result, mfloat_t fov, + mfloat_t w, mfloat_t h, mfloat_t n, + mfloat_t f); + struct mat4 *psmat4_perspective_infinite(struct mat4 *result, + mfloat_t fov_y, + mfloat_t aspect, mfloat_t n); +#endif +#endif + +#if defined(MATHC_USE_FLOATING_POINT) && defined(MATHC_USE_EASING_FUNCTIONS) + mfloat_t quadratic_ease_out(mfloat_t f); + mfloat_t quadratic_ease_in(mfloat_t f); + mfloat_t quadratic_ease_in_out(mfloat_t f); + mfloat_t cubic_ease_out(mfloat_t f); + mfloat_t cubic_ease_in(mfloat_t f); + mfloat_t cubic_ease_in_out(mfloat_t f); + mfloat_t quartic_ease_out(mfloat_t f); + mfloat_t quartic_ease_in(mfloat_t f); + mfloat_t quartic_ease_in_out(mfloat_t f); + mfloat_t quintic_ease_out(mfloat_t f); + mfloat_t quintic_ease_in(mfloat_t f); + mfloat_t quintic_ease_in_out(mfloat_t f); + mfloat_t sine_ease_out(mfloat_t f); + mfloat_t sine_ease_in(mfloat_t f); + mfloat_t sine_ease_in_out(mfloat_t f); + mfloat_t circular_ease_out(mfloat_t f); + mfloat_t circular_ease_in(mfloat_t f); + mfloat_t circular_ease_in_out(mfloat_t f); + mfloat_t exponential_ease_out(mfloat_t f); + mfloat_t exponential_ease_in(mfloat_t f); + mfloat_t exponential_ease_in_out(mfloat_t f); + mfloat_t elastic_ease_out(mfloat_t f); + mfloat_t elastic_ease_in(mfloat_t f); + mfloat_t elastic_ease_in_out(mfloat_t f); + mfloat_t back_ease_out(mfloat_t f); + mfloat_t back_ease_in(mfloat_t f); + mfloat_t back_ease_in_out(mfloat_t f); + mfloat_t bounce_ease_out(mfloat_t f); + mfloat_t bounce_ease_in(mfloat_t f); + mfloat_t bounce_ease_in_out(mfloat_t f); +#endif + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/source/engine/mesh.c b/source/engine/mesh.c new file mode 100644 index 0000000..f455e43 --- /dev/null +++ b/source/engine/mesh.c @@ -0,0 +1,132 @@ +#include "mesh.h" + +#include "shader.h" +#include "texture.h" +#include +#include +#include +#include + +void DrawMesh(struct mMesh *mesh, struct mShader *shader) +{ + // bind appropriate textures + uint32_t diffuseNr = 1; + uint32_t specularNr = 1; + uint32_t normalNr = 1; + uint32_t heightNr = 1; + + for (uint32_t i = 0; i < (mesh->te - mesh->textures); i++) { + glActiveTexture(GL_TEXTURE0 + i); // active proper texture unit before binding + // retrieve texture number (the N in diffuse_textureN) + char number; + // TODO: malloc every single frame ... nope! Change to stack + char *name = + (char *) malloc(sizeof(char) * + (strlen(mesh->textures[i].type) + 2)); + if (mesh->textures[i].type == "texture_diffuse") + number = diffuseNr++; + else if (mesh->textures[i].type == "texture_specular") + number = specularNr++; + else if (mesh->textures[i].type == "texture_normal") + number = normalNr++; + else if (mesh->textures[i].type == "texture_height") + number = heightNr++; + + sprintf(name, "%s%d", mesh->textures[i].type, number); + // now set the sampler to the correct texture unit + glUniform1i(glGetUniformLocation(shader->id, name), i); + // and finally bind the texture + glBindTexture(GL_TEXTURE_2D, mesh->textures[i].id); + free(name); + } + + // draw mesh + glBindVertexArray(mesh->VAO); + DrawMeshAgain(mesh); + + // DEBUG + // triCount += indices.size() / 3; +} + + +void DrawMeshAgain(struct mMesh *mesh) +{ + glDrawElements(GL_TRIANGLES, (mesh->ie - mesh->indices), + GL_UNSIGNED_INT, 0); +} + +struct mMesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve, + uint32_t * indices, uint32_t * ie, + struct Texture *textures, struct Texture *te) +{ + struct mMesh *newmesh = (struct mMesh *) malloc(sizeof(struct mMesh)); + newmesh->vertices = vertices; + newmesh->ve = ve; + newmesh->indices = indices; + newmesh->ie = ie; + newmesh->textures = textures; + newmesh->te = te; + + setupmesh(newmesh); + return newmesh; +} + +void setupmesh(struct mMesh *mesh) +{ + // create buffers/arrays + glGenVertexArrays(1, &mesh->VAO); + glGenBuffers(1, &mesh->VBO); + glGenBuffers(1, &mesh->EBO); + + glBindVertexArray(mesh->VAO); + // load data into vertex buffers + glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO); + + + // The effect is that we can simply pass a pointer to the struct and it translates perfectly to vevc array which + // again translates to 3/2 floats which translates to a byte array. + glBufferData(GL_ARRAY_BUFFER, + (mesh->ve - mesh->vertices) * sizeof(struct Vertex), + &mesh->vertices[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + (mesh->ie - mesh->indices) * sizeof(uint32_t), + &mesh->indices[0], GL_STATIC_DRAW); + + // set the vertex attribute pointers + // vertex Positions + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), + (void *) 0); + // vertex normals + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), + (void *) offsetof(struct Vertex, Normal[3])); + // vertex texture coords + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), + (void *) offsetof(struct Vertex, TexCoords[2])); + // vertex tangent + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), + (void *) offsetof(struct Vertex, Tangent[3])); + // vertex bitangent + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), + (void *) offsetof(struct Vertex, Bitangent[3])); + + // Bone ids + glEnableVertexAttribArray(5); + glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, sizeof(struct Vertex), + (void *) offsetof(struct Vertex, + m_BoneIDs + [MAX_BONE_INFLUENCE])); + + // Weights + glEnableVertexAttribArray(6); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), + (void *) offsetof(struct Vertex, m_Weights)); + + glBindVertexArray(0); +} diff --git a/source/engine/mesh.h b/source/engine/mesh.h new file mode 100644 index 0000000..f0ddb70 --- /dev/null +++ b/source/engine/mesh.h @@ -0,0 +1,41 @@ +#ifndef MESH_H +#define MESH_H + +#include "mathc.h" +#include + +struct mShader; +struct Texture; + +#define MAX_BONE_INFLUENCE 4 + +struct Vertex { + mfloat_t Position[3]; + mfloat_t Normal[3]; + mfloat_t TexCoords[2]; + mfloat_t Tangent[3]; + mfloat_t Bitangent[3]; + + int m_BoneIDs[MAX_BONE_INFLUENCE]; + + float m_Weights[MAX_BONE_INFLUENCE]; +}; + +struct mMesh { + struct Vertex *vertices; + struct Vertex *ve; + uint32_t *indices; + uint32_t *ie; + struct Texture *textures; + struct Texture *te; + uint32_t VAO, VBO, EBO; +}; + +struct mMesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve, + uint32_t * indices, uint32_t * ie, + struct Texture *textures, struct Texture *te); +void setupmesh(struct mMesh *mesh); /* Loads mesh into the GPU */ +void DrawMesh(struct mMesh *mesh, struct mShader *shader); +void DrawMeshAgain(struct mMesh *mesh); /* Draws whatever mesh was drawn last */ + +#endif diff --git a/source/engine/model.c b/source/engine/model.c new file mode 100644 index 0000000..b7d0428 --- /dev/null +++ b/source/engine/model.c @@ -0,0 +1,281 @@ +#include "model.h" + +#include "mesh.h" +#include "resources.h" +#include "shader.h" +#include +#include +#include + +static struct mModel *lastRendered; +static struct mModel *loadedModels[100]; +static struct mModel **lastModel = loadedModels; + +static void processnode(); +static void processmesh(); +static void processtexture(); + + +struct mModel *GetExistingModel(const char *path) +{ + struct mModel **model = loadedModels; + + while (model++ != lastModel) { + if (!strcmp(path, (*model)->path)) + goto end; + + return MakeModel(path); + + } + + end: + return NULL; +} + +/* TODO: Make this a hash compare for speedup */ +struct mModel *MakeModel(const char *path) +{ + char *modelPath = + (char *) malloc(sizeof(char) * + (strlen(DATA_PATH) + strlen(path) + 1)); + modelPath[0] = '\0'; + strcat(modelPath, DATA_PATH); + strcat(modelPath, path); + printf + ("Created new model with modelPath %s, from data_path %s and path %s\n", + modelPath, DATA_PATH, path); + + struct mModel *newmodel = + (struct mModel *) malloc(sizeof(struct mModel)); + newmodel->path = path; + + loadmodel(newmodel); + *lastModel++ = newmodel; + return newmodel; +} + +// TODO: Come back to this; simple optimization +void draw_model(struct mModel *model, struct mShader *shader) +{ + if (lastRendered != model) { + lastRendered = model; + for (uint32_t i = 0; i < (model->mp - model->meshes); i++) + DrawMesh(&model->meshes[i], shader); + } else { + for (uint32_t i = 0; i < (model->mp - model->meshes); i++) + DrawMeshAgain(&model->meshes[i]); + } +} + +void loadmodel(struct mModel *model) +{ + printf("Loading model at path %s\n", model->path); +/* + // Load model with cgltf + cgltf_options options = {0}; + cgltf_data *data = NULL; + cgltf_result result = cgltf_parse_file(&options, model->path, &data); + + meshes = (struct mMesh*)malloc(sizeof(Mesh)*cgltf_data->meshes_count); + + directory = get_directory_from_path(model->path); + + for (int i = 0; i < data->nodes_count; i++) { + if (data->nodes[i]->mesh) { + for (int j = 0; j < data->nodes[i]->mesh->primatives_count; j++) { + + + for (int k = 0; k < data->nodes[i]->mesh->primatives[j]->attributes_count; k++) { + switch(data->nodes[i]->mesh->primatives[j]->attributes[k]->type) { + case cgltf_attribute_type_position: + Vertex *vs = (Vertex*)malloc(sizeof(Vertex) * cgltf_accessor_unpack_floats(:::attributes[k]->accesor, NULL, attributes[k]->accessor.count); + cgltf_accessor_unpack_floats(:::attributes[k]->accessor, vs, attributes[k]->accessor.count); + break; + + case cgltf_attribute_type_normal: + + break; + + case cgltf_attribute_type_tangent: + break; + + case cgltf_attribute_type_texcoord: + break; + + } + } + } + } + } + } + */ + + /* TODO: DELETE + + + + // read file via ASSIMP + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(path, + aiProcess_Triangulate | + aiProcess_GenSmoothNormals | + aiProcess_FlipUVs | + aiProcess_CalcTangentSpace); + // check for errors + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE + || !scene->mRootNode) { + YughLog(0, SDL_LOG_PRIORITY_ERROR, + "ASSIMP error: %s", + importer.GetErrorString()); + return; + } + + directory = get_directory_from_path(path); + + meshes = (Mesh *) malloc(sizeof(Mesh) * 100); + mp = meshes; + // process ASSIMP's root node recursively + processNode(scene->mRootNode, scene); */ +} + + +static void processnode() +{ +/* + for (uint32_t i = 0; i < node->mNumMeshes; i++) { + aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; + *mp = processMesh(mesh, scene); + mp++; + } + + for (uint32_t i = 0; i < node->mNumChildren; i++) { + processnode(node->mChildren[i], scene); + } +*/ +} + +static void processmesh() +{ +/* + Vertex *vertices = + (Vertex *) malloc(sizeof(Vertex) * mesh->mNumVertices); + Vertex *vp = vertices + mesh->mNumVertices; + Vertex *p = vertices; + for (int i = 0; i < mesh->mNumVertices; i++) { + // positions + (p + i)->Position.x = mesh->mVertices[i][0]; + (p + i)->Position.y = mesh->mVertices[i][1]; + (p + i)->Position.z = mesh->mVertices[i][2]; + + + // normals + if (mesh->HasNormals()) { + (p + i)->Normal.x = mesh->mNormals[i][0]; + (p + i)->Normal.y = mesh->mNormals[i].y; + (p + i)->Normal.z = mesh->mNormals[i].z; + } + + // texture coordinates + if (mesh->mTextureCoords[0]) { + glm::vec2 vec; + // a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't + // use models where a vertex can have multiple texture coordinates so we always take the first set (0). + (p + i)->TexCoords.x = mesh->mTextureCoords[0][i].x; + (p + i)->TexCoords.y = mesh->mTextureCoords[0][i].y; + + // tangent + (p + i)->Tangent.x = mesh->mTangents[i].x; + (p + i)->Tangent.y = mesh->mTangents[i].y; + (p + i)->Tangent.z = mesh->mTangents[i].z; + + // bitangent + (p + i)->Bitangent.x = mesh->mBitangents[i].x; + (p + i)->Bitangent.y = mesh->mBitangents[i].y; + (p + i)->Bitangent.z = mesh->mBitangents[i].z; + + } else + (p + i)->TexCoords = glm::vec2(0.0f, 0.0f); + } + + + + // TODO: Done quickly, find better way. Go through for loop twice! + int numindices = 0; + // now walk through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices. + for (uint32_t i = 0; i < mesh->mNumFaces; i++) { + numindices += mesh->mFaces[i].mNumIndices; + } + + uint32_t *indices = (uint32_t *) malloc(sizeof(uint32_t) * numindices); + uint32_t *ip = indices; + + for (uint32_t i = 0; i < mesh->mNumFaces; i++) { + for (uint32_t j = 0; j < mesh->mFaces[i].mNumIndices; j++) { + *ip = mesh->mFaces[i].mIndices[j]; + ip++; + } + } + + + // std::vector textures; + aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; + + // TODO: Allocating 100 to be safe, can probably be way less + textures_loaded = (Texture *) malloc(sizeof(Texture) * 100); + tp = textures_loaded; + // we assume a convention for sampler names in the shaders. Each diffuse texture should be named + // as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER. + // Same applies to other texture as the following list summarizes: + // diffuse: texture_diffuseN + // specular: texture_specularN + // normal: texture_normalN + + // 1. diffuse maps + loadMaterialTextures(material, aiTextureType_DIFFUSE, + "texture_diffuse"); + + // 2. specular maps + loadMaterialTextures(material, aiTextureType_SPECULAR, + "texture_specular"); + + // 3. normal maps + loadMaterialTextures(material, aiTextureType_NORMALS, + "texture_normal"); + + // 4. height maps + loadMaterialTextures(material, aiTextureType_AMBIENT, + "texture_height"); + + + // return a mesh object created from the extracted mesh data + return Mesh(vertices, vp, indices, ip, textures_loaded, tp); + + */ + +} + +// TODO: This routine mallocs inside the function +static void processtexture() +{ +/* + for (uint32_t i = 0; i < mat->GetTextureCount(type); i++) { + aiString str; + mat->GetTexture(type, i, &str); + for (Texture * tpp = textures_loaded; tpp != tp; tpp++) { + if (strcmp(tpp->path, str.data) == 0) + goto next; // Check if we already have this texture + } + + tp->id = TextureFromFile(str.data, this->directory); + tp->type = (char *) malloc(sizeof(char) * strlen(typeName)); + strcpy(tp->type, typeName); + tp->path = (char *) malloc(sizeof(char) * strlen(str.data)); + strcpy(tp->path, str.data); + + tp++; + + next:; + + } + */ +} diff --git a/source/engine/model.h b/source/engine/model.h new file mode 100644 index 0000000..8430cb9 --- /dev/null +++ b/source/engine/model.h @@ -0,0 +1,26 @@ +#ifndef MODEL_H +#define MODEL_H + +struct mMesh; +struct mShader; + +struct mModel { + struct mMesh *meshes; + struct mMesh *mp; + char *directory; + const char *path; + char *name; +}; + +/* Get the model at a path, or create and return if it doesn't exist */ +struct mModel *GetExistingModel(const char *path); + +/* Make a Model struct */ +struct mModel *MakeModel(const char *path); + +/* Load a model from memory into the GPU */ +void loadmodel(struct mModel *model); + +void draw_model(struct mModel *model, struct mShader *shader); + +#endif diff --git a/source/engine/openglrender.c b/source/engine/openglrender.c new file mode 100644 index 0000000..65d9a1c --- /dev/null +++ b/source/engine/openglrender.c @@ -0,0 +1,695 @@ +#include "openglrender.h" + +#include +#include +#include "sprite.h" +#include "shader.h" +#include "font.h" +#include "config.h" +#include "static_actor.h" +#include "gameobject.h" +#include "camera.h" +#include "window.h" +#include "debugdraw.h" +#include "log.h" + +int renderMode = 0; + +static GLuint UBO; +static GLuint UBOBind = 0; + +static GLuint gridVBO = 0; +static GLuint gridVAO = 0; + +static GLuint quadVAO = 0; +static GLuint quadVBO = 0; + +static GLuint depthMapFBO = 0; +static GLuint depthMap = 0; +const unsigned int SHADOW_WIDTH = 2048, SHADOW_HEIGHT = 2048; + +static struct mShader *outlineShader; +static struct mShader *modelShader; +static struct mShader *shadowShader; + +struct mShader *spriteShader = NULL; +struct mShader *animSpriteShader = NULL; +static struct mShader *textShader; +static struct mShader *diffuseShader; + +struct sFont stdFont; + +static struct mShader *debugDepthQuad; +static struct mShader *debugColorPickShader; +static struct mShader *debugGridShader; +static struct mShader *debugGizmoShader; + +struct mStaticActor *gizmo; + +float editorFOV = 45.f; +float editorClose = 0.1f; +float editorFar = 1000.f; +mfloat_t editorClearColor[4] = { 0.2f, 0.4f, 0.3f, 1.f }; + +float shadowLookahead = 8.5f; + +mfloat_t gridSmallColor[3] = { 0.35f, 1.f, 0.9f }; + +mfloat_t gridBigColor[3] = { 0.92f, 0.92f, 0.68f }; + +float gridScale = 500.f; +float smallGridUnit = 1.f; +float bigGridUnit = 10.f; +float gridSmallThickness = 2.f; +float gridBigThickness = 7.f; +float gridOpacity = 0.3f; + +mfloat_t proj[16]; + +float near_plane = -100.f, far_plane = 10.f, plane_size = 60.f; + + +// Debug render modes +bool renderGizmos = false; +bool showGrid = true; +bool debugDrawPhysics = false; +bool renderNav = false; + +// Lighting effect flags +bool renderAO = true; +bool renderDynamicShadows = true; +bool renderRefraction = true; +bool renderReflection = true; + +///// for editing +struct mGameObject *selectedobject = NULL; +char objectName[200] = { '\0' }; // object name buffer + +uint16_t debugColorPickBO = 0; +uint16_t debugColorPickTEX = 0; + + +struct mSprite *tsprite = NULL; +static struct mSprite *tanim = NULL; + +static unsigned int projUBO; + +void openglInit() +{ + //Initialize SDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) { + YughLog(0, SDL_LOG_PRIORITY_ERROR, + "SDL could not initialize! SDL Error: %s", SDL_GetError()); + } + //Use OpenGL 3.3 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, + SDL_GL_CONTEXT_PROFILE_CORE); + + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2); /* How many x MSAA */ + + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); + + // TODO: Add non starter initializtion return here for some reason? + window = MakeSDLWindow("Untitled Game", 1920, 1080, + SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | + SDL_WINDOW_RESIZABLE); + + //Use Vsync + if (SDL_GL_SetSwapInterval(1)) { + YughLog(0, SDL_LOG_PRIORITY_WARN, + "Unable to set VSync! SDL Error: %s", SDL_GetError()); + } + ////// MAKE SHADERS + outlineShader = MakeShader("outlinevert.glsl", "outline.glsl"); + + textShader = MakeShader("textvert.glsl", "textfrag.glsl"); + spriteShader = MakeShader("spritevert.glsl", "spritefrag.glsl"); + animSpriteShader = + MakeShader("animspritevert.glsl", "animspritefrag.glsl"); + + debugdraw_init(); + + stdFont = MakeFont("notosans.ttf", 300); + + //glEnable(GL_STENCIL_TEST); + glClearColor(editorClearColor[0], editorClearColor[1], + editorClearColor[2], editorClearColor[3]); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glLineWidth(1.3f); +/* + glEnable(GL_TEXTURE_3D); + glEnable(GL_MULTISAMPLE); + glLineWidth(2); + */ + + glGenBuffers(1, &projUBO); + glBindBuffer(GL_UNIFORM_BUFFER, projUBO); + glBufferData(GL_UNIFORM_BUFFER, 64, NULL, GL_DYNAMIC_DRAW); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, projUBO, 0, + sizeof(float) * 16); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + shader_setUBO(spriteShader, "Projection", 0); + shader_setUBO(textShader, "Projection", 0); + shader_setUBO(animSpriteShader, "Projection", 0); + + +} + +void openglRender(struct mCamera *mcamera) +{ + //////////// 2D projection + mfloat_t projection[16] = { 0.f }; + mat4_ortho(projection, mcamera->transform.position[0], + window->width + mcamera->transform.position[0], + mcamera->transform.position[1], + window->height + mcamera->transform.position[1], -1.f, 1.f); + glBindBuffer(GL_UNIFORM_BUFFER, projUBO); + glBufferSubData(GL_UNIFORM_BUFFER, 0, 64, projection); + + /* + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glCullFace(GL_BACK); + */ + // Clear color and depth + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT); + + ////// TEXT && GUI + /* + glDepthFunc(GL_ALWAYS); + shader_use(textShader); + shader_setmat4(textShader, "projection", window->projection); + + */ + + /* + mfloat_t fontpos[2] = { 25.f, 25.f }; + mfloat_t fontcolor[3] = { 0.5f, 0.8f, 0.2f }; + renderText(stdFont, textShader, "Sample text", fontpos, 0.4f, fontcolor, -1.f); + */ + + for (int i = 0; i < numSprites; i++) { + sprite_draw(sprites[i]); + } + + + //glDepthFunc(GL_LESS); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +void openglInit3d(struct mSDLWindow *window) +{ + //Initialize SDL + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { + YughLog(0, SDL_LOG_PRIORITY_ERROR, + "SDL could not initialize! SDL Error: %s", SDL_GetError()); + } + //Use OpenGL 3.3 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, + SDL_GL_CONTEXT_PROFILE_CORE); + + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2); /* How many x MSAA */ + + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); + + // TODO: Add non starter initializtion return here for some reason? + MakeSDLWindow("Untitled Game", 1280, 720, + SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | + SDL_WINDOW_RESIZABLE); + + + //Use Vsync + if (!SDL_GL_SetSwapInterval(1)) { + YughLog(0, SDL_LOG_PRIORITY_WARN, + "Unable to set VSync! SDL Error: %s", SDL_GetError()); + } +/* TODO: IMG init doesn't work in C+ + int init =(0x00000001 | 0x00000002); + int initted =IMG_Init(init); + YughLog(0, SDL_LOG_PRIORITY_ERROR, "Init flags: %d\nInitted values: %d ", init, initted); + if ((initted & (IMG_INIT_JPG | IMG_INIT_PNG)) != (IMG_INIT_JPG | IMG_INIT_PNG)) { + YughLog(0, SDL_LOG_PRIORITY_ERROR, + "IMG_Init: Failed to init required jpg and png support! SDL_IMG error: %s", + IMG_GetError()); + + } +*/ + + + + ////// MAKE SHADERS + outlineShader = MakeShader("outlinevert.glsl", "outline.glsl"); + diffuseShader = MakeShader("simplevert.glsl", "albedofrag.glsl"); + modelShader = MakeShader("modelvert.glsl", "modelfrag.glsl"); + shadowShader = MakeShader("shadowvert.glsl", "shadowfrag.glsl"); + + textShader = MakeShader("textvert.glsl", "textfrag.glsl"); + spriteShader = MakeShader("spritevert.glsl", "spritefrag.glsl"); + + debugDepthQuad = MakeShader("postvert.glsl", "debugdepthfrag.glsl"); + debugColorPickShader = + MakeShader("simplevert.glsl", "debugcolorfrag.glsl"); + debugGridShader = MakeShader("gridvert.glsl", "gridfrag.glsl"); + debugGizmoShader = MakeShader("gizmovert.glsl", "gizmofrag.glsl"); + + stdFont = MakeFont("notosans.ttf", 300); + + shader_compile_all(); + + mat4_perspective_fov(proj, editorFOV * DEG2RADS, window->width, + window->height, editorClose, editorFar); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_3D); + glEnable(GL_MULTISAMPLE); + glLineWidth(2); + + //// + // Shadow mapping buffers + //// + glGenFramebuffers(1, &depthMapFBO); + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + + glGenTextures(1, &depthMap); + glBindTexture(GL_TEXTURE_2D, depthMap); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, SHADOW_WIDTH, + SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, depthMap, 0); + glDrawBuffer(GL_NONE); + //glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + //// Universal buffer to hold projection and light coordinates + glGenBuffers(1, &UBO); + glBindBuffer(GL_UNIFORM_BUFFER, UBO); + + glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(proj), NULL, + GL_STATIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, UBO, 0, 2 * sizeof(proj)); + + + glBindBuffer(GL_UNIFORM_BUFFER, UBO); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(proj), proj); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + ////// debug color pick buffer + glGenFramebuffers(1, &debugColorPickBO); + glBindFramebuffer(GL_FRAMEBUFFER, debugColorPickBO); + + glGenTextures(1, &debugColorPickTEX); + glBindTexture(GL_TEXTURE_2D, debugColorPickTEX); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCREEN_WIDTH, SCREEN_HEIGHT, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, debugColorPickTEX, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + + //////// Create grid + float gridVertices[] = { + -1.f, 0.f, 1.f, 0.f, 1.f, + -1.f, 0.f, -1.f, 0.f, 0.f, + 1.f, 0.f, 1.f, 1.f, 1.f, + 1.f, 0.f, -1.f, 1.f, 0.f, + }; + + glGenVertexArrays(1, &gridVAO); + glGenBuffers(1, &gridVBO); + glBindVertexArray(gridVAO); + glBindBuffer(GL_ARRAY_BUFFER, gridVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(gridVertices), &gridVertices, + GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), + (void *) 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), + (void *) (3 * sizeof(float))); + + //////// Create post quad + float quadVertices[] = { + // positions // texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + // setup plane VAO + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, + GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), + (void *) 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), + (void *) (3 * sizeof(float))); + + ////// + + // skybox = new Skybox("skybox"); + + BindUniformBlock(modelShader->id, "Matrices", 0); + BindUniformBlock(outlineShader->id, "Matrices", 0); + // BindUniformBlock(skybox->shader->id, "Matrices", 0); + BindUniformBlock(diffuseShader->id, "Matrices", 0); + + BindUniformBlock(debugGridShader->id, "Matrices", 0); + BindUniformBlock(debugGizmoShader->id, "Matrices", 0); + + shader_use(debugDepthQuad); + shader_setint(debugDepthQuad, "depthMap", 0); + + glBindTexture(GL_TEXTURE_2D, 0); + + //////////// 2D projection + mfloat_t projection[16] = { 0.f }; + mat4_ortho(projection, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT, 1.f, -1.f, + 1.f); + shader_setmat4(textShader, "projection", projection); + shader_setmat4(spriteShader, "projection", projection); + shader_setmat4(debugGizmoShader, "proj", projection); + + + + +} + +void openglRender3d(struct mSDLWindow *window, struct mCamera *mcamera) +{ + //////// SET NEW PROJECTION + // TODO: Make this not happen every frame + mat4_perspective_fov(proj, editorFOV * DEG2RADS, window->width, + window->height, editorClose, editorFar); + + glBindBuffer(GL_UNIFORM_BUFFER, UBO); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(proj), proj); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + ////////// Render a depthmap from the perspective of the directional light + + glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + glCullFace(GL_BACK); + glClear(GL_DEPTH_BUFFER_BIT); + + // Configure matrices with an orthogonal + mfloat_t lightView[16] = { 0.f }; + mfloat_t lightSpaceMatrix[16] = { 0.f }; + +/* + if (dLight) { + + mfloat_t lightProjection[16] = { 0.f }; + mat4_ortho(lightProjection, -plane_size, plane_size, -plane_size, + plane_size, near_plane, far_plane); + + mfloat_t lookPos[3] = { 0.f }; + mfloat_t cam_fwd[3] = { 0.f }; + vec3_add(lookPos, mcamera->transform.position, + vec3_multiply_f(lookPos, + trans_forward(cam_fwd, + &mcamera->transform), + shadowLookahead)); + lookPos[1] = 0.f; + + mfloat_t lightLookPos[3] = { 0.f }; + mfloat_t light_fwd[3] = { 0.f }; + mat4_look_at(lightView, + vec3_subtract(lightLookPos, lookPos, + trans_forward(light_fwd, + &dLight->light.obj. + transform)), lookPos, UP); + + mat4_multiply(lightSpaceMatrix, lightProjection, lightView); + //lightSpaceMatrix = lightProjection * lightView; + + if (renderDynamicShadows) { + shader_use(shadowShader); + shader_setmat4(shadowShader, "lightSpaceMatrix", + lightSpaceMatrix); + staticactor_draw_shadowcasters(shadowShader); + } + } + */ + ////////////////////////// + + // Back to the normal render + window_makecurrent(window); + + + glCullFace(GL_BACK); + + // Render the color thing for debug picking + glBindFramebuffer(GL_FRAMEBUFFER, debugColorPickBO); + glClearColor(editorClearColor[0], editorClearColor[1], + editorClearColor[2], editorClearColor[3]); + glClear(GL_COLOR_BUFFER_BIT); + shader_use(debugColorPickShader); + staticactor_draw_dbg_color_pick(debugColorPickShader); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Clear color and depth + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT); + + if (renderMode == DIRSHADOWMAP) { + // render Depth map to quad for visual debugging + // --------------------------------------------- + shader_use(debugDepthQuad); + shader_setfloat(debugDepthQuad, "near_plane", near_plane); + shader_setfloat(debugDepthQuad, "far_plane", far_plane); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, depthMap); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); + } else if (renderMode == OBJECTPICKER) { + // TODO: This rendering mode + shader_use(debugColorPickShader); + } else { + + glClearColor(editorClearColor[0], editorClearColor[1], + editorClearColor[2], editorClearColor[3]); + glDepthMask(GL_TRUE); + + mfloat_t view[16] = { 0.f }; + getviewmatrix(view, mcamera); + + glBindBuffer(GL_UNIFORM_BUFFER, UBO); + glBufferSubData(GL_UNIFORM_BUFFER, sizeof(view), sizeof(view), + view); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + switch (renderMode) { + case LIT: + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + shader_use(modelShader); + +/* + if (dLight) + dlight_prepshader(dLight, modelShader); + + pointlights_prepshader(modelShader); + spotlights_prepshader(modelShader); +*/ + + shader_setvec3(modelShader, "viewPos", + mcamera->transform.position); + shader_setmat4(modelShader, "lightSpaceMatrix", + lightSpaceMatrix); + shader_setint(modelShader, "shadowMap", 12); + glActiveTexture(GL_TEXTURE); + glBindTexture(GL_TEXTURE_2D, depthMap); + staticactor_draw_models(modelShader); + + + break; + + case UNLIT: + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + shader_use(diffuseShader); + staticactor_draw_models(diffuseShader); + + break; + + case WIREFRAME: + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + shader_use(diffuseShader); + staticactor_draw_models(diffuseShader); + + break; + } + + //// skybox + // draw skybox as last + glDepthFunc(GL_LEQUAL); + // skybox->Draw(mcamera); + glDepthFunc(GL_LESS); + + + + + + if (debugDrawPhysics) { + // Render physics world + //dynamicsWorld->debugDrawWorld(); + } + // Draw outline + if (selectedobject != NULL) { + // Draw the selected object outlined + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glDepthFunc(GL_ALWAYS); + glDepthMask(false); + glColorMask(false, false, false, false); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFF); + shader_use(diffuseShader); + setup_model_transform(&selectedobject->transform, + diffuseShader, 1.f); + //selectedobject->draw(diffuseShader); + + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glDepthMask(true); + glColorMask(true, true, true, true); + glStencilMask(0x00); + shader_use(outlineShader); + setup_model_transform(&selectedobject->transform, + outlineShader, 1.f); + //selectedobject->draw(outlineShader); + + + } + + glDepthFunc(GL_LESS); + glStencilMask(0xFF); + glStencilFunc(GL_ALWAYS, 0, 0xFF); + + } + + ////// TEXT && GUI + // glCullFace(GL_FRONT); + glDepthFunc(GL_ALWAYS); + shader_use(textShader); + shader_setmat4(textShader, "projection", window->projection); + mfloat_t fontpos[2] = { 25.f, 25.f }; + mfloat_t fontcolor[3] = { 0.5f, 0.8f, 0.2f }; + renderText(stdFont, textShader, "Sample text", fontpos, 0.4f, + fontcolor, -1.f); + + sprite_draw(tsprite); + + glDepthFunc(GL_LESS); + + + ////// Render grid + if (showGrid) { + glDisable(GL_CULL_FACE); + shader_use(debugGridShader); + mfloat_t gmodel[16] = { 0.f }; + mfloat_t gridscale[3] = { 0.f }; + vec3(gridscale, gridScale, gridScale, gridScale); + mat4_multiply_f(gmodel, gmodel, gridScale); + // TODO: Hook into here to make the grid scalable + shader_setmat4(debugGridShader, "model", gmodel); + shader_setvec3(debugGridShader, "smallColor", gridSmallColor); + shader_setvec3(debugGridShader, "bigColor", gridBigColor); + shader_setfloat(debugGridShader, "gridScale", gridScale); + shader_setfloat(debugGridShader, "smallUnit", smallGridUnit); + shader_setfloat(debugGridShader, "bigUnit", bigGridUnit); + shader_setfloat(debugGridShader, "smallThickness", + gridSmallThickness); + shader_setfloat(debugGridShader, "largeThickness", + gridBigThickness); + shader_setfloat(debugGridShader, "opacity", gridOpacity); + glBindVertexArray(gridVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); + } + ///// Render gizmos + // These are things that are overlaid on everything else + + + // glBindFramebuffer(GL_FRAMEBUFFER, 0); // back to default + // glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // glClear(GL_COLOR_BUFFER_BIT); + + // postShader.use(); + // glBindVertexArray(quadVAO); + // glBindTexture(GL_TEXTURE_2D, fboTexture); + // glDrawArrays(GL_TRIANGLES, 0, 6); +} + +void BindUniformBlock(GLuint shaderID, const char *bufferName, + GLuint bufferBind) +{ + glUniformBlockBinding(shaderID, + glGetUniformBlockIndex(shaderID, bufferName), + bufferBind); +} diff --git a/source/engine/openglrender.h b/source/engine/openglrender.h new file mode 100644 index 0000000..2a9bb86 --- /dev/null +++ b/source/engine/openglrender.h @@ -0,0 +1,54 @@ +#ifndef OPENGL_RENDER_H +#define OPENGL_RENDER_H + +#include "render.h" + +struct mCamera; +struct mSDLWindow; + +extern struct mShader *spriteShader; +extern struct mShader *animSpriteShader; + +extern struct mSprite *tsprite; + +extern int renderMode; + + +extern float editorClose; +extern float editorFar; +extern float gridScale; +extern float smallGridUnit; +extern float bigGridUnit; +extern float gridSmallThickness; +extern float gridBigThickness; +extern float gridBigColor[]; +extern float gridSmallColor[]; +extern float gridOpacity; +extern float editorFOV; +extern float shadowLookahead; +extern float plane_size; +extern float near_plane; +extern float far_plane; +extern char objectName[]; +extern uint16_t debugColorPickBO; + +extern struct mGameObject *selectedobject; + +enum RenderMode { + LIT, + UNLIT, + WIREFRAME, + DIRSHADOWMAP, + OBJECTPICKER +}; + +void openglInit(); +void openglRender(struct mCamera *camera); + +void openglInit3d(struct mSDLWindow *window); +void openglRender3d(struct mSDLWindow *window, struct mCamera *camera); + +void BindUniformBlock(GLuint shaderID, const char *bufferName, + GLuint bufferBind); + +#endif diff --git a/source/engine/pinball.c b/source/engine/pinball.c new file mode 100644 index 0000000..2a21145 --- /dev/null +++ b/source/engine/pinball.c @@ -0,0 +1,25 @@ +#include "pinball.h" +#include "gameobject.h" +#include "input.h" + +struct flipper *pinball_flipper_make(struct mGameObject *go) +{ + struct flipper *new = calloc(1, sizeof(struct flipper)); + pinball_flipper_init(new, go); + + return new; +} + +void pinball_flipper_init(struct flipper *flip, struct mGameObject *go) +{ + cpBodySetAngle(go->body, flip->angle1); +} + +void pinball_flipper_update(struct flipper *flip, struct mGameObject *go) +{ + if ((flip->left && currentKeystates[SDL_SCANCODE_LSHIFT]) + || currentKeystates[SDL_SCANCODE_RSHIFT]) { + cpBodySetAngle(go->body, flip->angle2); + } else + cpBodySetAngle(go->body, flip->angle1); +} diff --git a/source/engine/pinball.h b/source/engine/pinball.h new file mode 100644 index 0000000..d7ee385 --- /dev/null +++ b/source/engine/pinball.h @@ -0,0 +1,18 @@ +#ifndef PINBALL_H +#define PINBALL_H + +struct mGameObject; + +struct flipper { + float angle1; + float angle2; + float flipspeed; + int left; +}; + +struct flipper *pinball_flipper_make(struct mGameObject *go); +void pinball_flipper_init(struct flipper *flip, struct mGameObject *go); +void pinball_flipper_update(struct flipper *flip, struct mGameObject *go); + + +#endif diff --git a/source/engine/registry.c b/source/engine/registry.c new file mode 100644 index 0000000..75b4e7f --- /dev/null +++ b/source/engine/registry.c @@ -0,0 +1,53 @@ +#include "registry.h" +#include "gameobject.h" +#include "2dphysics.h" +#include "editor.h" +#include "sprite.h" +#include "pinball.h" + +struct component components[MAXNAME] = { 0 }; + +int ncomponent = 0; + +void registry_init() +{ + register_component("Sprite", sizeof(struct mSprite), &MakeSprite, NULL, + sprite_gui, &sprite_init, NULL); + register_component("2D Circle Collider", sizeof(struct phys2d_circle), + &Make2DCircle, &phys2d_dbgdrawcircle, &circle_gui, + &phys2d_circleinit, NULL); + register_component("2D Segment", sizeof(struct phys2d_segment), + &Make2DSegment, &phys2d_dbgdrawseg, &segment_gui, + &phys2d_seginit, NULL); + register_component("2D Box", sizeof(struct phys2d_box), &Make2DBox, + &phys2d_dbgdrawbox, &box_gui, &phys2d_boxinit, + NULL); + register_component("2D Polygon", sizeof(struct phys2d_poly), + &Make2DPoly, &phys2d_dbgdrawpoly, &poly_gui, + &phys2d_polyinit, NULL); + register_component("2D Edge", sizeof(struct phys2d_edge), &Make2DEdge, + &phys2d_dbgdrawedge, &edge_gui, &phys2d_edgeinit, + NULL); + register_component("Flipper", sizeof(struct flipper), + &pinball_flipper_make, NULL, &pinball_flipper_gui, + &pinball_flipper_init, &pinball_flipper_update); +} + +void register_component(const char *name, size_t size, + void (*make)(struct mGameObject * go, + struct component * c), + void(*draw_debug)(void *data), + void(*draw_gui)(void *data), + void(*init)(void *data, struct mGameObject * go), + void(*update)(void *data, struct mGameObject * go)) +{ + struct component *c = &components[ncomponent++]; + c->name = name; + c->make = make; + c->draw_debug = draw_debug; + c->draw_gui = draw_gui; + c->init = init; + c->data = NULL; + c->id = ncomponent - 1; + c->datasize = size; +} diff --git a/source/engine/registry.h b/source/engine/registry.h new file mode 100644 index 0000000..86fdea8 --- /dev/null +++ b/source/engine/registry.h @@ -0,0 +1,35 @@ +#ifndef REGISTRY_H +#define REGISTRY_H + +#include +#include "config.h" + +struct mGameObject; + +struct component { + const char *name; + void *(*make)(struct mGameObject * go); + void *data; + struct mGameObject *go; + void (*draw_debug)(void *data); + void (*draw_gui)(void *data); + void (*update)(void *data, struct mGameObject * go); + int id; + int datasize; + void (*init)(void *data, struct mGameObject * go); +}; + +extern struct component components[MAXNAME]; +extern int ncomponent; + +void registry_init(); +void register_component(const char *name, size_t size, + void (*make)(struct mGameObject * go, + struct component * c), + void(*draw_debug)(void *data), + void(*draw_gui)(void *data), + void(*init)(void *data, struct mGameObject * go), + void(*update)(void *data, + struct mGameObject * go)); + +#endif diff --git a/source/engine/render.c b/source/engine/render.c new file mode 100644 index 0000000..e69de29 diff --git a/source/engine/render.h b/source/engine/render.h new file mode 100644 index 0000000..941b775 --- /dev/null +++ b/source/engine/render.h @@ -0,0 +1,9 @@ +#ifndef RENDER_H +#define RENDER_H + +#define GL_GLEXT_PROTOTYPES +#include +#include + + +#endif \ No newline at end of file diff --git a/source/engine/resources.c b/source/engine/resources.c new file mode 100644 index 0000000..0e4bc7a --- /dev/null +++ b/source/engine/resources.c @@ -0,0 +1,112 @@ +#include "resources.h" + +#include "config.h" +#include +#include +#include +#include +#include "vec.h" +#include +#include +#include + +char *DATA_PATH = NULL; +char *PREF_PATH = NULL; + +struct vec *prefabs = NULL; + +const char *EXT_PREFAB = ".prefab"; +const char *EXT_LEVEL = ".level"; +int stemlen = 0; + +static const char *cur_ext = NULL; +static DIR *cur_dir = NULL; +struct dirent *c_dirent = NULL; +struct vec *c_vec = NULL; + +char pathbuf[MAXPATH]; + + +void resources_init() +{ + char *dpath = SDL_GetBasePath(); + DATA_PATH = malloc(strlen(dpath) + 1); + strcpy(DATA_PATH, dpath); + + char *ppath = SDL_GetPrefPath("Odplot", "Test Game"); + PREF_PATH = malloc(strlen(ppath) + 1); + strcpy(PREF_PATH, ppath); +} + +char *get_filename_from_path(char *path, int extension) +{ + char *dirpos = strrchr(path, '/'); + if (!dirpos) + dirpos = path; + + char *end = strrchr(path, '\0'); + + int offset = 0; + if (!extension) { + char *ext = strrchr(path, '.'); + offset = end - ext; + printf("Making without extension ...\n"); + } + + char *filename = + (char *) malloc(sizeof(char) * (end - dirpos - offset + 1)); + strncpy(filename, dirpos, end - dirpos - offset); + return filename; +} + +char *get_directory_from_path(char *path) +{ + const char *dirpos = strrchr(path, '/'); + char *directory = (char *) malloc(sizeof(char) * (dirpos - path + 1)); + strncpy(directory, path, dirpos - path); + return directory; +} + +FILE *res_open(char *path, const char *tag) +{ + strncpy(pathbuf, DATA_PATH, MAXPATH); + strncat(pathbuf, path, MAXPATH); + FILE *f = fopen(pathbuf, tag); + return f; +} + +static int ext_check(const char *path, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) +{ + if (typeflag == FTW_F) { + const char *ext = strrchr(path, '.'); + if (ext != NULL && !strcmp(ext, cur_ext)) + vec_add(c_vec, path); + } + + return 0; +} + +void fill_extensions(struct vec *vec, char *path, const char *ext) +{ + c_vec = vec; + cur_ext = ext; + vec_clear(c_vec); + nftw(path, &ext_check, 10, 0); +} + +void findPrefabs() +{ + fill_extensions(prefabs, DATA_PATH, EXT_PREFAB); +} + +FILE *path_open(const char *fmt, const char *tag, ...) +{ + va_list args; + va_start(args, fmt); + vsprintf(pathbuf, fmt, args); + va_end(args); + + FILE *f = fopen(pathbuf, tag); + return f; +} \ No newline at end of file diff --git a/source/engine/resources.h b/source/engine/resources.h new file mode 100644 index 0000000..cf352ec --- /dev/null +++ b/source/engine/resources.h @@ -0,0 +1,27 @@ +#ifndef RESOURCES_H +#define RESOURCES_H + + + +#include + +struct vec; + +extern char *DATA_PATH; +extern char *PREF_PATH; + +extern const char *EXT_PREFAB; +extern const char *EXT_LEVEL; +extern int stemlen; + +void resources_init(); + +extern struct vec *prefabs; +void findPrefabs(); +void fill_extensions(struct vec *vec, char *path, const char *ext); +char *get_filename_from_path(char *path, int extension); +char *get_directory_from_path(char *path); +FILE *res_open(char *path, const char *tag); +FILE *path_open(const char *fmt, const char *tag, ...); + +#endif diff --git a/source/engine/script.c b/source/engine/script.c new file mode 100644 index 0000000..d8d740c --- /dev/null +++ b/source/engine/script.c @@ -0,0 +1,54 @@ +#include "script.h" + +#include "gameobject.h" +#include + +s7_scheme *s7 = NULL; + +s7_pointer s7square(s7_scheme * sc, s7_pointer args) +{ + if (s7_is_integer(s7_car(args))) + return (s7_make_integer + (sc, s7_integer(s7_car(args)) * s7_integer(s7_car(args)))); + + return (s7_wrong_type_arg_error + (sc, "square", 1, s7_car(args), "an integer")); +} + +s7_pointer s7move(s7_scheme * sc, s7_pointer args) +{ + if (s7_is_number(s7_car(args)) && s7_is_number(s7_cadr(args))) { + gameobject_move(updateGO, s7_real(s7_car(args)), + s7_real(s7_cadr(args))); + return args; + } + + return args; +} + +s7_pointer s7rotate(s7_scheme * sc, s7_pointer args) +{ + if (s7_is_number(s7_car(args))) { + gameobject_rotate(updateGO, s7_real(s7_car(args))); + return (s7_make_real(sc, cpBodyGetAngle(updateGO->body))); + } + + return (s7_wrong_type_arg_error + (sc, "rotate", 1, s7_car(args), "a number")); +} + +void script_init() +{ + s7 = s7_init(); + s7_define_function(s7, "square", s7square, 1, 0, 0, + "(square int) squares int"); + s7_define_function(s7, "move", s7move, 1, 0, 0, + "(move (xs ys)) moves at xs and ys pixels per second"); + s7_define_function(s7, "rotate", s7rotate, 1, 0, 0, + "(rotate ms) rotates at ms meters per second"); +} + +void script_run(const char *script) +{ + s7_eval_c_string(s7, script); +} \ No newline at end of file diff --git a/source/engine/script.h b/source/engine/script.h new file mode 100644 index 0000000..38f39fb --- /dev/null +++ b/source/engine/script.h @@ -0,0 +1,10 @@ +#ifndef SCRIPT_H +#define SCRIPT_H + +struct s7_scheme; +extern struct s7_scheme *s7; + +void script_init(); +void script_run(const char *script); + +#endif \ No newline at end of file diff --git a/source/engine/shader.c b/source/engine/shader.c new file mode 100644 index 0000000..39526ef --- /dev/null +++ b/source/engine/shader.c @@ -0,0 +1,176 @@ +#include "shader.h" + +#include "config.h" +#include +#include +#include +#include "log.h" +#include "resources.h" +#include + +#define SHADER_BUF 10000 + +struct mShader *mshaders[255]; +struct mShader **lastShader = mshaders; + +struct mShader *MakeShader(const char *vertpath, const char *fragpath) +{ + struct mShader init = { 0, vertpath, fragpath }; + struct mShader *newshader = + (struct mShader *) malloc(sizeof(struct mShader)); + memcpy(newshader, &init, sizeof(*newshader)); + *lastShader++ = newshader; + shader_compile(newshader); + return newshader; +} + +int shader_compile_error(GLuint shader) +{ + GLint success = 0; + GLchar infoLog[ERROR_BUFFER] = { '\0' }; + + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (success) return 0; + + glGetShaderInfoLog(shader, ERROR_BUFFER, NULL, infoLog); + YughLog(0, SDL_LOG_PRIORITY_ERROR, "Shader compilation error.\nLog: %s", infoLog); + + return 1; +} + +int shader_link_error(GLuint shader) +{ + GLint success = 0; + GLchar infoLog[ERROR_BUFFER] = { '\0' }; + + glGetProgramiv(shader, GL_LINK_STATUS, &success); + if (success) return 0; + + glGetProgramInfoLog(shader, ERROR_BUFFER, NULL, infoLog); + YughLog(0, SDL_LOG_PRIORITY_ERROR, "Shader link error.\nLog: %s", infoLog); + + return 1; +} + +GLuint load_shader_from_file(char *path, int type) +{ + char spath[MAXPATH] = {'\0'}; + + sprintf(spath, "%s%s%s", DATA_PATH, "shaders/", path); + FILE *f = fopen(spath, "r'"); + if (!path) + perror(spath), exit(1); + + char buf[SHADER_BUF] = {'\0'}; + long int fsize; + fseek(f, 0, SEEK_END); + fsize = ftell(f); + rewind(f); + fread(buf, fsize, 1, f); + + fclose(f); + + + GLuint id = glCreateShader(type); + const char *code = buf; + glShaderSource(id, 1, &code, NULL); + glCompileShader(id); + if ( shader_compile_error(id)) + return 0; + + return id; +} + +void shader_compile(struct mShader *shader) +{ + GLuint vert = load_shader_from_file(shader->vertpath, GL_VERTEX_SHADER); + GLuint frag = load_shader_from_file(shader->fragpath, GL_FRAGMENT_SHADER); + + shader->id = glCreateProgram(); + glAttachShader(shader->id, vert); + glAttachShader(shader->id, frag); + glLinkProgram(shader->id); + shader_link_error(shader->id); + + glDeleteShader(vert); + glDeleteShader(frag); +} + +void shader_use(struct mShader *shader) +{ + glUseProgram(shader->id); +} + +void shader_setbool(struct mShader *shader, const char *name, int val) +{ + glUniform1i(glGetUniformLocation(shader->id, name), val); +} + +void shader_setint(struct mShader *shader, const char *name, int val) +{ + glUniform1i(glGetUniformLocation(shader->id, name), val); +} + +void shader_setfloat(struct mShader *shader, const char *name, float val) +{ + glUniform1f(glGetUniformLocation(shader->id, name), val); +} + +void shader_setvec2(struct mShader *shader, const char *name, + mfloat_t val[2]) +{ + glUniform2fv(glGetUniformLocation(shader->id, name), 1, val); +} + +void shader_setvec3(struct mShader *shader, const char *name, + mfloat_t val[3]) +{ + glUniform3fv(glGetUniformLocation(shader->id, name), 1, val); +} + +void shader_setvec4(struct mShader *shader, const char *name, + mfloat_t val[4]) +{ + glUniform4fv(glGetUniformLocation(shader->id, name), 1, val); +} + +void shader_setmat2(struct mShader *shader, const char *name, + mfloat_t val[4]) +{ + glUniformMatrix2fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, + val); +} + +void shader_setmat3(struct mShader *shader, const char *name, + mfloat_t val[9]) +{ + glUniformMatrix3fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, + val); +} + +void shader_setmat4(struct mShader *shader, const char *name, + mfloat_t val[16]) +{ + shader_use(shader); + glUniformMatrix4fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, + val); +} + +void shader_setUBO(struct mShader *shader, const char *name, + unsigned int index) +{ + glUniformBlockBinding(shader->id, + glGetUniformBlockIndex(shader->id, name), index); +} + + + +void shader_compile_all() +{ + struct mShader **curshader = mshaders; + do { + YughLog(0, SDL_LOG_PRIORITY_INFO, "Compiled Shader %d", 1); + shader_compile(*curshader); + } while (++curshader != lastShader); + +} diff --git a/source/engine/shader.h b/source/engine/shader.h new file mode 100644 index 0000000..10567c2 --- /dev/null +++ b/source/engine/shader.h @@ -0,0 +1,37 @@ +#ifndef SHADER_H +#define SHADER_H + +#include "mathc.h" + +struct mShader { + unsigned int id; + const char *vertpath; + const char *fragpath; +}; + +void shader_compile_all(); +struct mShader *MakeShader(const char *vertpath, const char *fragpath); +void shader_compile(struct mShader *shader); +void shader_use(struct mShader *shader); + +void shader_setbool(struct mShader *shader, const char *name, int val); +void shader_setint(struct mShader *shader, const char *name, int val); +void shader_setfloat(struct mShader *shader, const char *name, float val); + +void shader_setvec2(struct mShader *shader, const char *name, + mfloat_t val[2]); +void shader_setvec3(struct mShader *shader, const char *name, + mfloat_t val[3]); +void shader_setvec4(struct mShader *shader, const char *name, + mfloat_t val[4]); +void shader_setmat2(struct mShader *shader, const char *name, + mfloat_t val[4]); +void shader_setmat3(struct mShader *shader, const char *name, + mfloat_t val[9]); +void shader_setmat4(struct mShader *shader, const char *name, + mfloat_t val[16]); + +void shader_setUBO(struct mShader *shader, const char *name, + unsigned int index); + +#endif diff --git a/source/engine/skybox.c b/source/engine/skybox.c new file mode 100644 index 0000000..6e1ba4e --- /dev/null +++ b/source/engine/skybox.c @@ -0,0 +1,123 @@ +#include "skybox.h" + +#include "shader.h" +#include "camera.h" +#include +#include + +#include "openglrender.h" + +static const float skyboxVertices[216] = { + -1.0f, 1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f +}; + +struct mSkybox *MakeSkybox(const char *cubemap) +{ + struct mSkybox *newskybox = + (struct mSkybox *) malloc(sizeof(struct mSkybox)); + + newskybox->shader = MakeShader("skyvert.glsl", "skyfrag.glsl"); + shader_compile(newskybox->shader); + + glGenVertexArrays(1, &newskybox->VAO); + glGenBuffers(1, &newskybox->VBO); + glBindVertexArray(newskybox->VAO); + glBindBuffer(GL_ARRAY_BUFFER, newskybox->VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, + GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), + (void *) 0); + + shader_use(newskybox->shader); + shader_setint(newskybox->shader, "skybox", 0); + + const char *faces[6] = + { "right.jpg", "left.jpg", "top.jpg", "bottom.jpg", "front.jpg", + "back.jpg" + }; + + glGenTextures(1, &newskybox->id); + glBindTexture(GL_TEXTURE_CUBE_MAP, newskybox->id); + char buf[100] = { '\0' }; + + for (unsigned int i = 0; i < 6; i++) { + buf[0] = '\0'; + strcat(buf, cubemap); + strcat(buf, "/"); + strcat(buf, faces[i]); + SDL_Surface *data = NULL; //IMG_Load(buf); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 2048, + 2048, 0, GL_RGB, GL_UNSIGNED_BYTE, data->pixels); + SDL_FreeSurface(data); + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, + GL_CLAMP_TO_EDGE); + + + return newskybox; +} + +void skybox_draw(const struct mSkybox *skybox, + const struct mCamera *camera) +{ + shader_use(skybox->shader); + + mfloat_t view[16] = { 0.f }; + getviewmatrix(view, camera); + shader_setmat4(skybox->shader, "skyview", view); + + // skybox cube + glBindVertexArray(skybox->VAO); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->id); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); +} diff --git a/source/engine/skybox.h b/source/engine/skybox.h new file mode 100644 index 0000000..1d28350 --- /dev/null +++ b/source/engine/skybox.h @@ -0,0 +1,17 @@ +#ifndef SKYBOX_H +#define SKYBOX_H + +struct mCamera; + +struct mSkybox { + unsigned int VAO; + unsigned int VBO; + unsigned int id; + struct mShader *shader; +}; + +struct mSkybox *MakeSkybox(const char *cubemap); +void skybox_draw(const struct mSkybox *skybox, + const struct mCamera *camera); + +#endif diff --git a/source/engine/sprite.c b/source/engine/sprite.c new file mode 100644 index 0000000..c73ada4 --- /dev/null +++ b/source/engine/sprite.c @@ -0,0 +1,206 @@ +#include "sprite.h" + + +#include "render.h" +#include "openglrender.h" +#include "texture.h" +#include "shader.h" +#include "datastream.h" +#include "gameobject.h" +#include + + +/* +static struct mShader *spriteShader = NULL; + +static struct mShader *animSpriteShader = NULL; +*/ + +struct TextureOptions TEX_SPRITE = { 1, 0 }; + +struct mSprite *sprites[100] = { NULL }; + +int numSprites = 0; + +static uint32_t quadVAO; +static uint32_t VBO; + +struct mSprite *MakeSprite(struct mGameObject *go) +{ + struct mSprite *sprite = malloc(sizeof(struct mSprite)); + sprites[numSprites++] = sprite; + sprite->color[0] = 1.f; + sprite->color[1] = 1.f; + sprite->color[2] = 1.f; + sprite->pos[0] = 0.f; + sprite->pos[1] = 0.f; + sprite->size[0] = 1.f; + sprite->size[1] = 1.f; + sprite->tex = NULL; + sprite_init(sprite, go); + return sprite; +} + +void sprite_init(struct mSprite *sprite, struct mGameObject *go) +{ + sprite->go = go; +} + +void sprite_loadtex(struct mSprite *sprite, const char *path) +{ + sprite->tex = texture_loadfromfile(sprite->tex, path); +} + +void sprite_loadanim(struct mSprite *sprite, const char *path, + struct Anim2D anim) +{ + sprite->tex = texture_loadfromfile(sprite->tex, path); + sprite->anim = anim; + sprite->anim.timer = + SDL_AddTimer(sprite->anim.ms, incrementAnimFrame, sprite); +/* + sprite->tex = texture_loadanimfromfile(sprite->tex, path, sprite->anim.frames, + sprite->anim.dimensions); +*/ +} + + +Uint32 incrementAnimFrame(Uint32 interval, struct mSprite *sprite) +{ + sprite->anim.frame = (sprite->anim.frame + 1) % sprite->anim.frames; + return interval; +} + + +// TODO: This should be done once for all sprites +void sprite_initialize() +{ + uint32_t VBO; + float vertices[] = { + // pos + 0.f, 0.f, + 1.0f, 0.0f, + 0.f, 1.f, + 1.f, 1.f + }; + + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &VBO); + + glBindVertexArray(quadVAO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, + GL_STATIC_DRAW); + + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); + + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +void sprite_draw(struct mSprite *sprite) +{ + if (sprite->tex != NULL) { + + shader_use(spriteShader); + + + mfloat_t model[16] = { 0.f }; + mfloat_t r_model[16] = { 0.f }; + mfloat_t s_model[16] = { 0.f }; + memcpy(model, UNITMAT4, sizeof(UNITMAT4)); + memcpy(r_model, UNITMAT4, sizeof(UNITMAT4)); + memcpy(s_model, UNITMAT4, sizeof(UNITMAT4)); + + + + mfloat_t t_move[2] = { 0.f }; + mfloat_t t_scale[2] = { 0.f }; + + t_scale[0] = + sprite->size[0] * sprite->tex->width * sprite->go->scale; + t_scale[1] = + sprite->size[1] * sprite->tex->height * sprite->go->scale; + + t_move[0] = sprite->pos[0] * t_scale[0]; + t_move[1] = sprite->pos[1] * t_scale[1]; + + mat4_translate_vec2(model, t_move); + mat4_scale_vec2(model, t_scale); + mat4_rotation_z(r_model, cpBodyGetAngle(sprite->go->body)); + + mat4_multiply(model, r_model, model); + + cpVect pos = cpBodyGetPosition(sprite->go->body); + t_move[0] = pos.x; + t_move[1] = pos.y; + mat4_translate_vec2(model, t_move); + + + shader_setmat4(spriteShader, "model", model); + shader_setvec3(spriteShader, "spriteColor", sprite->color); + + //tex_bind(sprite->tex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, sprite->tex->id); + + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } +} + +void spriteanim_draw(struct mSprite *sprite) +{ + shader_use(animSpriteShader); + + mfloat_t model[16] = { 0.f }; + memcpy(model, UNITMAT4, sizeof(UNITMAT4)); + + mat4_translate_vec2(model, sprite->pos); + mfloat_t msize[2] = + { sprite->size[0] * sprite->anim.dimensions[0], +sprite->size[1] * sprite->anim.dimensions[1] }; + mat4_scale_vec2(model, msize); + + shader_setmat4(animSpriteShader, "model", model); + shader_setvec3(animSpriteShader, "spriteColor", sprite->color); + shader_setfloat(animSpriteShader, "frame", sprite->anim.frame); + + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D_ARRAY, sprite->tex->id); + + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + + +void video_draw(struct datastream *stream, mfloat_t position[2], + mfloat_t size[2], float rotate, mfloat_t color[3]) +{ + shader_use(spriteShader); + + static mfloat_t model[16]; + memcpy(model, UNITMAT4, sizeof(UNITMAT4)); + mat4_translate_vec2(model, position); + mat4_scale_vec2(model, size); + + shader_setmat4(spriteShader, "model", model); + shader_setvec3(spriteShader, "spriteColor", color); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, stream->texture_y); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, stream->texture_cb); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, stream->texture_cr); + + // TODO: video bind VAO + //glBindVertexArray(stream->quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); +} diff --git a/source/engine/sprite.h b/source/engine/sprite.h new file mode 100644 index 0000000..a450614 --- /dev/null +++ b/source/engine/sprite.h @@ -0,0 +1,47 @@ +#ifndef SPRITE_H +#define SPRITE_H + +#include +#include "mathc.h" + +struct datastream; +struct mGameObject; + +struct Anim2D { + int frames; + int frame; + int dimensions[2]; + SDL_TimerID timer; + int ms; +}; + +struct mSprite { + struct Texture *tex; + mfloat_t pos[2]; + mfloat_t size[2]; + float rotation; + mfloat_t color[3]; + + struct Anim2D anim; + struct mGameObject *go; +}; + +extern struct mSprite *sprites[100]; +extern int numSprites; + +struct mSprite *MakeSprite(struct mGameObject *go); +void sprite_init(struct mSprite *sprite, struct mGameObject *go); +void sprite_loadtex(struct mSprite *sprite, const char *path); +void sprite_loadanim(struct mSprite *sprite, const char *path, + struct Anim2D anim); +void sprite_initalize(); +void sprite_draw(struct mSprite *sprite); +void spriteanim_draw(struct mSprite *sprite); +void video_draw(struct datastream *ds, mfloat_t pos[2], mfloat_t size[2], + float rotate, mfloat_t color[3]); +Uint32 incrementAnimFrame(Uint32 interval, struct mSprite *sprite); + +void sprite_draw_all(); + + +#endif diff --git a/source/engine/static_actor.c b/source/engine/static_actor.c new file mode 100644 index 0000000..adf68ff --- /dev/null +++ b/source/engine/static_actor.c @@ -0,0 +1,77 @@ +#include "static_actor.h" +#include "editorstate.h" + +//ADDMAKE(StaticActor); + +static struct mStaticActor *models[100]; +static int numModels = 0; +static struct mStaticActor *shadow_casters[100]; +static int numShadowCasters = 0; + +struct mStaticActor *curActor = NULL; + +void staticactor_draw_dbg_color_pick(struct mShader *s) +{ + for (int i = 0; i < numModels; i++) { + shader_setvec3(s, "PickingColor", models[i]->obj.editor.color); + setup_model_transform(&models[i]->obj.transform, s, 1.f); + //models[i]->obj.draw(s); + } + +} + +void staticactor_draw_models(struct mShader *s) +{ + for (int i = 0; i < numModels; i++) { + setup_model_transform(&models[i]->obj.transform, s, 1.f); + draw_model(models[i]->model, s); + } +} + +void staticactor_draw_shadowcasters(struct mShader *s) +{ + for (int i = 0; i < numShadowCasters; i++) { + setup_model_transform(&shadow_casters[i]->obj.transform, s, 1.f); + //models[i]->obj.draw(s); + } +} + +/* +void StaticActor::serialize(FILE * file) +{ + GameObject::serialize(file); + SerializeBool(file, &castShadows); + Serializecstr(file, currentModelPath); +} + +void StaticActor::deserialize(FILE * file) +{ + GameObject::deserialize(file); + DeserializeBool(file, &castShadows); + + Deserializecstr(file, currentModelPath, MAXPATH); + curActor = this; + set_new_model(currentModelPath); +} +*/ + + + +struct mStaticActor *MakeStaticActor(const char *modelPath) +{ + struct mStaticActor *newsa = + (struct mStaticActor *) malloc(sizeof(struct mStaticActor)); + newsa->model = GetExistingModel(modelPath); + models[numModels++] = newsa; + + return newsa; +} + +/* +Serialize *make_staticactor() +{ + StaticActor *nactor = (StaticActor *) malloc(sizeof(StaticActor)); + + return nactor; +} +*/ diff --git a/source/engine/static_actor.h b/source/engine/static_actor.h new file mode 100644 index 0000000..c5b6c75 --- /dev/null +++ b/source/engine/static_actor.h @@ -0,0 +1,24 @@ +#ifndef STATIC_ACTOR_H +#define STATIC_ACTOR_H + +#include "gameobject.h" +#include "model.h" +#include "shader.h" + +struct mStaticActor { + struct mGameObject obj; + struct mModel *model; + char *modelPath; + char currentModelPath[MAXPATH]; + bool castShadows; +}; + +void staticactor_draw_dbg_color_pick(struct mShader *s); +void staticactor_draw_models(struct mShader *s); +void staticactor_draw_shadowcasters(struct mShader *s); +struct mStaticActor *MakeStaticActor(); + + +extern struct mStaticActor *curActor; + +#endif diff --git a/source/engine/texture.c b/source/engine/texture.c new file mode 100644 index 0000000..4b0a070 --- /dev/null +++ b/source/engine/texture.c @@ -0,0 +1,265 @@ +#include "texture.h" + +#define STBI_FAILURE_USERMSG + +#include +#include +#include +#include +#include +#include "log.h" + +static struct { + char *key; + struct Texture *value; +} *texhash = NULL; + + +struct Texture *texture_loadfromfile(struct Texture *tex, const char *path) +{ + int index = shgeti(texhash, path); + if (index != -1) + return texhash[index].value; + + tex = calloc(1, sizeof(*tex)); + tex->path = malloc(strlen(path) + 1); + strncpy(tex->path, path, strlen(path) + 1); + tex->flipy = 0; + tex->opts.sprite = 1; + tex->opts.gamma = 0; + tex->anim.frames = 1; + tex->anim.ms = 1; + + glGenTextures(1, &tex->id); + uint8_t n; + stbi_set_flip_vertically_on_load(0); + tex->data = stbi_load(tex->path, &tex->width, &tex->height, &n, 4); + + if (stbi_failure_reason()) + YughLog(0, 3, "STBI failed to load file %s with message: %s", + tex->path, stbi_failure_reason()); + + shput(texhash, tex->path, tex); + + tex_gpu_load(tex); + + + return tex; +} + +void tex_reload(struct Texture *tex) +{ + tex_free(tex); + + tex_gpu_load(tex); +} + +void tex_gpu_load(struct Texture *tex) +{ + if (tex->anim.frames >= 0) { + glBindTexture(GL_TEXTURE_2D, tex->id); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->width, tex->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, tex->data); + + glGenerateMipmap(GL_TEXTURE_2D); + + if (tex->opts.sprite) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } else { + glBindTexture(GL_TEXTURE_2D_ARRAY, tex->id); + glTexImage3D(GL_TEXTURE_2D_ARRAY, + 0, + GL_RGBA, + tex->anim.dimensions[0], + tex->anim.dimensions[1], + tex->anim.frames, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + SDL_Surface *loadedSurface = + SDL_CreateRGBSurfaceFrom(tex->data, tex->width, tex->height, + 32, (4 * tex->width), + 0x000000ff, 0x0000ff00, 0x00ff0000, + 0xff000000); + + SDL_Surface *tempSurface; + tempSurface = + SDL_CreateRGBSurfaceWithFormat(0, tex->anim.dimensions[0], + tex->anim.dimensions[1], 32, + SDL_PIXELFORMAT_RGBA32); + + SDL_Rect srcRect; + srcRect.x = 0; + srcRect.y = 0; + srcRect.w = tex->anim.dimensions[0]; + srcRect.h = tex->anim.dimensions[1]; + + for (int i = 0; i < tex->anim.frames; i++) { + srcRect.x = i * srcRect.w; + SDL_FillRect(tempSurface, NULL, 0x000000); + + TestSDLError(SDL_BlitSurface + (loadedSurface, &srcRect, tempSurface, NULL)); + + //SDL_UnlockSurface(tempSurface); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, + tex->anim.dimensions[0], + tex->anim.dimensions[1], 1, GL_RGBA, + GL_UNSIGNED_BYTE, tempSurface->pixels); + } + + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + + SDL_FreeSurface(loadedSurface); + SDL_FreeSurface(tempSurface); + } +} + +Uint32 tex_incr_anim(Uint32 interval, struct TexAnimation *tex_anim) +{ + anim_incr(tex_anim); + + if (!tex_anim->tex->anim.loop + && tex_anim->frame == tex_anim->tex->anim.frames) + anim_pause(tex_anim); + + + return interval; +} + +void anim_incr(struct TexAnimation *anim) +{ + anim->frame = (anim->frame + 1) % anim->tex->anim.frames; + tex_anim_calc_uv(anim); +} + +void anim_decr(struct TexAnimation *anim) +{ + anim->frame = + (anim->frame + anim->tex->anim.frames - + 1) % anim->tex->anim.frames; + tex_anim_calc_uv(anim); +} + +void tex_anim_set(struct TexAnimation *anim) +{ + if (anim->playing) { + SDL_RemoveTimer(anim->timer); + anim->timer = + SDL_AddTimer(floor(1000.f / anim->tex->anim.ms), tex_incr_anim, + anim); + + } + + tex_anim_calc_uv(anim); +} + +void tex_free(struct Texture *tex) +{ + if (tex->id != 0) { + glDeleteTextures(1, &tex->id); + tex->id = 0; + } +} + +void tex_anim_calc_uv(struct TexAnimation *anim) +{ + struct Rect uv; + uv.w = 1.f / anim->tex->anim.frames; + uv.h = 1.f; + uv.y = 0.f; + uv.x = uv.w * (anim->frame); + + anim->uv = uv; +} + +unsigned int powof2(unsigned int num) +{ + if (num != 0) { + num--; + num |= (num >> 1); + num |= (num >> 2); + num |= (num >> 4); + num |= (num >> 8); + num |= (num >> 16); + num++; + } + + return num; +} + +int ispow2(int num) +{ + return (num && !(num & (num - 1))); +} + +void tex_bind(struct Texture *tex) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex->id); + glBindTexture(GL_TEXTURE_2D_ARRAY, tex->id); +} + +void anim_play(struct TexAnimation *anim) +{ + if (anim->playing) + return; + + if (anim->frame == anim->tex->anim.frames) + anim->frame = 0; + + anim->playing = 1; + SDL_RemoveTimer(anim->timer); + anim->timer = + SDL_AddTimer(floor(1000.f / anim->tex->anim.ms), tex_incr_anim, + anim); +} + +void anim_stop(struct TexAnimation *anim) +{ + if (!anim->playing) + return; + + anim->playing = 0; + anim->frame = 0; + anim->pausetime = 0; + SDL_RemoveTimer(anim->timer); + tex_anim_calc_uv(anim); +} + +void anim_pause(struct TexAnimation *anim) +{ + if (!anim->playing) + return; + + anim->playing = 0; + SDL_RemoveTimer(anim->timer); +} + +void anim_fwd(struct TexAnimation *anim) +{ + anim_incr(anim); +} + +void anim_bkwd(struct TexAnimation *anim) +{ + anim_decr(anim); +} diff --git a/source/engine/texture.h b/source/engine/texture.h new file mode 100644 index 0000000..3fe71ff --- /dev/null +++ b/source/engine/texture.h @@ -0,0 +1,73 @@ +#ifndef TEXTURE_H +#define TEXTURE_H + +#include + +struct Rect { + float x; + float y; + float w; + float h; +}; + +struct TexAnimation { + int frame; + int playing; + int pausetime; + SDL_TimerID timer; + struct Rect uv; + struct Texture *tex; +}; + +struct TexAnim { + int frames; + int dimensions[2]; + int ms; + int loop; +}; + +struct TextureOptions { + int sprite; + unsigned int gamma:1; + int animation; +}; + +struct Texture { + char *type; + unsigned int id; + char *path; + unsigned int width; + unsigned int height; + short flipy; + unsigned char *data; + + struct TextureOptions opts; + struct TexAnim anim; +}; + + + + +struct Texture *texture_loadfromfile(struct Texture *tex, + const char *path); +void tex_gpu_load(struct Texture *tex); +void tex_reload(struct Texture *tex); +void tex_free(struct Texture *tex); +void tex_bind(struct Texture *tex); +unsigned int powof2(unsigned int num); +int ispow2(int num); + +void anim_play(struct TexAnimation *anim); +void anim_stop(struct TexAnimation *anim); +void anim_pause(struct TexAnimation *anim); +void anim_fwd(struct TexAnimation *anim); +void anim_bkwd(struct TexAnimation *anim); +void anim_incr(struct TexAnimation *anim); +void anim_decr(struct TexAnimation *anim); + +Uint32 tex_incr_anim(Uint32 interval, struct TexAnimation *tex_anim); +void tex_anim_calc_uv(struct TexAnimation *anim); +void tex_anim_set(struct TexAnimation *anim); + + +#endif diff --git a/source/engine/thirdpersonfollow.c b/source/engine/thirdpersonfollow.c new file mode 100644 index 0000000..37f05e6 --- /dev/null +++ b/source/engine/thirdpersonfollow.c @@ -0,0 +1,226 @@ +// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit. + +#include "thirdpersonfollow.h" +#include + +// void ThirdPersonFollow::_ready() { +// Target = dynamic_cast(get_node(TargetPath)); +// ExternalFrame = dynamic_cast(get_node(ExternalFramePath)); +// } + +// void ThirdPersonFollow::_process(float delta_time) { + +// if (Target != nullptr) { +// // Get the frame of reference +// if (has_node(ExternalFramePath) && get_node(ExternalFramePath) != this) +// TFOR = dynamic_cast(get_node(ExternalFramePath))->get_global_transform(); +// else +// TFOR = Transform(Basis(glm::vec3::RIGHT(), glm::vec3::UP(), glm::vec3::FORWARD()), glm::vec3::ZERO()); + +// CalculateTargetOffset(); +// TargetPosition = CalculatePosition(); + +// translate(to_local(FrameBasedVectorLerp(get_global_translation(), TargetPosition, PositionSpeeds, delta_time))); + +// set_rotation_degrees(get_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time)); +// } + +// // For rotation +// // TODO: Add rotation offset in properly +// //this->SetActorRotation(FMath::Lerp(this->GetActorRotation(), TargetRotation, RotationSpeed * DeltaTime)); +// //this->set_rotation(glm::quat(this->get_rotation().slerp(RotationOffset, RotationSpeed * DeltaTime)).get_euler()); + +// //set_global_rotation_degrees(get_global_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time)); + +// // TODO: Figure out how to translate rotation to a global rotation +// } + +mfloat_t *follow_calcpos() +{ + mfloat_t p1[3] = { 0 }; + mfloat_t p2[3] = { 0 }; +} + +/* + +glm::vec3 ThirdPersonFollow::CalculatePosition() +{ + glm::vec3 p1 = CalculateCenter(); + + glm::vec3 p2 = + XDirPosts ? GetPostsOffset(TFOR.Right(), + FloatWidths. + x) : GetExtentsOffset(TFOR.Right(), + FloatWidths.x, + TargetOffset.x, + AnchorWidths.x); + glm::vec3 p3 = + YDirPosts ? GetPostsOffset(TFOR.Up(), + FloatWidths. + y) : GetExtentsOffset(TFOR.Up(), + FloatWidths.y, + TargetOffset.y, + AnchorWidths.y); + glm::vec3 p4 = + ZDirPosts ? GetPostsOffset(TFOR.Back(), + FloatWidths. + z) : GetExtentsOffset(TFOR.Back(), + FloatWidths.z, + TargetOffset.z, + AnchorWidths.z); + + return p1 + p2 + p3 + p4; +} + +glm::vec3 ThirdPersonFollow::CalculateCenter() +{ + return Target->get_global_translation() + + TFOR.TransformDirection(Offset) + (mytransform->Back() * Distance); +} + +glm::vec3 ThirdPersonFollow:: +GetPostsOffset(const glm::vec3 & DirectionVector, float AnchorWidth) +{ + float dot = glm::dot(Target->Forward(), DirectionVector); + + return DirectionVector * (dot >= 0 ? AnchorWidth : AnchorWidth * -1); +} + +glm::vec3 ThirdPersonFollow:: +GetExtentsOffset(const glm::vec3 & DirectionVector, float AnchorWidth, + float TOffset, float Width) +{ + + float negated_offset_sign = ((0 <= TOffset) - (TOffset < 0)) * -1.f; + float TotalWidth = AnchorWidth + Width; + + if (glm::abs(TOffset) > TotalWidth + && !glm::epsilonEqual(glm::abs(TOffset), TotalWidth, 0.5f)) + return DirectionVector * TotalWidth * negated_offset_sign; + else { + if (glm::abs(TOffset) >= AnchorWidth) + return DirectionVector * AnchorWidth * negated_offset_sign; + else + return DirectionVector * TOffset * -1.f; + } + + return glm::vec3(0.f); +} + +glm::vec3 ThirdPersonFollow::FrameBasedVectorLerp(const glm::vec3 & From, + const glm::vec3 & To, + const glm::vec3 & Speeds, + float Tick) +{ + // Previously "FORTransform.TransformVector(Speeds) + glm::vec3 TSpeed = glm::abs(TFOR.TransformDirection(Speeds)); + glm::vec3 TOffset = glm::abs(TFOR.TransformDirection(TargetOffset)); + glm::vec3 TAnchorWidths = + glm::abs(TFOR.TransformDirection(AnchorWidths)); + glm::vec3 TFloatWidths = + glm::abs(TFOR.TransformDirection(FloatWidths)); + + + + // If these are true, that means to use the anchor speed instead of the normal speed. + // True if the offset is beyond the anchor plus the width + bool bUseX = GetLerpParam(TOffset.x, TAnchorWidths.x, TFloatWidths.x); + bool bUseY = GetLerpParam(TOffset.y, TAnchorWidths.y, TFloatWidths.y); + bool bUseZ = GetLerpParam(TOffset.z, TAnchorWidths.z, TFloatWidths.z); + + + float xAlpha = + glm::clamp((bUseX ? AnchorSpeed : TSpeed.x) * Tick, 0.f, 1.f); + float yAlpha = + glm::clamp((bUseY ? AnchorSpeed : TSpeed.y) * Tick, 0.f, 1.f); + float zAlpha = + glm::clamp((bUseZ ? AnchorSpeed : TSpeed.z) * Tick, 0.f, 1.f); + + return VectorLerpPiecewise(From, To, + glm::vec3(xAlpha, yAlpha, zAlpha)); +} + +int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e) +{ + return fabs(a - b) < e; +} + +int lerpparam(float offset, float anchorwidth, float floatwidth) +{ + return (offset > (anchorwidth + floatwidth)) && !float_epsilon(anchorwidth + floatwidth, offset, 0.5f); +} + +mfloat_t *vec3lerp(mfloat_t from[3], mfloat_t to[3], mfloat_t a[3]) +{ + from[0] = from[0] + (to[0] - from[0]) * a[0]; + from[1] = from[1] + (to[1] - from[1]) * a[1]; + from[2] = from[2] + (to[2] - from[2]) * a[2]; +} + +void follow_calctargets() +{ + +} + +void ThirdPersonFollow::CalculateTargets() +{ + // For translation + TargetPosition = CalculatePosition(); + + + // For rotation + // TODO: Check of this implementation is the same as UKismetMath FindLookAtRotation + TargetRotation = + RemoveLockedRotation(glm::quat + (mytransform-> + get_global_transform()->get_origin() - + Target-> + get_global_transform()->get_origin())); +} + +follow_removelockedrot() +{ + +} + +glm::quat ThirdPersonFollow:: +RemoveLockedRotation(const glm::quat & CurrentRotation) +{ + glm::vec3 NewRotator; + glm::vec3 CurrentRotator = glm::eulerAngles(CurrentRotation); + // + + NewRotator.x = + LockRoll ? mytransform->get_rotation().x : CurrentRotator.x; + NewRotator.y = + LockPitch ? mytransform->get_rotation().y : CurrentRotator.y; + NewRotator.z = + LockYaw ? mytransform->get_rotation().z : CurrentRotator.z; + + return glm::quat(NewRotator); +} + +// The target offset is the value of where the target is compared to where he "should" be based on where +// the camera is. It is what the camera needs to move to be centered on the target +void ThirdPersonFollow::CalculateTargetOffset() +{ + glm::vec3 p1 = + (mytransform->Forward() * Distance) + + TFOR.TransformDirection(Offset) + + mytransform->get_global_translation(); + glm::vec3 p2 = + TFOR.InverseTransformDirection(Target->get_global_translation()); + glm::vec3 p3 = TFOR.InverseTransformDirection(p1); + + TargetOffset = p2 - p3; +} + +void follow_targetoffset() +{ + mfloat_t p1[3], p2[3], p3[3] = {0}; + + + +} + +*/ diff --git a/source/engine/thirdpersonfollow.h b/source/engine/thirdpersonfollow.h new file mode 100644 index 0000000..f2b2f73 --- /dev/null +++ b/source/engine/thirdpersonfollow.h @@ -0,0 +1,190 @@ +// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit. + +#ifndef THIRDPERSONFOLLOW_H +#define THIRDPERSONFOLLOW_H + +#include "transform.h" + +struct follow { + float distance; + mfloat_t target_rot[4]; +}; + +mfloat_t *follow_calcpos(); +mfloat_t *follow_calccenter(); +mfloat_t *follow_postoffset(); +mfloat_t *extentsoffset(); +mfloat_t *framebasedveclerp(); +int lerpparam(float offset, float anchorwidth, float floatwidth); +mfloat_t *vec3lerp(mfloat_t from[3], mfloat_t to[3], mfloat_t a[3]); +void follow_calctargets(); +mfloat_t *follow_removelockedrot(); +void follow_targetoffset(struct follow *follow); +int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e); + +/* + +////////////////////////////////////////////////////////////////////////// +// A good camera. +////////////////////////////////////////////////////////////////////////// + +class ThirdPersonFollow { + + public: + enum CameraType { + STATIONARY, + TRANSLATING, + ROTATING, + SPLINE + }; + + enum CameraTransition { + NONE, + CROSSDISSOLVE, + WIPE, + DIP + }; + + enum FrameOfReference { + LOCAL, + WORLD, + EXTERNAL + }; + + ThirdPersonFollow() { + // Rotation + RotationSpeed = 10.0f; + LockPitch = LockYaw = LockRoll = true; + + XDirPosts = false; + YDirPosts = false; + ZDirPosts = false; + + + // Translation + //FloatWidths = AnchorWidths = CenterVector = glm::vec3(0, 0, 0); + PositionSpeeds = glm::vec3(2.f, 2.f, 2.f); + //TranslationScales = glm::vec3(1, 1, 1); + + // Frame settings + Offset = glm::vec3(0.f, 0.f, 0.f); + Distance = 10; + + AnchorSpeed = 80; + } ~ThirdPersonFollow() { + } + + Transform *mytransform; + + // An actor that can be given for the camera to base its movement around + // instead of itself. Makes most sense for this to be stationary + Transform *ExternalFrame = nullptr; + + + void SetExternalFrame(Transform * val) { + ExternalFrame = val; + } + + // The target the camera "looks" at, used for calculations + Transform *Target = nullptr; + + void SetTarget(Transform * val) { + Target = val; + } + + // Offset from the target + glm::vec3 Offset; + + // How far away should the camera act from the target + float Distance; + + /////////////////////////////////////////////////////////////////////////// + // Translation variables. In this mode, the camera doesn't rotate to look + // at the target, it only moves around the world. + /////////////////////////////////////////////////////////////////////////// + + /// "Posts" for each direction in 3D space. These are items that the target + /// is allowed to move within without the camera following along. + bool XDirPosts; + bool YDirPosts; + bool ZDirPosts; + + /// The range in ecah direction the camera floats. While within this range, + /// the camera will smoothly glide to the desired position. + glm::vec3 FloatWidths; + + /// The clamp range for each direction. If the camera reaches this range, + /// it will stick and not move any further. + glm::vec3 AnchorWidths; + + /// When floating to the target, the speed to float. + glm::vec3 PositionSpeeds; + + ////////////////////////////////////////////////////////////////////////// + // Rotation variables. Used for the camera's rotation mode, where it + // follows the Target without translating. + ////////////////////////////////////////////////////////////////////////// + + /// Variables to lock its rotation in any of the three directions + bool LockRoll; + bool LockPitch; + bool LockYaw; + + glm::vec3 RotationOffset; + + /// The speed of rotation + float RotationSpeed; + + private: + void CalculateTargetOffset(); + + // Transform of frame of reference + Transform TFOR; + + /// The calculated offset based on frames of reference + glm::vec3 TargetOffset; + + glm::vec3 TargetPosition; + + glm::quat TargetRotation; + + + void CalculateTargets(); + + // Calculates + + glm::vec3 CalculatePosition(); + + glm::vec3 CalculateCenter(); + + /// Given a direction and width, find the offsets. + glm::vec3 GetPostsOffset(const glm::vec3 & DirectionVector, + float AnchorWidth); + + /// Given anchors, what's the anchor width? + glm::vec3 GetExtentsOffset(const glm::vec3 & DirectionVector, + float AnchorWidth, float TOffset, + float Width); + + glm::quat RemoveLockedRotation(const glm::quat & CurrentRotation); + + glm::vec3 FrameBasedVectorLerp(const glm::vec3 & From, + const glm::vec3 & To, + const glm::vec3 & Speeds, float Tick); + + glm::vec3 VectorLerpPiecewise(const glm::vec3 & From, + const glm::vec3 & To, + const glm::vec3 & Alpha); + + bool GetLerpParam(const float Offst, const float AnchorWidth, + const float FloatWidth); + + /// Set to a value that gives good clamping, smoothly. Activates when + /// the target is out of range. + float AnchorSpeed; + +}; + +*/ + +#endif diff --git a/source/engine/transform.c b/source/engine/transform.c new file mode 100644 index 0000000..d143f90 --- /dev/null +++ b/source/engine/transform.c @@ -0,0 +1,44 @@ +#include "transform.h" +#include + +struct mTransform MakeTransform(mfloat_t pos[3], mfloat_t rotation[4], + float scale) +{ + struct mTransform newT; + memcpy(newT.position, pos, sizeof(*pos)); + memcpy(newT.rotation, rotation, sizeof(*rotation)); + newT.scale = scale; + return newT; +} + +mfloat_t *trans_forward(mfloat_t * res, + const struct mTransform *const trans) +{ + // YughLog(0, SDL_LOG_PRIORITY_WARN, "Rotation is %f", trans->rotation[0]); + return vec3_rotate_quat(res, FORWARD, trans->rotation); +} + +mfloat_t *trans_back(mfloat_t * res, const struct mTransform *trans) +{ + return vec3_rotate_quat(res, BACK, trans->rotation); +} + +mfloat_t *trans_up(mfloat_t * res, const struct mTransform *trans) +{ + return vec3_rotate_quat(res, UP, trans->rotation); +} + +mfloat_t *trans_down(mfloat_t * res, const struct mTransform *trans) +{ + return vec3_rotate_quat(res, DOWN, trans->rotation); +} + +mfloat_t *trans_right(mfloat_t * res, const struct mTransform *trans) +{ + return vec3_rotate_quat(res, RIGHT, trans->rotation); +} + +mfloat_t *trans_left(mfloat_t * res, const struct mTransform *trans) +{ + return vec3_rotate_quat(res, LEFT, trans->rotation); +} diff --git a/source/engine/transform.h b/source/engine/transform.h new file mode 100644 index 0000000..171e900 --- /dev/null +++ b/source/engine/transform.h @@ -0,0 +1,27 @@ +#ifndef TRANSFORM_H +#define TRANSFORM_H + +#include "mathc.h" + +struct mTransform { + mfloat_t position[3]; + mfloat_t rotation[4]; + float scale; +}; + + +struct mTransform MakeTransform(mfloat_t pos[3], mfloat_t rotation[3], + float scale); + +mfloat_t *trans_forward(mfloat_t * res, + const struct mTransform *const trans); +mfloat_t *trans_back(mfloat_t * res, const struct mTransform *trans); +mfloat_t *trans_up(mfloat_t * res, const struct mTransform *trans); +mfloat_t *trans_down(mfloat_t * res, const struct mTransform *trans); +mfloat_t *trans_right(mfloat_t * res, const struct mTransform *trans); +mfloat_t *trans_left(mfloat_t * res, const struct mTransform *trans); + + +//extern Serialize *make_transform(); + +#endif diff --git a/source/engine/vec.c b/source/engine/vec.c new file mode 100644 index 0000000..565e627 --- /dev/null +++ b/source/engine/vec.c @@ -0,0 +1,132 @@ +#include "vec.h" +#include "log.h" + + +struct vec *vec_make(int width, int size) +{ + struct vec *new = calloc(1, sizeof(struct vec)); + new->size = size; + new->width = width; + new->data = calloc(new->size, new->width); + return new; +} + +void *vec_get(struct vec *vec, int n) +{ + if (n < vec->len) + return (char *) vec->data + (n * vec->width); + + YughLog(0, 4, + "Attempted to access element %d of a vec with %d elements.", n, + vec->len); + return NULL; +} + +void vec_walk(struct vec *vec, void (*fn)(void *data)) +{ + for(int i = 0; i < vec->len; i++) + fn((char *) (vec->data + (i * vec->width))); +} + +void vec_delete(struct vec *vec, int n) +{ + if (n < vec->len) { + vec->len--; + memcpy(vec_p(vec, n), vec_p(vec, vec->len), vec->width); + } + +} + +void vec_del_order(struct vec *vec, int n) +{ + if (n < vec->len) { + vec->len--; + memmove(vec_p(vec, n), vec_p(vec, n + 1), + vec->width * (vec->len - n)); + } +} + +void *vec_add(struct vec *vec, void *data) +{ + if (vec->size == vec->len) + vec_expand(vec); + + if (data) + memcpy(vec_p(vec, vec->len), data, vec->width); + else + memset(vec_p(vec, vec->len), 0, vec->width); + + vec->len++; + return vec_get(vec, vec->len - 1); +} + +void *vec_add_sort(struct vec *vec, void *data, + int (*sort)(void *a, void *b)) +{ + if(vec->size == vec->len) + vec_expand(vec); + + int n = vec->len - 1; + while (sort(vec_p(vec, n), data)) + n--; + + vec_insert(vec, data, n); +} + +void *vec_insert(struct vec *vec, void *data, int n) +{ + if (vec->size == vec->len) + vec_expand(vec); + + memmove(vec_p(vec, n), vec_p(vec, n + 1), vec->width * (vec->len - n)); + vec->len++; + memcpy(vec_p(vec, n), data, vec->width); + return vec_get(vec, n); +} + +char *vec_p(struct vec *vec, int n) +{ + return ((char *) vec->data + (vec->width * n)); +} + +void *vec_set(struct vec *vec, int n, void *data) +{ + if (vec->len >= n) + return NULL; + + memcpy(vec_p(vec, n), data, vec->width); + return vec_get(vec, n); +} + +void vec_expand(struct vec *vec) +{ + vec->size *= 2; + vec->data = realloc(vec->data, vec->size * vec->width); +} + +void vec_store(struct vec *vec, FILE * f) +{ + fwrite(&vec->len, sizeof(vec->len), 1, f); + fwrite(&vec->size, sizeof(vec->size), 1, f); + fwrite(&vec->width, sizeof(vec->width), 1, f); + fwrite(vec->data, vec->width, vec->len, f); +} + +void vec_load(struct vec *vec, FILE * f) +{ + fread(&vec->len, sizeof(vec->len), 1, f); + fread(&vec->size, sizeof(vec->size), 1, f); + fread(&vec->width, sizeof(vec->width), 1, f); + fread(vec->data, vec->width, vec->len, f); +} + +void vec_clear(struct vec *vec) +{ + vec->len = 0; +} + +void vec_fit(struct vec *vec) +{ + vec->size = vec->len; + vec->data = realloc(vec->data, vec->size * vec->width); +} diff --git a/source/engine/vec.h b/source/engine/vec.h new file mode 100644 index 0000000..955e908 --- /dev/null +++ b/source/engine/vec.h @@ -0,0 +1,32 @@ +#ifndef VEC_H +#define VEC_H + +#include + +struct vec { + int len; + int size; + int width; + void *data; +}; + +struct vec *vec_make(int width, int size); +void *vec_get(struct vec *vec, int n); +void vec_walk(struct vec *vec, void (*fn)(void *data)); +void vec_clear(struct vec *vec); +void *vec_add(struct vec *vec, void *data); + +/* sort returns 0 for a<=b, 1 for a>b */ +void *vec_add_sort(struct vec *vec, void *data, + int (*sort)(void *a, void *b)); +void *vec_insert(struct vec *vec, void *data, int n); +void *vec_set(struct vec *vec, int n, void *data); +void vec_delete(struct vec *vec, int n); +void vec_del_order(struct vec *vec, int n); +void vec_store(struct vec *vec, FILE *f); +void vec_load(struct vec *vec, FILE *f); +char *vec_p(struct vec *vec, int n); +void vec_expand(struct vec *vec); +void vec_fit(struct vec *vec); + +#endif \ No newline at end of file diff --git a/source/engine/window.c b/source/engine/window.c new file mode 100644 index 0000000..e8230f6 --- /dev/null +++ b/source/engine/window.c @@ -0,0 +1,157 @@ +#include "window.h" + +#include "openglrender.h" + +#include +#include "log.h" + +struct mSDLWindow *window = NULL; + +static struct mSDLWindow *windows[5]; +static int numWindows = 0; + +struct mSDLWindow *MakeSDLWindow(const char *name, int width, int height, + uint32_t flags) +{ + struct mSDLWindow *w = calloc(1, sizeof(struct mSDLWindow)); + w->width = width; + w->height = height; + w->window = SDL_CreateWindow(name, 0, 0, width, height, flags); + + if (w->window == NULL) { + YughLog(0, SDL_LOG_PRIORITY_ERROR, + "Window could not be created! SDL Error: %s", + SDL_GetError()); + } else { + w->glContext = SDL_GL_CreateContext(w->window); + + if (w->glContext == NULL) { + YughLog(0, SDL_LOG_PRIORITY_ERROR, + "OpenGL context could not be created! SDL Error: %s", + SDL_GetError()); + } + w->id = SDL_GetWindowID(w->window); + + glewExperimental = GL_TRUE; + glewInit(); + + SDL_GL_SetSwapInterval(1); + + if (numWindows < 5) + windows[numWindows++] = w; + } + + + return w; +} + +void window_handle_event(struct mSDLWindow *w, SDL_Event * e) +{ + if (e->type == SDL_WINDOWEVENT && e->window.windowID == w->id) { // TODO: Check ptr direct? + switch (e->window.event) { + case SDL_WINDOWEVENT_SHOWN: + YughLog(0, SDL_LOG_PRIORITY_INFO, "Showed window %d.", w->id); + w->shown = true; + break; + + case SDL_WINDOWEVENT_HIDDEN: + w->shown = false; + YughLog(0, SDL_LOG_PRIORITY_INFO, "Hid window %d.", w->id); + break; + + case SDL_WINDOWEVENT_SIZE_CHANGED: + + w->width = e->window.data1; + w->height = e->window.data2; + YughLog(0, SDL_LOG_PRIORITY_INFO, + "Changed size of window %d: width %d, height %d.", + w->id, w->width, w->height); + window_makecurrent(w); + /*w.projection = + glm::ortho(0.f, (float) width, 0.f, (float) height, -1.f, + 1.f); */ + w->render = true; + break; + + case SDL_WINDOWEVENT_EXPOSED: + YughLog(0, SDL_LOG_PRIORITY_INFO, "Exposed window %d.", w->id); + w->render = true; + break; + + case SDL_WINDOWEVENT_ENTER: + YughLog(0, SDL_LOG_PRIORITY_INFO, "Entered window %d.", w->id); + w->mouseFocus = true; + SDL_RaiseWindow(w->window); + break; + + case SDL_WINDOWEVENT_LEAVE: + YughLog(0, SDL_LOG_PRIORITY_INFO, "Left window %d.", w->id); + w->mouseFocus = false; + break; + + case SDL_WINDOWEVENT_FOCUS_LOST: + YughLog(0, SDL_LOG_PRIORITY_INFO, + "Lost focus on window %d.", w->id); + w->keyboardFocus = false; + break; + + case SDL_WINDOWEVENT_FOCUS_GAINED: + YughLog(0, SDL_LOG_PRIORITY_INFO, + "Gained focus on window %d.", w->id); + w->keyboardFocus = true; + break; + + case SDL_WINDOWEVENT_MINIMIZED: + YughLog(0, SDL_LOG_PRIORITY_INFO, + "Minimized window %d.", w->id); + w->minimized = true; + break; + + case SDL_WINDOWEVENT_MAXIMIZED: + YughLog(0, SDL_LOG_PRIORITY_INFO, + "Maximized window %d.", w->id); + w->minimized = false; + break; + + case SDL_WINDOWEVENT_RESTORED: + YughLog(0, SDL_LOG_PRIORITY_INFO, + "Restored window %d.", w->id); + w->minimized = false; + break; + + case SDL_WINDOWEVENT_CLOSE: + YughLog(0, SDL_LOG_PRIORITY_INFO, "Closed window %d.", w->id); + break; + } + } +} + +void window_makefullscreen(struct mSDLWindow *w) +{ + SDL_SetWindowFullscreen(w->window, SDL_WINDOW_FULLSCREEN_DESKTOP); + w->fullscreen = true; +} + +void window_togglefullscreen(struct mSDLWindow *w) +{ + w->fullscreen = !w->fullscreen; + + if (w->fullscreen) { + window_makefullscreen(w); + } else { + SDL_SetWindowFullscreen(w->window, 0); + } + +} + +void window_makecurrent(struct mSDLWindow *w) +{ + if (w->window != SDL_GL_GetCurrentWindow()) + SDL_GL_MakeCurrent(w->window, w->glContext); + glViewport(0, 0, w->width, w->height); +} + +void window_swap(struct mSDLWindow *w) +{ + SDL_GL_SwapWindow(w->window); +} diff --git a/source/engine/window.h b/source/engine/window.h new file mode 100644 index 0000000..1841e41 --- /dev/null +++ b/source/engine/window.h @@ -0,0 +1,34 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include +#include + +struct mSDLWindow { + SDL_Window *window; + SDL_GLContext glContext; + int id; + int width; + int height; + /* TODO: Bitfield these */ + bool render; + bool mouseFocus; + bool keyboardFocus; + bool fullscreen; + bool minimized; + bool shown; + float projection[16]; +}; + +extern struct mSDLWindow *window; + +struct mSDLWindow *MakeSDLWindow(const char *name, int width, int height, + uint32_t flags); +void window_handle_event(struct mSDLWindow *w, SDL_Event * e); +void window_focus(struct mSDLWindow *w); +void window_makecurrent(struct mSDLWindow *w); +void window_makefullscreen(struct mSDLWindow *w); +void window_togglefullscreen(struct mSDLWindow *w); +void window_swap(struct mSDLWindow *w); + +#endif