This commit is contained in:
2019-01-11 23:24:46 -05:00
commit d533139d1f
11 changed files with 521 additions and 0 deletions

151
.gitignore vendored Normal file
View File

@@ -0,0 +1,151 @@
# Created by .ignore support plugin (hsz.mobi)
### C template
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
### CMake template
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/dictionaries
.idea/**/shelf
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
cmake-build-release/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
### C++ template
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app

7
.gitmodules vendored Normal file
View File

@@ -0,0 +1,7 @@
[submodule "vendor/glfw"]
path = vendor/glfw
url = https://github.com/glfw/glfw.git
[submodule "vendor/glad"]
path = vendor/glad
url = https://github.com/Dav1dde/glad.git
branch = c

6
.idea/vcs.xml generated Normal file
View 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>

14
CMakeLists.txt Normal file
View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.10)
project(main)
set(CMAKE_CXX_STANDARD 17)
add_library(glad vendor/glad/src/glad.c)
target_include_directories(glad PUBLIC vendor/glad/include)
option(GLFW_BUILD_DOCS OFF)
option(GLFW_BUILD_EXAMPLES OFF)
option(GLFW_BUILD_TESTS OFF)
add_subdirectory(vendor/glfw)
add_subdirectory(main)

29
main/CMakeLists.txt Normal file
View File

@@ -0,0 +1,29 @@
project(main)
add_executable(${PROJECT_NAME}
src/main.cpp)
target_link_libraries(${PROJECT_NAME}
glad
glfw)
target_include_directories(${PROJECT_NAME}
PRIVATE include)
set(SHADERS
shaders/main.frag
shaders/main.vert)
add_custom_target(shaders DEPENDS ${SHADERS})
add_custom_command(
TARGET shaders PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/shaders/
COMMENT "clearing shaders"
)
add_custom_command(
TARGET shaders POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/shaders/ ${CMAKE_CURRENT_BINARY_DIR}/shaders/
COMMENT "copying shaders"
)
add_dependencies(${PROJECT_NAME} shaders)

7
main/shaders/main.frag Normal file
View File

@@ -0,0 +1,7 @@
#version 440
out vec4 color;
void main() {
color = vec4(1);
}

31
main/shaders/main.geom Normal file
View File

@@ -0,0 +1,31 @@
#version 440
#define CIRCLE_RES 256
#define PI 3.14159
layout(points) in;
layout(line_strip, max_vertices=CIRCLE_RES) out;
in float xi_[];
in float eta_[];
layout(binding=1) uniform Matrices {
mat4 proj;
};
void main(){
for(int k = 0; k <= CIRCLE_RES; k++) {
vec2 xi = vec2(xi_[0], 4 * PI * k / CIRCLE_RES);
float eta = eta_[0];
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);
vec4 pos = vec4(x / (1 - w), y / (1 - w), z / (1 - w), 1);
gl_Position = proj * pos;
EmitVertex();
}
}

12
main/shaders/main.vert Normal file
View File

@@ -0,0 +1,12 @@
#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;
}

262
main/src/main.cpp Normal file
View File

@@ -0,0 +1,262 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#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;
float eta;
};
struct State {
GLuint vao{};
GLuint vbo{}, ubo{};
GLuint ubo_bp = 1;
GLuint prog{};
std::vector<HopfCircle> circles{};
explicit State(GLFWwindow *window) {
const int N = 32;
for (int k = 0; k < N; ++k) {
circles.push_back({2 * PI * k / N, 0.025});
circles.push_back({2 * PI * k / N, PI / 2 - 0.025});
circles.push_back({2 * PI * k / N, 0.3f});
circles.push_back({2 * PI * k / N, 0.4f});
circles.push_back({2 * PI * k / N, 0.5f});
circles.push_back({2 * PI * k / N, 1.1f});
circles.push_back({2 * PI * k / N, 1.2f});
circles.push_back({2 * PI * k / N, 1.3f});
}
printf("vendor: %s\nrenderer: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
glGenBuffers(1, &vbo);
glGenBuffers(1, &ubo);
glGenVertexArrays(1, &vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
util::bufferData<HopfCircle>(GL_ARRAY_BUFFER, circles, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
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;
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
util::bufferData<float>(GL_UNIFORM_BUFFER, {
1.f / 4 / ar, 0, 0, 0,
0, 0, 1.f / 10, 0,
0, 1.f / 4, 0, 0,
0, 0, 0, 1
}, 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);
glUseProgram(prog);
glBindVertexArray(vao);
glPointSize(5);
glLineWidth(3);
glDrawArrays(GL_POINTS, 0, (unsigned) circles.size());
glBindVertexArray(0);
glUseProgram(0);
glFinish();
glfwSwapBuffers(window);
}
void deinit(GLFWwindow *window) {
}
};
void run() {
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);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(0);
auto state = State(window);
double time = glfwGetTime();
int frame = 0;
while (!glfwWindowShouldClose(window)) {
double time_ = glfwGetTime();
auto dt = (float) (time_ - time);
state.update(window, dt, frame);
state.render(window, dt, frame);
glfwPollEvents();
time = time_;
frame += 1;
}
state.deinit(window);
glfwDestroyWindow(window);
}
int main() {
if (!glfwInit()) {
return EXIT_FAILURE;
}
run();
glfwTerminate();
return EXIT_SUCCESS;
}

1
vendor/glad vendored Submodule

Submodule vendor/glad added at 5bf3eda6da

1
vendor/glfw vendored Submodule

Submodule vendor/glfw added at 72c3908e14