diff --git a/.gitmodules b/.gitmodules index 74ae14a..4b4c1d6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ path = vendor/glad url = https://github.com/Dav1dde/glad.git branch = c +[submodule "vendor/glm"] + path = vendor/glm + url = https://github.com/g-truc/glm.git diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index bbaf422..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -hopf \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 0028c7b..a53ae4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(hopf) +project(hopf-fibration) set(CMAKE_CXX_STANDARD 17) @@ -11,4 +11,7 @@ option(GLFW_BUILD_EXAMPLES OFF) option(GLFW_BUILD_TESTS OFF) add_subdirectory(vendor/glfw) -add_subdirectory(main) +option(GLM_TEST_ENABLE OFF) +add_subdirectory(vendor/glm) + +add_subdirectory(main) \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index ddda9a7..2c3174b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,17 +1,18 @@ project(main) add_executable(${PROJECT_NAME} - src/main.cpp) + src/main.cpp include/util.h) target_link_libraries(${PROJECT_NAME} glad + glm glfw) target_include_directories(${PROJECT_NAME} - PRIVATE include) + PRIVATE + include) set(SHADERS - shaders/main.frag shaders/main.vert) add_custom_target(shaders DEPENDS ${SHADERS}) diff --git a/main/include/glga.hpp b/main/include/glga.hpp deleted file mode 100644 index 2aea9be..0000000 --- a/main/include/glga.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#include - -namespace ga { - struct Vec; - struct Bivec; - struct Mat; - - struct Vec { - float x, y, z, w; - - Vec(float x, float y, float z, float w) : - x(x), y(y), z(z), w(w) {} - - }; - - struct Bivec { - float xy, yz, zw, wx, xz, yw; - - Bivec(float xy, float yz, float zw, float wx, float xz, float yw) : - xy(xy), yz(yz), zw(zw), wx(wx), xz(xz), yw(yw) {} - }; - - struct Mat { - Vec x, y, z, w; - - Mat(Vec x, Vec y, Vec z, Vec w) : x(x), y(y), z(z), w(w) {} - }; - - namespace unit { - Vec x() { return Vec(1, 0, 0, 0); }; - - Vec y() { return Vec(1, 0, 0, 0); }; - - Vec z() { return Vec(1, 0, 0, 0); }; - - Vec w() { return Vec(1, 0, 0, 0); }; - - Bivec xy() { return Bivec(1, 0, 0, 0, 0, 0); } - - Bivec yz() { return Bivec(0, 1, 0, 0, 0, 0); } - - Bivec zw() { return Bivec(0, 0, 1, 0, 0, 0); } - - Bivec wx() { return Bivec(0, 0, 0, 1, 0, 0); } - - Bivec xz() { return Bivec(0, 0, 0, 0, 1, 0); } - - Bivec yw() { return Bivec(0, 0, 0, 0, 0, 1); } - } - - float length2(Vec v) { - return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w; - } - - float length2(Bivec v) { - return v.xy * v.xy + v.yz * v.yz + v.zw * v.zw - + v.wx * v.wx + v.xz * v.xz + v.yw * v.yw; - } - - float length(Vec v) { return sqrt(length2(v)); } - - float length(Bivec v) { return sqrt(length2(v)); } - - Vec add(Vec u, Vec v) { - return Vec(u.x + v.x, - u.y + v.y, - u.z + v.z, - u.w + v.w); - } - - Bivec add(Bivec u, Bivec v) { - Bivec(u.xy + v.xy, - u.yz + v.yz, - u.zw + v.zw, - u.wx + v.wx, - u.xz + v.xz, - u.yw + v.yw); - } - - Vec mul(float c, Vec v) { - return Vec(c * v.x, - c * v.y, - c * v.z, - c * v.w); - } - - Bivec mul(float c, Bivec v) { - Bivec(c * v.xy, - c * v.yz, - c * v.zw, - c * v.wx, - c * v.xz, - c * v.yw); - } - - Vec normalize(Vec v) { - return mul(1 / length(v), v); - } - - Bivec normalize(Bivec v) { - return mul(1 / length(v), v); - } - - Mat matrix(float c) { - // c as a transformation - // scale by c - return Mat(Vec(c, 0, 0, 0), Vec(0, c, 0, 0), Vec(0, 0, c, 0), Vec(0, 0, 0, c)); - } - - Mat matrix(Vec v) { - // v as a transformation - // reflect along v - return matrix(1); // todo reflection - } - - Mat rotor(Bivec v) { - // v as a transformation - // rotate along v - return matrix(1); - } -} \ No newline at end of file diff --git a/main/include/util.h b/main/include/util.h new file mode 100644 index 0000000..29d6df0 --- /dev/null +++ b/main/include/util.h @@ -0,0 +1,18 @@ +// +// Created by allem on 2/7/2019. +// + +#ifndef HOPF_FIBRATION_UTIL_H +#define HOPF_FIBRATION_UTIL_H + +#include + +void hello() { + printf("Hello there.\n"); +} + +void general() { + printf("General Kenobi.\n"); +} + +#endif //HOPF_FIBRATION_UTIL_H diff --git a/main/shaders/main.frag b/main/shaders/main.frag deleted file mode 100644 index d2e268c..0000000 --- a/main/shaders/main.frag +++ /dev/null @@ -1,17 +0,0 @@ -#version 440 - -#define PI 3.14159 - -in vec4 pos; -in vec4 pos4; -in vec4 pos3; - -out vec4 color; - -void main() { - float light = -pos3.y / 10 + .5; - - vec3 col = vec3(1); - - color = vec4(col * light, 1); -} \ No newline at end of file diff --git a/main/shaders/main.geom b/main/shaders/main.geom deleted file mode 100644 index cede560..0000000 --- a/main/shaders/main.geom +++ /dev/null @@ -1,47 +0,0 @@ -#version 440 - -#define CIRCLE_RES 64 -#define PI 3.14159 - -layout(points) in; -layout(line_strip, max_vertices=CIRCLE_RES) out; - -layout(binding=1) uniform Matrices { - mat4 proj; - mat4 model; -}; - -in float xi_[]; -in float eta_[]; - -out vec4 pos; -out vec4 pos4; -out vec4 pos3; - -void main(){ - for(int k = 0; k <= CIRCLE_RES; k++) { - vec2 xi = vec2(xi_[0], 4 * PI * k / (CIRCLE_RES - 1)); - float eta = eta_[0]; - - // todo parameterize the projected circle so there aren't jagged edges. - // should be smooth at <=32 segments, not just 128+ - float x = cos((xi.y + xi.x) / 2) * sin(eta); - float y = sin((xi.y + xi.x) / 2) * sin(eta); - float z = cos((xi.y - xi.x) / 2) * cos(eta); - float w = sin((xi.y - xi.x) / 2) * cos(eta); - - pos = vec4(x, y, z, w); - pos4 = model * pos; - pos3 = vec4(pos4.xyz / (1 - pos4.w), 1); - gl_Position = proj * pos3; - - if (length(gl_Position) > 4) { - EndPrimitive(); - continue; - } - - EmitVertex(); - } - - EndPrimitive(); -} \ No newline at end of file diff --git a/main/shaders/main.vert b/main/shaders/main.vert index ed3da93..e69de29 100644 --- a/main/shaders/main.vert +++ b/main/shaders/main.vert @@ -1,12 +0,0 @@ -#version 440 - -layout(location=0) in float xi; -layout(location=1) in float eta; - -out float xi_; -out float eta_; - -void main(){ - xi_ = xi; - eta_ = eta; -} \ No newline at end of file diff --git a/main/src/main.cpp b/main/src/main.cpp index e735b61..8249cd9 100644 --- a/main/src/main.cpp +++ b/main/src/main.cpp @@ -1,254 +1,37 @@ +// +// Created by allem on 2/7/2019. +// + #include #include -#include -#include -#include -#include -#include - -#include "glga.hpp" - -#define PI 3.14159f - -namespace util { - template - void bufferData(GLenum target, std::vector data, GLenum usage) { - glBufferData(target, data.size() * sizeof(T), &data.front(), usage); - } - - template - void bufferData(GLenum target, T &data, GLenum usage) { - glBufferData(target, sizeof(T), &data, usage); - } - - std::string readFile(const std::string &path) { - std::ifstream file(path); - if (!file) return std::string(); - - file.ignore(std::numeric_limits::max()); - auto size = file.gcount(); - - if (size > 0x10000) return std::string(); - - file.clear(); - file.seekg(0, std::ios_base::beg); - - std::stringstream sstr; - sstr << file.rdbuf(); - file.close(); - - return sstr.str(); - } - - void shaderFiles(GLuint shader, std::vector &paths) { - std::vector strs; - std::vector c_strs; - - for (const auto &path : paths) strs.push_back(readFile(path)); - for (const auto &str:strs) c_strs.push_back(str.c_str()); - - glShaderSource(shader, (GLsizei) c_strs.size(), &c_strs.front(), nullptr); - } - - std::string shaderInfoLog(GLuint shader) { - GLint log_len; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len); - char log[log_len]; - glGetShaderInfoLog(shader, log_len, nullptr, log); - return std::string(log); - } - - std::string programInfoLog(GLuint program) { - GLint log_len; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len); - char log[log_len]; - glGetProgramInfoLog(program, log_len, nullptr, log); - return std::string(log); - } - - GLuint buildShader(GLenum kind, const std::string &name, std::vector paths) { - GLuint shader = glCreateShader(kind); - shaderFiles(shader, paths); - - glCompileShader(shader); - - GLint comp; - glGetShaderiv(shader, GL_COMPILE_STATUS, &comp); - if (!comp) { - std::string log = shaderInfoLog(shader); - fprintf(stderr, "SHADER ERROR (%s):\n%s", name.c_str(), log.c_str()); - glDeleteShader(shader); - return 0; - } - - return shader; - } - - GLuint buildProgram(bool separable, const std::string &name, std::vector shaders) { - GLuint program = glCreateProgram(); - - if (separable) - glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); - - for (GLuint shader : shaders) - glAttachShader(program, shader); - - glLinkProgram(program); - - GLint link; - glGetProgramiv(program, GL_LINK_STATUS, &link); - if (!link) { - std::string log = programInfoLog(program); - fprintf(stderr, "PROGRAM ERROR (%s):\n%s", name.c_str(), log.c_str()); - glDeleteProgram(program); - return 0; - } - - return program; - } -} - -struct HopfCircle { - float xi; // longitude - float eta; // latitude - - HopfCircle(float xi, float eta) : xi(xi), eta(eta) {} - - HopfCircle() : HopfCircle(0, 0) {} -}; +#include +#include struct State { - GLuint vao{}; - GLuint vbo{}, ubo{}; - GLuint ubo_bp = 1; + void deinit(GLFWwindow *window) { - GLuint prog{}; - - std::vector circles{}; - - float t = 0; - - void regen() { - circles.clear(); - - const int N = 32; - const int M = 4; - const float PAD = 0.0125; - - for (int k = 0; k <= N; ++k) { - for (int j = 0; j <= M; ++j) { - float xi = 2 * PI * k / N; - float eta = (PI / 2 - 2 * PAD) * j / M + PAD; - circles.emplace_back(xi, eta); - } - } - - glBindBuffer(GL_ARRAY_BUFFER, vbo); - util::bufferData(GL_ARRAY_BUFFER, circles, GL_STREAM_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); } - explicit State(GLFWwindow *window) { - printf("vendor: %s\nrenderer: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER)); + void init(GLFWwindow *window) { - glGenBuffers(1, &vbo); - glGenBuffers(1, &ubo); - glGenVertexArrays(1, &vao); - - regen(); - - glBindBufferBase(GL_UNIFORM_BUFFER, ubo_bp, ubo); - - GLuint vs = util::buildShader(GL_VERTEX_SHADER, "vs", {"shaders/main.vert"}); - GLuint gs = util::buildShader(GL_GEOMETRY_SHADER, "gs", {"shaders/main.geom"}); - GLuint fs = util::buildShader(GL_FRAGMENT_SHADER, "fs", {"shaders/main.frag"}); - prog = util::buildProgram(false, "prog", {vs, gs, fs}); - - glBindVertexArray(vao); - - glBindBuffer(GL_ARRAY_BUFFER, vbo); - auto xi = glGetAttribLocation(prog, "xi"); - if (xi >= 0) { - glEnableVertexAttribArray((unsigned) xi); - glVertexAttribPointer((unsigned) xi, 1, GL_FLOAT, GL_FALSE, - sizeof(HopfCircle), - (void *) offsetof(HopfCircle, xi)); - } - - auto eta = glGetAttribLocation(prog, "eta"); - if (eta >= 0) { - glEnableVertexAttribArray((unsigned) eta); - glVertexAttribPointer((unsigned) eta, 1, GL_FLOAT, GL_FALSE, - sizeof(HopfCircle), - (void *) offsetof(HopfCircle, eta)); - } - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindVertexArray(0); - } - - void update(GLFWwindow *window, float dt, int frame) { - int w, h; - glfwGetFramebufferSize(window, &w, &h); - auto ar = (float) w / h; - - t += dt; - - float c = std::cos(t / 8); - float s = std::sin(t / 8); - - float c_ = std::cos(3.f / 8); - float s_ = std::sin(3.f / 8); - - glBindBuffer(GL_UNIFORM_BUFFER, ubo); - util::bufferData(GL_UNIFORM_BUFFER, { - ga::Mat( - ga::Vec(1.f / 4 / ar, 0, 0, 0), - ga::Vec(0, 0, 1.f / 10, 0), - ga::Vec(0, 1.f / 4, 0, 0), - ga::Vec(0, 0, 0, 1.f)), - - ga::Mat( - ga::Vec(c, 0, 0, s), - ga::Vec(0, c_, s_, 0), - ga::Vec(0, -s_, c_, 0), - ga::Vec(-s, 0, 0, c) - ) - }, GL_STREAM_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); } void render(GLFWwindow *window, float dt, int frame) { - int w, h; - glfwGetFramebufferSize(window, &w, &h); - glViewport(0, 0, w, h); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glUseProgram(prog); - glBindVertexArray(vao); - glEnable(GL_DEPTH_TEST); - glPointSize(5); - glLineWidth(5); - glDrawArrays(GL_POINTS, 0, (unsigned) circles.size()); - glBindVertexArray(0); - glUseProgram(0); - - glFinish(); - glfwSwapBuffers(window); } - void deinit(GLFWwindow *window) { + void update(GLFWwindow *window, float dt, int frame) { + } }; -void run() { +void run(State *state, const std::string &title) { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - auto window = glfwCreateWindow(1280, 720, "Hopf Fibration", nullptr, nullptr); + auto window = glfwCreateWindow(1280, 720, title.c_str(), nullptr, nullptr); if (!window) { glfwTerminate(); exit(EXIT_FAILURE); @@ -258,7 +41,7 @@ void run() { gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); glfwSwapInterval(0); - auto state = State(window); + state->init(window); double time = glfwGetTime(); int frame = 0; @@ -266,8 +49,8 @@ void run() { double time_ = glfwGetTime(); auto dt = (float) (time_ - time); - state.update(window, dt, frame); - state.render(window, dt, frame); + state->update(window, dt, frame); + state->render(window, dt, frame); glfwPollEvents(); @@ -275,7 +58,7 @@ void run() { frame += 1; } - state.deinit(window); + state->deinit(window); glfwDestroyWindow(window); } @@ -285,8 +68,11 @@ int main() { return EXIT_FAILURE; } - run(); + auto *state = new State(); + run(state, "Hopf Fibration"); + delete state; glfwTerminate(); + return EXIT_SUCCESS; -} \ No newline at end of file +} diff --git a/vendor/glm b/vendor/glm new file mode 160000 index 0000000..7590260 --- /dev/null +++ b/vendor/glm @@ -0,0 +1 @@ +Subproject commit 7590260cf81f3e49f492e992f60dd88cd3265d14