diff --git a/.gitmodules b/.gitmodules index 729155b..3167aa9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "ext/glfw"] path = ext/glfw url = https://github.com/glfw/glfw.git +[submodule "ext/glm"] + path = ext/glm + url = https://github.com/g-truc/glm.git diff --git a/LivePlotter.vcxproj b/LivePlotter.vcxproj index f64b801..d42a03b 100644 --- a/LivePlotter.vcxproj +++ b/LivePlotter.vcxproj @@ -72,7 +72,7 @@ $(SolutionDir)ext\glfw\build\src\Debug;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) - $(SolutionDir)ext\glfw\include;$(SolutionDir)inc;$(IncludePath) + $(SolutionDir)ext\glm;$(SolutionDir)ext\glfw\include;$(SolutionDir)inc;$(IncludePath) $(SolutionDir)bin\$(Platform)\$(Configuration)\ $(SolutionDir)obj\$(Platform)\$(Configuration)\ $(SolutionDir)src;$(SourcePath) @@ -111,7 +111,7 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 Console @@ -136,6 +136,7 @@ + diff --git a/LivePlotter.vcxproj.filters b/LivePlotter.vcxproj.filters index 42191b5..23a472a 100644 --- a/LivePlotter.vcxproj.filters +++ b/LivePlotter.vcxproj.filters @@ -27,5 +27,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/compile_commands.json b/compile_commands.json index d71ff1b..490054d 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -1,25 +1,31 @@ [ { - "directory": "C:/Users/sethh/Documents/repos/LivePlotter/", - "command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/sethh/Documents/repos/LivePlotter/src/util.cpp\" -std=c++17 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"", - "file": "C:/Users/sethh/Documents/repos/LivePlotter/src/util.cpp" + "directory": "C:/Users/seth/Documents/repos/LivePlotter/", + "command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/main.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"", + "file": "C:/Users/seth/Documents/repos/LivePlotter/src/main.cpp" } , { - "directory": "C:/Users/sethh/Documents/repos/LivePlotter/", - "command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c \"C:/Users/sethh/Documents/repos/LivePlotter/src/glad.c\" -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"", - "file": "C:/Users/sethh/Documents/repos/LivePlotter/src/glad.c" + "directory": "C:/Users/seth/Documents/repos/LivePlotter/", + "command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/shaders.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"", + "file": "C:/Users/seth/Documents/repos/LivePlotter/src/shaders.cpp" } , { - "directory": "C:/Users/sethh/Documents/repos/LivePlotter/", - "command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/sethh/Documents/repos/LivePlotter/src/shaders.cpp\" -std=c++17 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"", - "file": "C:/Users/sethh/Documents/repos/LivePlotter/src/shaders.cpp" + "directory": "C:/Users/seth/Documents/repos/LivePlotter/", + "command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c \"C:/Users/seth/Documents/repos/LivePlotter/src/glad.c\" -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"", + "file": "C:/Users/seth/Documents/repos/LivePlotter/src/glad.c" } , { - "directory": "C:/Users/sethh/Documents/repos/LivePlotter/", - "command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/sethh/Documents/repos/LivePlotter/src/main.cpp\" -std=c++17 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"", - "file": "C:/Users/sethh/Documents/repos/LivePlotter/src/main.cpp" + "directory": "C:/Users/seth/Documents/repos/LivePlotter/", + "command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/util.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"", + "file": "C:/Users/seth/Documents/repos/LivePlotter/src/util.cpp" + } + , + { + "directory": "C:/Users/seth/Documents/repos/LivePlotter/", + "command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/body.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"", + "file": "C:/Users/seth/Documents/repos/LivePlotter/src/body.cpp" } ] diff --git a/ext/glm b/ext/glm new file mode 160000 index 0000000..2d4c4b4 --- /dev/null +++ b/ext/glm @@ -0,0 +1 @@ +Subproject commit 2d4c4b4dd31fde06cfffad7915c2b3006402322f diff --git a/inc/body.hpp b/inc/body.hpp new file mode 100644 index 0000000..e27e766 --- /dev/null +++ b/inc/body.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include "util.hpp" + +struct body { + glm::mat4 pose; + uint ebo; + uint vao; + uint vbo; + uint shader; + array verts; + array faces; + glm::vec4 color; +}; + +bool load_body(body* out_body, const char* obj_filepath); +void draw_body(const body& b); diff --git a/inc/globj.hpp b/inc/globj.hpp deleted file mode 100644 index 76b8b2b..0000000 --- a/inc/globj.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "util.hpp" - - diff --git a/inc/shaders.hpp b/inc/shaders.hpp index c4a9404..a344fff 100644 --- a/inc/shaders.hpp +++ b/inc/shaders.hpp @@ -2,18 +2,16 @@ #include #include +#include #include "util.hpp" -namespace shader { - // Reads shader source files, compiles, and links -bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepath); +bool load_shader(uint* out_id, const char* vertex_filepath, const char* fragment_filepath); // Sets shader as active on the gpu -void use(uint id); +void use_shader(uint id); // Set uniform value -typedef std::variant uniform_variant; +typedef std::variant + uniform_variant; void set_uniform(uint id, const char* name, uniform_variant value); - -} // namespace shaders diff --git a/inc/util.hpp b/inc/util.hpp index 0a12000..72cfe09 100644 --- a/inc/util.hpp +++ b/inc/util.hpp @@ -5,45 +5,9 @@ template struct array { T* data; size_t len; - T& operator[](int i); + inline T& operator[](int i) { return data[i]; } }; typedef unsigned int uint; bool read_file(array* out, const char* filepath); - -struct vec4 { - float x; - float y; - float z; - float w; -}; - -struct vec3 { - float x; - float y; - float z; -}; - -struct vec2 { - float x; - float y; -}; - -struct vec4i { - int x; - int y; - int z; - int w; -}; - -struct vec3i { - int x; - int y; - int z; -}; - -struct vec2i { - int x; - int y; -}; diff --git a/src/body.cpp b/src/body.cpp new file mode 100644 index 0000000..d10f321 --- /dev/null +++ b/src/body.cpp @@ -0,0 +1,120 @@ +#include +#include +#include "util.hpp" +#include "body.hpp" +#include "shaders.hpp" + +enum class ParserState { + PREFIX, + VERTEX, + FACE, + FACE_SKIP, +}; + +bool load_body(body* out_body, const char* obj_filepath) { + array source; + if (!read_file(&source, obj_filepath)) { + return false; + } + + size_t num_verts = 0; + size_t num_faces = 0; + for (int i = 1; i < source.len; i++) { + if (source[i] == ' ' && source[i - 1] == 'v') { + num_verts++; + } else if (source[i] == ' ' && source[i - 1] == 'f') { + num_faces++; + } + } + + array verts = { (float*)malloc(sizeof(float) * num_verts * 3), num_verts * 3 }; + array faces = { (int*)malloc(sizeof(int) * num_faces * 3), num_faces*3 }; + + // Get ready for the parsing loop + ParserState state = ParserState::PREFIX; + int vert_i = 0; + int face_i = 0; + int start = 0; + + for (int i = 1; i < source.len; i++) { + if (source[i] == '\n') { + state = ParserState::PREFIX; + continue; + } + switch (state) { + case ParserState::PREFIX: + if (source[i - 1] == 'v' && source[i] == ' ') { + state = ParserState::VERTEX; + start = i + 1; + } else if (i > 0 && source[i - 1] == 'f' && source[i] == ' ') { + state = ParserState::FACE; + start = i + 1; + } + break; + case ParserState::VERTEX: + if (source[i] == ' ' || source[i] == '\r' || source[i] == '\n') { + verts[vert_i] = atof(&source[start])/1.5; + vert_i++; + start = i + 1; + } + break; + case ParserState::FACE: + if (source[i] == '/') { + state = ParserState::FACE_SKIP; + faces[face_i] = atoi(&source[start]) - 1; + face_i++; + } + break; + case ParserState::FACE_SKIP: + if (source[i] == ' ') { + state = ParserState::FACE; + start = i + 1; + } + } + } + + // Need a good validation check here. This is a stand in. + if (verts.len == 0 || faces.len == 0) { + printf( + "Obj file appears incomplete or corrupted. Num verts %zu. Num Faces %zu.\n", verts.len, faces.len); + return false; + } + + uint vao, vbo, ebo; + + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + glGenBuffers(1, &ebo); + + glBindVertexArray(vao); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, verts.len * sizeof(float), verts.data, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, faces.len * sizeof(int), faces.data, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + + *out_body = { .pose = glm::mat4(1), + .ebo = ebo, + .vao = vao, + .vbo = vbo, + .shader = 0, + .verts = verts, + .faces = faces, + .color = glm::vec4(0.5, 0.5, 0.5, 1) + }; + + return true; +} + +void draw_body(const body& b) { + use_shader(b.shader); + set_uniform(b.shader, "global_t", b.pose); + set_uniform(b.shader, "color", b.color); + glBindVertexArray(b.vao); + glDrawElements(GL_TRIANGLES, b.faces.len, GL_UNSIGNED_INT, 0); + //glDisableVertexAttribArray(0); +} diff --git a/src/main.cpp b/src/main.cpp index 91cc7e0..ffaca6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,24 +1,91 @@ -#include -#include #include #include -#include +#include +#include +#include #include -#include #include "util.hpp" #include "shaders.hpp" +#include "body.hpp" static GLFWwindow* window; +static float width, height; -void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } - -void processInput(GLFWwindow* window) { - if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) - glfwSetWindowShouldClose(window, true); +void framebuffer_size_callback(GLFWwindow* window, int w, int h) { + width = w; + height = h; + glViewport(0, 0, width, height); } -bool glfw_window_setup() { +void process_input() { + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); + +} + +static bool mouse_pressed = false; +static bool scroll_pressed = false; +static double prev_cursor_x, prev_cursor_y; + +static double theta = 0.0; // angle of camera trans vect wrt x-z plane +static double phi = 0.0; // angle of camera trans vect wrt x-axis + +static glm::vec3 camera_loc = glm::vec3(0, 0, 2); +static glm::vec3 focal_point = glm::vec3(0, 0, 0); +static glm::vec3 up = glm::vec3(0, 1, 0); +static glm::mat4 camera_t = glm::lookAt(camera_loc, focal_point, up); + +static glm::vec4 strafe_x = camera_t[0]; +static glm::vec4 strafe_y = camera_t[1]; + +static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) { + float dx = (xpos - prev_cursor_x); + float dy = (ypos - prev_cursor_y); + prev_cursor_x = xpos; + prev_cursor_y = ypos; + if (mouse_pressed) { + phi += dx / width * glm::radians(360.0); + theta += dy / height * glm::radians(360.0); + } + + if (scroll_pressed) { + focal_point += strafe_x * (dx/300) + strafe_y * (dy/300); + } + + double len = glm::length(camera_loc); + camera_loc.x = len * glm::cos(theta) * glm::cos(-phi); + camera_loc.y = len * glm::sin(theta); + camera_loc.z = -len * glm::cos(theta) * glm::sin(-phi); + + camera_t = glm::lookAt(camera_loc, focal_point, up); +} + +void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { + if (button == GLFW_MOUSE_BUTTON_RIGHT) { + mouse_pressed = action == GLFW_PRESS; + } + + if (button == GLFW_MOUSE_BUTTON_MIDDLE) { + scroll_pressed = action == GLFW_PRESS; + strafe_x = camera_t[0]; + strafe_y = camera_t[1]; + } + + glfwGetCursorPos(window, &prev_cursor_x, &prev_cursor_y); +} + +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) +{ + glm::vec4 k = camera_t[2]; + float d = yoffset; + + camera_loc += k * (-d * glm::length(camera_loc) / 10); + + camera_t = glm::lookAt(camera_loc, focal_point, up); +} + +bool glfw_setup() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); @@ -26,147 +93,72 @@ bool glfw_window_setup() { // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); window = glfwCreateWindow(800, 800, "LearnOpenGL", NULL, NULL); if (window == NULL) { - std::cout << "Failed to create GLFW windoww" << std::endl; + printf("Failed to create GLFW window\n"); glfwTerminate(); return false; } glfwMakeContextCurrent(window); + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwSetCursorPosCallback(window, cursor_position_callback); + glfwSetMouseButtonCallback(window, mouse_button_callback); + glfwSetScrollCallback(window, scroll_callback); + + cursor_position_callback(window, 0, 0); return true; } -enum class ParserState { - PREFIX, - VERTEX, - FACE, - FACE_SKIP, -}; -std::optional, array>> load_icosphere() { - std::FILE* f = NULL; - - if (fopen_s(&f, "Icosphere.obj", "r")) { - return {}; - } - - // MEMORY LEAK!!! 84 verts currently - float* vert_data = (float*)malloc(sizeof(float) * 128); - size_t vert_data_size = 0; - - // MEMORY LEAK!!! (I think) - unsigned int* indices_data = (unsigned int*)malloc(sizeof(int) * 256); - size_t indices_data_size = 0; - - ParserState state = ParserState::PREFIX; - - char ln[128]; - int len = 0; - int start = 0; - while ((ln[len] = std::fgetc(f)) != EOF) { - switch (state) { - case ParserState::PREFIX: - if (len > 0 && ln[len - 1] == 'v' && ln[len] == ' ') { - state = ParserState::VERTEX; - start = len + 1; - } else if (len > 0 && ln[len - 1] == 'f' && ln[len] == ' ') { - state = ParserState::FACE; - start = len + 1; - } - break; - case ParserState::VERTEX: - if (ln[len] == ' ' || ln[len] == '\n') { - vert_data[vert_data_size] = atof(&ln[start]); - vert_data_size++; - start = len + 1; - } - break; - case ParserState::FACE: - if (ln[len] == '/') { - state = ParserState::FACE_SKIP; - indices_data[indices_data_size] = atoi(&ln[start]) - 1; - indices_data_size++; - } - break; - case ParserState::FACE_SKIP: - if (ln[len] == ' ') { - state = ParserState::FACE; - start = len + 1; - } - } - - if (ln[len] == '\n') { - len = 0; - state = ParserState::PREFIX; - } - len++; - } - - array verts = { vert_data, vert_data_size }; - array indices = { indices_data, indices_data_size }; - - return std::make_pair(verts, indices); -} int main() { - if (!glfw_window_setup()) + if (!glfw_setup()) return -1; - auto data = load_icosphere(); - if (!data) { - std::cout << "ERROR loading the icosphere obj file failed" << std::endl; - return -1; - } - - auto verts = data.value().first; - auto indices = data.value().second; - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { - std::cout << "Failed to initialize GLAD" << std::endl; + printf("Failed to initialize GLAD\n"); return -1; } glViewport(0, 0, 800, 800); - glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + width = 800; + height = 800; - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + uint shader; + const char* vertex_filepath = "src/shaders/vertex.glsl"; + const char* fragment_filepath = "src/shaders/fragment.glsl"; + if (!load_shader(&shader, vertex_filepath, fragment_filepath)) + return -1; + + //glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); // Write to back buffer glfwSwapBuffers(window); // front buffer is now back glClear(GL_COLOR_BUFFER_BIT); // Write to back buffer again (former front buf) - unsigned int VAO; - glGenVertexArrays(1, &VAO); - glBindVertexArray(VAO); - - unsigned int VBO; - glGenBuffers(1, &VBO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, verts.len * sizeof(float), verts.data, GL_STATIC_DRAW); - - unsigned int EBO; - glGenBuffers(1, &EBO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.len * sizeof(unsigned int), indices.data, GL_STATIC_DRAW); - - uint program_id; - const char* vertex_filepath = "src/shaders/vertex.glsl"; - const char* fragment_filepath = "src/shaders/fragment.glsl"; - if (!shader::load(&program_id, vertex_filepath, fragment_filepath)) + body b; + if (!load_body(&b, "Icosphere.obj")) return -1; - shader::use(program_id); - - // Tell opengl which attribute our data is for (i.e. location) - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - glEnableVertexAttribArray(0); + b.shader = shader; + b.pose = glm::translate(b.pose, glm::vec3(0, 0, 0)); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //set_uniform(shader, "color", glm::vec4 { sin(time), sin(time + glm::radians(45.0f)), sin(time + glm::radians(90.0f)), 1.0 } / 2.0f); + //time = glfwGetTime(); + + glDisable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + float time; + + glm::mat4 projection_t + = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.1f, 1300.0f); while (!glfwWindowShouldClose(window)) { - float time = glfwGetTime(); - shader::set_uniform(program_id, "color", vec4 { 1, sin(time), 1, 1.0 }); - shader::use(program_id); - glClear(GL_COLOR_BUFFER_BIT); - glDrawElements(GL_TRIANGLES, indices.len, GL_UNSIGNED_INT, 0); - glBindVertexArray(VAO); + process_input(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + set_uniform(b.shader, "projection_t", projection_t); + set_uniform(b.shader, "camera_t", camera_t); + draw_body(b); - processInput(window); glfwSwapBuffers(window); glfwPollEvents(); } diff --git a/src/shaders.cpp b/src/shaders.cpp index 2c66c7c..127c456 100644 --- a/src/shaders.cpp +++ b/src/shaders.cpp @@ -1,5 +1,7 @@ -#include +#include #include +#include +#include #include "util.hpp" #include "shaders.hpp" @@ -14,11 +16,9 @@ struct overload : Ts ... { }; template overload(Ts...) -> overload; -namespace shader { - bool _compile_shader(uint *out_id, const char* filepath, int shader_type); -bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepath) { +bool load_shader(uint* out_id, const char* vertex_filepath, const char* fragment_filepath) { uint vertex_id; if (!_compile_shader(&vertex_id, vertex_filepath, GL_VERTEX_SHADER)) return false; @@ -49,25 +49,24 @@ bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepa return true; } -void use(uint id) { glUseProgram(id); } +void use_shader(uint id) { glUseProgram(id); } void set_uniform(uint id, const char* name, uniform_variant value) { const auto visitor = overload { [id, name](int i) { glUniform1i(glGetUniformLocation(id, name), i); }, [id, name](float f) { glUniform1f(glGetUniformLocation(id, name), f); }, [id, name](bool b) { glUniform1i(glGetUniformLocation(id, name), b); }, - [id, name](vec4 v) { glUniform4f(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); }, - [id, name](vec3 v) { glUniform3f(glGetUniformLocation(id, name), v.x, v.y, v.z); }, - [id, name](vec2 v) { glUniform2f(glGetUniformLocation(id, name), v.x, v.y); }, - [id, name](vec4i v) { glUniform4i(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); }, - [id, name](vec3i v) { glUniform3i(glGetUniformLocation(id, name), v.x, v.y, v.z); }, - [id, name](vec2i v) { glUniform2i(glGetUniformLocation(id, name), v.x, v.y); }, + [id, name](glm::vec4 v) { glUniform4f(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); }, + [id, name](glm::vec3 v) { glUniform3f(glGetUniformLocation(id, name), v.x, v.y, v.z); }, + [id, name](glm::vec2 v) { glUniform2f(glGetUniformLocation(id, name), v.x, v.y); }, + [id, name](glm::ivec4 v) { glUniform4i(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); }, + [id, name](glm::ivec3 v) { glUniform3i(glGetUniformLocation(id, name), v.x, v.y, v.z); }, + [id, name](glm::ivec2 v) { glUniform2i(glGetUniformLocation(id, name), v.x, v.y); }, + [id, name](glm::mat4 v) { glUniformMatrix4fv(glGetUniformLocation(id, name), 1, GL_FALSE, glm::value_ptr(v)); }, }; visit(visitor, value); } -// Privates - bool _compile_shader(uint *out_id, const char* filepath, int shader_type) { array source; if (!read_file(&source, filepath)) @@ -77,6 +76,8 @@ bool _compile_shader(uint *out_id, const char* filepath, int shader_type) { glShaderSource(id, 1, &source.data, (int*)&source.len); glCompileShader(id); + free(source.data); + int status; glGetShaderiv(id, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { @@ -89,5 +90,3 @@ bool _compile_shader(uint *out_id, const char* filepath, int shader_type) { *out_id = id; return status == GL_TRUE; } - -} // namespace shader diff --git a/src/shaders/fragment.glsl b/src/shaders/fragment.glsl index 2b3c651..978727c 100644 --- a/src/shaders/fragment.glsl +++ b/src/shaders/fragment.glsl @@ -2,8 +2,15 @@ uniform vec4 color; +in vec3 frag_pos; + out vec4 frag_color; void main() { - frag_color = color; + vec3 dx = dFdx(frag_pos) * 100; + vec3 dy = dFdy(frag_pos) * 100; + vec3 N = normalize(cross(dFdx(frag_pos), dFdy(frag_pos))); + frag_color = color + vec4(N/2, 1)/3; + //frag_color = vec4(length(dx), length(dy), length(dy), 1.0); + //frag_color += color; } diff --git a/src/shaders/vertex.glsl b/src/shaders/vertex.glsl index d126556..03ca3e6 100644 --- a/src/shaders/vertex.glsl +++ b/src/shaders/vertex.glsl @@ -1,8 +1,13 @@ #version 330 core -layout (location = 0) in vec3 pos; -uniform vec4 color; +layout (location = 0) in vec3 pos; +out vec3 frag_pos; + +uniform mat4 global_t; +uniform mat4 camera_t; +uniform mat4 projection_t; void main() { - gl_Position = vec4(pos.x, pos.y, pos.z, 1.0); + gl_Position = projection_t * camera_t * global_t * vec4(pos.x, pos.y, pos.z, 1.0); + frag_pos = pos; } diff --git a/src/util.cpp b/src/util.cpp index 351a15d..c69b6c5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "util.hpp"