simplify template
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -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
|
||||
|
||||
1
.idea/.name
generated
1
.idea/.name
generated
@@ -1 +0,0 @@
|
||||
hopf
|
||||
@@ -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)
|
||||
@@ -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})
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
18
main/include/util.h
Normal file
18
main/include/util.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by allem on 2/7/2019.
|
||||
//
|
||||
|
||||
#ifndef HOPF_FIBRATION_UTIL_H
|
||||
#define HOPF_FIBRATION_UTIL_H
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
void hello() {
|
||||
printf("Hello there.\n");
|
||||
}
|
||||
|
||||
void general() {
|
||||
printf("General Kenobi.\n");
|
||||
}
|
||||
|
||||
#endif //HOPF_FIBRATION_UTIL_H
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,254 +1,37 @@
|
||||
//
|
||||
// Created by allem on 2/7/2019.
|
||||
//
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "glga.hpp"
|
||||
|
||||
#define PI 3.14159f
|
||||
|
||||
namespace util {
|
||||
template<typename T>
|
||||
void bufferData(GLenum target, std::vector<T> data, GLenum usage) {
|
||||
glBufferData(target, data.size() * sizeof(T), &data.front(), usage);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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<std::streamsize>::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<std::string> &paths) {
|
||||
std::vector<std::string> strs;
|
||||
std::vector<const char *> 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<std::string> 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<GLuint> 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 <cstdlib>
|
||||
#include <string>
|
||||
|
||||
struct State {
|
||||
GLuint vao{};
|
||||
GLuint vbo{}, ubo{};
|
||||
GLuint ubo_bp = 1;
|
||||
void deinit(GLFWwindow *window) {
|
||||
|
||||
GLuint prog{};
|
||||
|
||||
std::vector<HopfCircle> 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<ga::Mat>(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;
|
||||
}
|
||||
}
|
||||
|
||||
1
vendor/glm
vendored
Submodule
1
vendor/glm
vendored
Submodule
Submodule vendor/glm added at 7590260cf8
Reference in New Issue
Block a user