Compare commits
9 Commits
fetchconte
...
torus
| Author | SHA1 | Date | |
|---|---|---|---|
| 2062f19631 | |||
| 16a5e403ce | |||
| f101bba5aa | |||
| 3263c7e45e | |||
| b504bf0222 | |||
| b274251501 | |||
| 421caed141 | |||
| 1bf3c556bd | |||
| e0ec2bf7e1 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -147,6 +147,4 @@ fabric.properties
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
.idea/
|
||||
*.app
|
||||
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
|
||||
|
||||
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||
</project>
|
||||
2
.idea/hopf-fibration.iml
generated
Normal file
2
.idea/hopf-fibration.iml
generated
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
||||
12
.idea/misc.xml
generated
Normal file
12
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
<component name="CidrRootsConfiguration">
|
||||
<sourceRoots>
|
||||
<file path="$PROJECT_DIR$/main" />
|
||||
</sourceRoots>
|
||||
<libraryRoots>
|
||||
<file path="$PROJECT_DIR$/vendor" />
|
||||
</libraryRoots>
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/hopf-fibration.iml" filepath="$PROJECT_DIR$/.idea/hopf-fibration.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
113
main/include/util.h
Normal file
113
main/include/util.h
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Created by allem on 2/7/2019.
|
||||
//
|
||||
|
||||
#ifndef HOPF_FIBRATION_UTIL_H
|
||||
#define HOPF_FIBRATION_UTIL_H
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //HOPF_FIBRATION_UTIL_H
|
||||
@@ -1,17 +1,12 @@
|
||||
#version 440
|
||||
|
||||
#define PI 3.14159
|
||||
|
||||
in vec4 pos;
|
||||
in vec4 pos4;
|
||||
in vec4 pos3;
|
||||
layout(binding=1) uniform Unifs {
|
||||
mat4 uProj;
|
||||
vec4 uColor;
|
||||
};
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main() {
|
||||
float light = -pos3.y / 10 + .5;
|
||||
|
||||
vec3 col = vec3(1);
|
||||
|
||||
color = vec4(col * light, 1);
|
||||
color = uColor;
|
||||
}
|
||||
@@ -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 +1,12 @@
|
||||
#version 440
|
||||
|
||||
layout(location=0) in float xi;
|
||||
layout(location=1) in float eta;
|
||||
layout(binding=1) uniform Unifs {
|
||||
mat4 uProj;
|
||||
vec4 uColor;
|
||||
};
|
||||
|
||||
out float xi_;
|
||||
out float eta_;
|
||||
in vec4 iPos;
|
||||
|
||||
void main(){
|
||||
xi_ = xi;
|
||||
eta_ = eta;
|
||||
gl_Position = uProj * vec4(iPos.xyz, 1);
|
||||
}
|
||||
@@ -1,254 +1,319 @@
|
||||
//
|
||||
// Created by allem on 2/7/2019.
|
||||
//
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#define GLM_FORCE_SWIZZLE
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "glga.hpp"
|
||||
#include "util.h"
|
||||
|
||||
#define PI 3.14159f
|
||||
#define RES_MAJOR 512
|
||||
#define RES_MINOR 8
|
||||
|
||||
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);
|
||||
}
|
||||
#define Z_RADIUS 10.f
|
||||
|
||||
std::string readFile(const std::string &path) {
|
||||
std::ifstream file(path);
|
||||
if (!file) return std::string();
|
||||
#define PI (float) (M_PI)
|
||||
|
||||
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) {}
|
||||
struct Unifs {
|
||||
glm::mat4 proj = glm::identity<glm::mat4>();
|
||||
glm::vec4 color = glm::vec4(1);
|
||||
};
|
||||
|
||||
struct State {
|
||||
GLuint vao{};
|
||||
GLuint vbo{}, ubo{};
|
||||
GLuint ubo_bp = 1;
|
||||
GLuint vao_wide{};
|
||||
GLuint vbo_wide{};
|
||||
GLuint ibo_wide{};
|
||||
|
||||
GLuint vao_thin{};
|
||||
GLuint vbo_thin{};
|
||||
GLuint ibo_thin{};
|
||||
|
||||
GLuint ubo{};
|
||||
|
||||
GLuint prog{};
|
||||
const GLuint UNIF_BINDING_POINT = 1;
|
||||
|
||||
std::vector<HopfCircle> circles{};
|
||||
std::vector<glm::vec4> verts_wide{};
|
||||
std::vector<unsigned> inds_wide{};
|
||||
|
||||
float t = 0;
|
||||
std::vector<glm::vec4> verts_thin{};
|
||||
std::vector<unsigned> inds_thin{};
|
||||
|
||||
void regen() {
|
||||
circles.clear();
|
||||
Unifs unifs;
|
||||
|
||||
const int N = 32;
|
||||
const int M = 4;
|
||||
const float PAD = 0.0125;
|
||||
glm::vec4 hopf(float xi, float nu, float eta) {
|
||||
return glm::vec4( // todo find parameterization given quaternion
|
||||
cos((nu + xi) / 2) * sin(eta),
|
||||
sin((nu + xi) / 2) * sin(eta),
|
||||
cos((nu - xi) / 2) * cos(eta),
|
||||
sin((nu - xi) / 2) * cos(eta)
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
glm::vec3 stereo(float xi, float nu, float eta) {
|
||||
auto h = hopf(xi, nu, eta);
|
||||
|
||||
float xw = 0.8;
|
||||
float yw = -0.1;
|
||||
float zw = 2.5;
|
||||
float xy = 0.0;
|
||||
float yz = 0.5;
|
||||
float zx = 0.0;
|
||||
|
||||
auto r = glm::mat4(
|
||||
glm::vec4(cos(xw), 0, 0, sin(xw)),
|
||||
glm::vec4(0, 1, 0, 0),
|
||||
glm::vec4(0, 0, 1, 0),
|
||||
glm::vec4(-sin(xw), 0, 0, cos(xw))
|
||||
) * glm::mat4(
|
||||
glm::vec4(1, 0, 0, 0),
|
||||
glm::vec4(0, cos(yw), 0, sin(yw)),
|
||||
glm::vec4(0, 0, 1, 0),
|
||||
glm::vec4(0, -sin(yw), 0, cos(yw))
|
||||
) * glm::mat4(
|
||||
glm::vec4(1, 0, 0, 0),
|
||||
glm::vec4(0, 1, 0, 0),
|
||||
glm::vec4(0, 0, cos(zw), sin(zw)),
|
||||
glm::vec4(0, 0, -sin(zw), cos(zw))
|
||||
) * glm::mat4(
|
||||
glm::vec4(cos(xy), sin(xy), 0, 0),
|
||||
glm::vec4(-sin(xy), cos(xy), 0, 0),
|
||||
glm::vec4(0, 0, 1, 0),
|
||||
glm::vec4(0, 0, 0, 1)
|
||||
) * glm::mat4(
|
||||
glm::vec4(1, 0, 0, 0),
|
||||
glm::vec4(0, cos(yz), sin(yz), 0),
|
||||
glm::vec4(0, -sin(yz), cos(yz), 0),
|
||||
glm::vec4(0, 0, 0, 1)
|
||||
) * glm::mat4(
|
||||
glm::vec4(cos(zx), 0, -sin(zx), 0),
|
||||
glm::vec4(0, 1, 0, 0),
|
||||
glm::vec4(sin(zx), 0, cos(zx), 0),
|
||||
glm::vec4(0, 0, 0, 1)
|
||||
);
|
||||
|
||||
auto rot = r;
|
||||
|
||||
h = rot * h;
|
||||
|
||||
auto s = h.xyz() / (1 - h.w);
|
||||
|
||||
s /= 2;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
add_ring(std::vector<glm::vec4> &dest_verts, std::vector<unsigned> &dest_inds, float xi, float eta, float rad) {
|
||||
std::vector<glm::vec3> circle;
|
||||
std::vector<glm::vec3> torus;
|
||||
std::vector<unsigned> ind;
|
||||
|
||||
for (unsigned i = 0; i < RES_MAJOR; ++i) {
|
||||
auto nu = 4 * PI * i / RES_MAJOR;
|
||||
|
||||
auto v = stereo(xi, nu, eta);
|
||||
|
||||
circle.push_back(v);
|
||||
}
|
||||
|
||||
auto center = glm::vec3(0);
|
||||
for (auto v : circle) center += v;
|
||||
center /= (float) RES_MAJOR;
|
||||
|
||||
auto A = stereo(xi, 0 * PI, eta);
|
||||
auto B = stereo(xi, 1 * PI, eta);
|
||||
auto normal = glm::normalize(cross(A - center, B - center));
|
||||
|
||||
for (unsigned i = 0; i < circle.size(); ++i) {
|
||||
auto v = circle[i];
|
||||
|
||||
auto b1 = normal;
|
||||
auto b2 = glm::normalize(v - center);
|
||||
|
||||
for (int j = 0; j < RES_MINOR; ++j) {
|
||||
auto theta = 2 * PI * j / RES_MINOR;
|
||||
|
||||
auto p = v + (cos(theta) * b1 + sin(theta) * b2) * rad;
|
||||
|
||||
ind.push_back(i * RES_MINOR + j);
|
||||
ind.push_back((i + 1) * RES_MINOR + j);
|
||||
ind.push_back(i * RES_MINOR + (j + 1) % RES_MINOR);
|
||||
|
||||
ind.push_back((i + 1) * RES_MINOR + j);
|
||||
ind.push_back((i + 1) * RES_MINOR + (j + 1) % RES_MINOR);
|
||||
ind.push_back(i * RES_MINOR + (j + 1) % RES_MINOR);
|
||||
|
||||
torus.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
util::bufferData(GL_ARRAY_BUFFER, circles, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
auto offset = (unsigned) dest_verts.size();
|
||||
|
||||
for (auto v : torus)
|
||||
dest_verts.emplace_back(v, 1);
|
||||
|
||||
for (auto i : ind)
|
||||
dest_inds.push_back(offset + i % (RES_MAJOR * RES_MINOR));
|
||||
}
|
||||
|
||||
explicit State(GLFWwindow *window) {
|
||||
printf("vendor: %s\nrenderer: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
|
||||
void updateUnifs() {
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
|
||||
util::bufferData(GL_UNIFORM_BUFFER, unifs, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
glGenBuffers(1, &vbo);
|
||||
glGenBuffers(1, &ubo);
|
||||
glGenVertexArrays(1, &vao);
|
||||
void regen() {
|
||||
printf("generating\n");
|
||||
|
||||
verts_wide.clear();
|
||||
verts_thin.clear();
|
||||
inds_wide.clear();
|
||||
inds_thin.clear();
|
||||
|
||||
const float XI_R = 28;
|
||||
const float ETA_R = 5;
|
||||
const float ETA_BUF = 0;
|
||||
|
||||
for (int i = 0; i < XI_R; ++i) {
|
||||
float xi = 2 * PI * i / XI_R;
|
||||
|
||||
for (int j = 1; j <= ETA_R - 1; ++j) {
|
||||
float eta = ETA_BUF + (PI / 2 - 2 * ETA_BUF) * j / ETA_R;
|
||||
|
||||
add_ring(verts_wide, inds_wide, xi, eta, .015);
|
||||
add_ring(verts_thin, inds_thin, xi, eta, .004);
|
||||
}
|
||||
}
|
||||
|
||||
add_ring(verts_wide, inds_wide, .001f, .0f, .015);
|
||||
add_ring(verts_thin, inds_thin, .001f, .0f, .008);
|
||||
|
||||
add_ring(verts_wide, inds_wide, .001f, PI / 2 - .0f, .015);
|
||||
add_ring(verts_thin, inds_thin, .001f, PI / 2 - .0f, .008);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_thin);
|
||||
util::bufferData(GL_ARRAY_BUFFER, verts_thin, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_thin);
|
||||
util::bufferData(GL_ELEMENT_ARRAY_BUFFER, inds_thin, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_wide);
|
||||
util::bufferData(GL_ARRAY_BUFFER, verts_wide, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_wide);
|
||||
util::bufferData(GL_ELEMENT_ARRAY_BUFFER, inds_wide, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void init(GLFWwindow *window) {
|
||||
GLuint vs = util::buildShader(GL_VERTEX_SHADER, "vs", {"shaders/main.vert"});
|
||||
GLuint fs = util::buildShader(GL_FRAGMENT_SHADER, "fs", {"shaders/main.frag"});
|
||||
prog = util::buildProgram(false, "prog", {vs, fs});
|
||||
|
||||
glGenBuffers(1, &vbo_wide);
|
||||
glGenBuffers(1, &ibo_wide);
|
||||
glGenBuffers(1, &vbo_thin);
|
||||
glGenBuffers(1, &ibo_thin);
|
||||
|
||||
regen();
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, ubo_bp, ubo);
|
||||
GLint pos = glGetAttribLocation(prog, "iPos");
|
||||
|
||||
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});
|
||||
glGenBuffers(1, &ubo);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, UNIF_BINDING_POINT, ubo);
|
||||
updateUnifs();
|
||||
|
||||
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));
|
||||
glGenVertexArrays(1, &vao_wide);
|
||||
glBindVertexArray(vao_wide);
|
||||
if (pos >= 0) {
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_wide);
|
||||
glVertexAttribPointer((GLuint) pos, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), nullptr);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_wide);
|
||||
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);
|
||||
glGenVertexArrays(1, &vao_thin);
|
||||
glBindVertexArray(vao_thin);
|
||||
if (pos >= 0) {
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_thin);
|
||||
glVertexAttribPointer((GLuint) pos, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), nullptr);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_thin);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void render(GLFWwindow *window, float dt, int frame) {
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
|
||||
glViewport(0, 0, w, h);
|
||||
glClearColor(1, 1, 1, 1);
|
||||
unifs.color = glm::vec4(0, 0, 0, 1);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glUseProgram(prog);
|
||||
glBindVertexArray(vao);
|
||||
glBindVertexArray(vao_wide);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glPointSize(5);
|
||||
glLineWidth(5);
|
||||
glDrawArrays(GL_POINTS, 0, (unsigned) circles.size());
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
updateUnifs();
|
||||
glUseProgram(prog);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei) inds_wide.size(), GL_UNSIGNED_INT, 0);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBindVertexArray(vao_thin);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
updateUnifs();
|
||||
glUseProgram(prog);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei) inds_thin.size(), GL_UNSIGNED_INT, 0);
|
||||
|
||||
glFinish();
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
void deinit(GLFWwindow *window) {
|
||||
void update(GLFWwindow *window, float dt, int frame) {
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
|
||||
float ar = (float) w / (float) h;
|
||||
unifs.proj = glm::ortho(-ar, ar, -1.f, 1.f, -Z_RADIUS, Z_RADIUS);
|
||||
}
|
||||
|
||||
void deinit(GLFWwindow *window) {
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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(3840, 1249, title.c_str(), nullptr, nullptr);
|
||||
if (!window) {
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -258,7 +323,8 @@ void run() {
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
glfwSwapInterval(0);
|
||||
|
||||
auto state = State(window);
|
||||
glfwSetWindowUserPointer(window, state);
|
||||
state->init(window);
|
||||
|
||||
double time = glfwGetTime();
|
||||
int frame = 0;
|
||||
@@ -266,8 +332,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 +341,7 @@ void run() {
|
||||
frame += 1;
|
||||
}
|
||||
|
||||
state.deinit(window);
|
||||
state->deinit(window);
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
}
|
||||
@@ -285,8 +351,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