mirror of
git://windcorp.ru/ProgressiaTexturePreviewer.git
synced 2025-04-21 14:40:45 +03:00
821 lines
20 KiB
C++
821 lines
20 KiB
C++
#include <vector>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
#include <glad/gl.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include <glm/ext.hpp>
|
|
|
|
#define STBI_ONLY_PNG
|
|
#include <stb/stb_image.h>
|
|
|
|
constexpr const char *NAME = "Progressia Texture Previewer";
|
|
constexpr const char *VERSION = "1.0";
|
|
|
|
void load_textures(int argc, char **argv);
|
|
void create_window();
|
|
void load_opengl();
|
|
void display_window();
|
|
void main_loop();
|
|
|
|
std::string programName;
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
programName = argv[0];
|
|
|
|
load_textures(argc, argv);
|
|
create_window();
|
|
load_opengl();
|
|
display_window();
|
|
main_loop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
class Texture {
|
|
private:
|
|
|
|
std::string name;
|
|
int width, height;
|
|
|
|
GLvoid *data;
|
|
GLuint gl_id;
|
|
|
|
public:
|
|
|
|
Texture(const std::string &name) :
|
|
name(name),
|
|
data(NULL),
|
|
gl_id(-1)
|
|
{}
|
|
|
|
Texture(const Texture&) = delete;
|
|
Texture& operator=(const Texture&) = delete;
|
|
|
|
void load_opengl();
|
|
void unload_opengl();
|
|
|
|
bool hasData() const {
|
|
return data != NULL;
|
|
}
|
|
|
|
bool hasID() const {
|
|
return gl_id != -1;
|
|
}
|
|
|
|
GLuint getId() const {
|
|
return gl_id;
|
|
}
|
|
|
|
|
|
void load_stb() {
|
|
int channels;
|
|
data = stbi_load(name.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
|
|
|
if (!hasData()) {
|
|
std::cerr << programName << ": Could not load image due to format or IO error: " << name << std::endl;
|
|
return;
|
|
}
|
|
|
|
std::cout << "Loaded image " << name << std::endl;
|
|
}
|
|
|
|
void unload_stb() {
|
|
if (hasData()) {
|
|
std::cout << "Freeing STB data for " << name << std::endl;
|
|
stbi_image_free(data);
|
|
data = NULL;
|
|
}
|
|
}
|
|
|
|
~Texture() {
|
|
unload_stb();
|
|
unload_opengl();
|
|
}
|
|
};
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<Texture>> LOADED_TEXTURES;
|
|
bool loadTexturesIntoOpenGLWhenLoaded = false;
|
|
|
|
void load_texture(const std::string &path) {
|
|
Texture *texture = new Texture(path);
|
|
texture->load_stb();
|
|
if (!texture->hasData()) {
|
|
delete texture;
|
|
return;
|
|
}
|
|
|
|
LOADED_TEXTURES.emplace_back(texture);
|
|
|
|
if (loadTexturesIntoOpenGLWhenLoaded) {
|
|
texture->load_opengl();
|
|
}
|
|
}
|
|
|
|
void unload_textures();
|
|
|
|
void load_textures(int argc, char **argv) {
|
|
|
|
std::vector<std::string> textures;
|
|
|
|
for (size_t i = 0; i < argc - 1; ++i) {
|
|
textures.emplace_back(argv[i + 1]);
|
|
|
|
if (textures.at(i) == "--help") {
|
|
std::cout << NAME << " version " << VERSION << std::endl;
|
|
std::cout <<
|
|
"Usage: " << programName << " [PATH... | --help | --version]\n"
|
|
" PATH adds a texture specified by PATH to the list of displayed textures\n"
|
|
" --help displays this message and exits\n"
|
|
" --version displays version information and exits"
|
|
<< std::endl;
|
|
std::exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
if (textures.at(i) == "--version") {
|
|
std::cout << NAME << " version " << VERSION << std::endl;
|
|
std::exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
std::for_each(textures.begin(), textures.end(), &load_texture);
|
|
std::cout << "Loaded " << LOADED_TEXTURES.size() << " images" << std::endl;
|
|
|
|
}
|
|
|
|
void unload_textures() {
|
|
LOADED_TEXTURES.clear();
|
|
}
|
|
|
|
|
|
|
|
GLFWwindow *window;
|
|
|
|
enum MODE {
|
|
BLOCK, PLANE
|
|
} currentMode = BLOCK;
|
|
enum CAMERA {
|
|
ANIMATED, ISOMETRIC
|
|
} currentCamera = ANIMATED;
|
|
int selection = 0;
|
|
bool light_theme = true;
|
|
|
|
int width, height;
|
|
|
|
void on_glfw_error(int errorCode, const char *description);
|
|
void glfw_shutdown_hook();
|
|
|
|
void on_key(GLFWwindow* window, int key, int scancode, int action, int mods);
|
|
void on_drop(GLFWwindow* window, int count, const char** paths);
|
|
|
|
void create_window() {
|
|
glfwSetErrorCallback(&on_glfw_error);
|
|
|
|
if (!glfwInit()) {
|
|
std::cerr << programName << ": could not initialize GLFW" << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
std::atexit(&glfw_shutdown_hook);
|
|
std::cout << "GLFW initialized" << std::endl;
|
|
|
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
|
glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
|
|
glfwWindowHint(GLFW_MAXIMIZED, GLFW_FALSE);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
|
|
|
glfwWindowHint(GLFW_SAMPLES, 4);
|
|
|
|
window = glfwCreateWindow(800, 600, NAME, NULL, NULL);
|
|
|
|
glfwSetKeyCallback(window, &on_key);
|
|
glfwSetDropCallback(window, &on_drop);
|
|
|
|
if (window == nullptr) {
|
|
std::cerr << programName << ": could not create window" << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void on_glfw_error(int errorCode, const char *description) {
|
|
std::cerr << programName << ": GLFW has failed: (" << errorCode << ") " << description << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void glfw_shutdown_hook() {
|
|
glfwTerminate();
|
|
std::cout << "GLFW terminated" << std::endl;
|
|
}
|
|
|
|
void switch_mode();
|
|
void switch_camera();
|
|
void switch_theme();
|
|
void change_texture(int direction);
|
|
void close_texture();
|
|
|
|
void on_key(GLFWwindow*, int key, int, int action, int mods) {
|
|
if (action != GLFW_PRESS) return;
|
|
|
|
switch (key) {
|
|
case GLFW_KEY_SPACE:
|
|
if ((mods & GLFW_MOD_SHIFT) != 0) {
|
|
switch_theme();
|
|
} else {
|
|
switch_mode();
|
|
}
|
|
return;
|
|
case GLFW_KEY_LEFT:
|
|
change_texture(-1);
|
|
return;
|
|
case GLFW_KEY_RIGHT:
|
|
change_texture(+1);
|
|
return;
|
|
case GLFW_KEY_DELETE:
|
|
close_texture();
|
|
return;
|
|
case GLFW_KEY_TAB:
|
|
switch_camera();
|
|
return;
|
|
default:
|
|
// Do nothing
|
|
break;
|
|
}
|
|
}
|
|
|
|
void on_drop(GLFWwindow*, int count, const char** paths) {
|
|
for (size_t i = 0; i < count; i++) {
|
|
load_texture(paths[i]);
|
|
}
|
|
}
|
|
|
|
|
|
void switch_mode() {
|
|
switch (currentMode) {
|
|
case BLOCK:
|
|
currentMode = PLANE;
|
|
break;
|
|
case PLANE:
|
|
currentMode = BLOCK;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void switch_camera() {
|
|
switch (currentCamera) {
|
|
case ANIMATED:
|
|
currentCamera = ISOMETRIC;
|
|
break;
|
|
case ISOMETRIC:
|
|
currentCamera = ANIMATED;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void switch_theme() {
|
|
light_theme = !light_theme;
|
|
}
|
|
|
|
void change_texture(int direction) {
|
|
if (LOADED_TEXTURES.size() < 2) return;
|
|
selection += direction;
|
|
}
|
|
|
|
void close_texture() {
|
|
if (LOADED_TEXTURES.empty()) return;
|
|
LOADED_TEXTURES.erase(LOADED_TEXTURES.begin() + selection);
|
|
selection -= 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
GLuint program;
|
|
GLint attrib_coords;
|
|
GLint attrib_textureCoords;
|
|
GLint attrib_color;
|
|
GLint uniform_tranform;
|
|
GLint uniform_useTexture;
|
|
|
|
void unload_opengl();
|
|
void check_opengl();
|
|
void load_shaders();
|
|
void load_model();
|
|
|
|
void load_opengl() {
|
|
glfwMakeContextCurrent(window);
|
|
gladLoadGL(glfwGetProcAddress);
|
|
|
|
glfwSwapInterval(1);
|
|
|
|
std::atexit(&unload_opengl);
|
|
|
|
load_shaders();
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
check_opengl();
|
|
std::cout << "OpenGL initialized" << std::endl;
|
|
}
|
|
|
|
enum VariableType {
|
|
ATTRIBUTE, UNIFORM
|
|
};
|
|
GLint find_shader_variable(const char *name, VariableType);
|
|
|
|
enum LogType {
|
|
SHADER, PROGRAM
|
|
};
|
|
void log_shader_error(GLuint id, LogType);
|
|
|
|
void load_shaders() {
|
|
GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;
|
|
|
|
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
|
const char *vs_source =
|
|
R"(#version 120
|
|
|
|
attribute vec3 coords;
|
|
attribute vec2 textureCoords;
|
|
attribute vec3 color;
|
|
|
|
uniform mat4 transform;
|
|
|
|
varying vec2 textureCoords_var;
|
|
varying vec3 color_var;
|
|
|
|
void main(void) {
|
|
gl_Position = transform * vec4(coords, 1.0);
|
|
color_var = color;
|
|
textureCoords_var = textureCoords;
|
|
})";
|
|
glShaderSource(vs, 1, &vs_source, NULL);
|
|
glCompileShader(vs);
|
|
glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok);
|
|
if (!compile_ok) {
|
|
log_shader_error(vs, SHADER);
|
|
std::cerr << programName << ": Error in vertex shader" << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
|
const char *fs_source =
|
|
R"(#version 120
|
|
|
|
varying vec2 textureCoords_var;
|
|
varying vec3 color_var;
|
|
uniform bool useTexture;
|
|
|
|
uniform sampler2D texture;
|
|
|
|
void main(void) {
|
|
if (useTexture) {
|
|
gl_FragColor = vec4(color_var, 1.0) * texture2D(texture, textureCoords_var);
|
|
} else {
|
|
gl_FragColor = vec4(color_var, 1.0);
|
|
}
|
|
})";
|
|
glShaderSource(fs, 1, &fs_source, NULL);
|
|
glCompileShader(fs);
|
|
glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok);
|
|
if (!compile_ok) {
|
|
log_shader_error(fs, SHADER);
|
|
std::cerr << programName << ": Error in fragment shader" << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
program = glCreateProgram();
|
|
glAttachShader(program, vs);
|
|
glAttachShader(program, fs);
|
|
glLinkProgram(program);
|
|
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
|
|
if (!link_ok) {
|
|
log_shader_error(program, SHADER);
|
|
std::cerr << programName << ": Could not link shaders" << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
attrib_coords = find_shader_variable("coords", ATTRIBUTE);
|
|
attrib_textureCoords = find_shader_variable("textureCoords", ATTRIBUTE);
|
|
attrib_color = find_shader_variable("color", ATTRIBUTE);
|
|
uniform_tranform = find_shader_variable("transform", UNIFORM);
|
|
uniform_useTexture = find_shader_variable("useTexture", UNIFORM);
|
|
|
|
glUseProgram(program);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glUniform1i(find_shader_variable("texture", UNIFORM), 0);
|
|
|
|
for (auto &texture : LOADED_TEXTURES) {
|
|
texture->load_opengl();
|
|
}
|
|
loadTexturesIntoOpenGLWhenLoaded = true;
|
|
|
|
check_opengl();
|
|
}
|
|
|
|
GLint find_shader_variable(const char *name, VariableType type) {
|
|
GLint result = (type == ATTRIBUTE ? glGetAttribLocation : glGetUniformLocation)(program, name);
|
|
if (result < 0) {
|
|
std::cerr << programName << ": Could not find " << (type == ATTRIBUTE ? "attribute " : "uniform ") << name << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void log_shader_error(GLuint id, LogType type) {
|
|
GLsizei logLength;
|
|
(type == SHADER ? glGetShaderiv : glGetProgramiv)(id, GL_INFO_LOG_LENGTH, &logLength);
|
|
GLchar *log = new GLchar[logLength];
|
|
(type == SHADER ? glGetShaderInfoLog : glGetProgramInfoLog)(id, logLength, NULL, log);
|
|
std::cerr << programName << ": OpenGL:\n" << log << std::endl;
|
|
delete[] log;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void unload_opengl() {
|
|
if (glIsProgram(program)) glDeleteProgram(program);
|
|
std::cout << "OpenGL terminated" << std::endl;
|
|
}
|
|
|
|
void check_opengl() {
|
|
GLenum error = glGetError();
|
|
if (error != GL_NO_ERROR) {
|
|
std::cerr << programName << ": OpenGL error " << std::hex << error << std::endl;
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void Texture::load_opengl() {
|
|
if (hasData() && !hasID()) {
|
|
|
|
glGenTextures(1, &gl_id);
|
|
glBindTexture(GL_TEXTURE_2D, gl_id);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGBA,
|
|
width,
|
|
height,
|
|
0,
|
|
GL_RGBA,
|
|
GL_UNSIGNED_BYTE,
|
|
data
|
|
);
|
|
check_opengl();
|
|
|
|
std::cout << "Loaded into OpenGL " << name << std::endl;
|
|
|
|
unload_stb();
|
|
|
|
}
|
|
}
|
|
|
|
void Texture::unload_opengl() {
|
|
if (hasID()) {
|
|
glDeleteTextures(1, &gl_id);
|
|
gl_id = -1;
|
|
|
|
std::cout << "Unloaded from OpenGL " << name << std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void display_window() {
|
|
glfwShowWindow(window);
|
|
}
|
|
|
|
|
|
|
|
void draw_background();
|
|
void draw_object();
|
|
void draw_block();
|
|
void draw_plane();
|
|
|
|
void bind_coords(const GLfloat*);
|
|
void bind_color(const GLfloat*);
|
|
void bind_texture_coords(const GLfloat*);
|
|
void set_texture(const Texture&);
|
|
void set_use_texture(bool);
|
|
void set_transform(const glm::mat4&);
|
|
|
|
void main_loop() {
|
|
|
|
while (!glfwWindowShouldClose(window)) {
|
|
|
|
glfwGetFramebufferSize(window, &width, &height);
|
|
glViewport(0, 0, width, height);
|
|
|
|
glEnableVertexAttribArray(attrib_coords);
|
|
glEnableVertexAttribArray(attrib_color);
|
|
glEnableVertexAttribArray(attrib_textureCoords);
|
|
|
|
draw_background();
|
|
draw_object();
|
|
|
|
glDisableVertexAttribArray(attrib_textureCoords);
|
|
glDisableVertexAttribArray(attrib_color);
|
|
glDisableVertexAttribArray(attrib_coords);
|
|
|
|
check_opengl();
|
|
|
|
glfwSwapBuffers(window);
|
|
glfwPollEvents();
|
|
|
|
}
|
|
}
|
|
|
|
namespace background {
|
|
constexpr const GLfloat COORDS[] = {
|
|
-1.0, -1.0, 0.0,
|
|
-1.0, +1.0, 0.0,
|
|
+1.0, +1.0, 0.0,
|
|
+1.0, -1.0, 0.0,
|
|
};
|
|
|
|
constexpr const GLfloat COLORS_LIGHT[] = {
|
|
+0.80, +0.80, +0.85,
|
|
+0.95, +0.95, +1.00,
|
|
+0.95, +0.95, +1.00,
|
|
+0.80, +0.80, +0.85,
|
|
};
|
|
|
|
constexpr const GLfloat COLORS_DARK[] = {
|
|
+0.1, +0.1, +0.15,
|
|
+0.2, +0.2, +0.25,
|
|
+0.2, +0.2, +0.25,
|
|
+0.1, +0.1, +0.15,
|
|
};
|
|
}
|
|
|
|
namespace block {
|
|
constexpr const GLfloat COORDS[] = {
|
|
// front
|
|
-1.0, -1.0, 1.0,
|
|
1.0, -1.0, 1.0,
|
|
1.0, 1.0, 1.0,
|
|
-1.0, 1.0, 1.0,
|
|
// top
|
|
-1.0, 1.0, 1.0,
|
|
1.0, 1.0, 1.0,
|
|
1.0, 1.0, -1.0,
|
|
-1.0, 1.0, -1.0,
|
|
// back
|
|
1.0, -1.0, -1.0,
|
|
-1.0, -1.0, -1.0,
|
|
-1.0, 1.0, -1.0,
|
|
1.0, 1.0, -1.0,
|
|
// bottom
|
|
-1.0, -1.0, -1.0,
|
|
1.0, -1.0, -1.0,
|
|
1.0, -1.0, 1.0,
|
|
-1.0, -1.0, 1.0,
|
|
// left
|
|
-1.0, -1.0, -1.0,
|
|
-1.0, -1.0, 1.0,
|
|
-1.0, 1.0, 1.0,
|
|
-1.0, 1.0, -1.0,
|
|
// right
|
|
1.0, -1.0, 1.0,
|
|
1.0, -1.0, -1.0,
|
|
1.0, 1.0, -1.0,
|
|
1.0, 1.0, 1.0,
|
|
};
|
|
|
|
constexpr const GLfloat COLORS[] = {
|
|
// front
|
|
0.9, 0.9, 0.9,
|
|
0.9, 0.9, 0.9,
|
|
0.9, 0.9, 0.9,
|
|
0.9, 0.9, 0.9,
|
|
// top
|
|
1.0, 1.0, 1.0,
|
|
1.0, 1.0, 1.0,
|
|
1.0, 1.0, 1.0,
|
|
1.0, 1.0, 1.0,
|
|
// back
|
|
0.6, 0.6, 0.6,
|
|
0.6, 0.6, 0.6,
|
|
0.6, 0.6, 0.6,
|
|
0.6, 0.6, 0.6,
|
|
// bottom
|
|
0.4, 0.4, 0.4,
|
|
0.4, 0.4, 0.4,
|
|
0.4, 0.4, 0.4,
|
|
0.4, 0.4, 0.4,
|
|
// left
|
|
0.8, 0.8, 0.8,
|
|
0.8, 0.8, 0.8,
|
|
0.8, 0.8, 0.8,
|
|
0.8, 0.8, 0.8,
|
|
// right
|
|
0.7, 0.7, 0.7,
|
|
0.7, 0.7, 0.7,
|
|
0.7, 0.7, 0.7,
|
|
0.7, 0.7, 0.7,
|
|
};
|
|
|
|
constexpr const GLfloat TEX_COORDS[] = {
|
|
// front
|
|
0.0, 0.0,
|
|
1.0, 0.0,
|
|
1.0, 1.0,
|
|
0.0, 1.0,
|
|
// top
|
|
0.0, 0.0,
|
|
1.0, 0.0,
|
|
1.0, 1.0,
|
|
0.0, 1.0,
|
|
// back
|
|
0.0, 0.0,
|
|
1.0, 0.0,
|
|
1.0, 1.0,
|
|
0.0, 1.0,
|
|
// bottom
|
|
0.0, 0.0,
|
|
1.0, 0.0,
|
|
1.0, 1.0,
|
|
0.0, 1.0,
|
|
// left
|
|
0.0, 0.0,
|
|
1.0, 0.0,
|
|
1.0, 1.0,
|
|
0.0, 1.0,
|
|
// right
|
|
0.0, 0.0,
|
|
1.0, 0.0,
|
|
1.0, 1.0,
|
|
0.0, 1.0,
|
|
};
|
|
}
|
|
|
|
namespace plane {
|
|
constexpr const GLfloat COORDS[] = {
|
|
-1.0, -1.0, 0.0,
|
|
-1.0, +1.0, 0.0,
|
|
+1.0, +1.0, 0.0,
|
|
+1.0, -1.0, 0.0,
|
|
};
|
|
|
|
constexpr const GLfloat COLORS[] = {
|
|
+1.0, +1.0, +1.0,
|
|
+1.0, +1.0, +1.0,
|
|
+1.0, +1.0, +1.0,
|
|
+1.0, +1.0, +1.0,
|
|
};
|
|
|
|
constexpr const GLfloat TEX_COORDS[] = {
|
|
-3.0, -3.0,
|
|
-3.0, +3.0,
|
|
+3.0, +3.0,
|
|
+3.0, -3.0,
|
|
};
|
|
}
|
|
|
|
void draw_background() {
|
|
bind_coords(background::COORDS);
|
|
bind_color(light_theme ? background::COLORS_LIGHT : background::COLORS_DARK);
|
|
set_transform(glm::identity<glm::mat4>());
|
|
set_use_texture(false);
|
|
glDrawArrays(GL_QUADS, 0, 4);
|
|
}
|
|
|
|
void draw_object() {
|
|
if (LOADED_TEXTURES.empty()) {
|
|
// Do nothing
|
|
return;
|
|
}
|
|
|
|
if (selection < 0) selection = LOADED_TEXTURES.size() - 1;
|
|
if (selection >= LOADED_TEXTURES.size()) selection = 0;
|
|
|
|
set_texture(*(LOADED_TEXTURES[selection]));
|
|
|
|
switch (currentMode) {
|
|
case BLOCK:
|
|
draw_block();
|
|
return;
|
|
case PLANE:
|
|
draw_plane();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void draw_block() {
|
|
glEnable(GL_CULL_FACE);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
bind_coords(block::COORDS);
|
|
bind_color(block::COLORS);
|
|
bind_texture_coords(block::TEX_COORDS);
|
|
|
|
GLfloat aspectRatio = static_cast<GLfloat>(width) / height;
|
|
|
|
glm::mat4 transform = glm::identity<glm::mat4>();
|
|
transform = glm::scale(transform, glm::vec3(
|
|
std::min(1.0f, 1.0f / aspectRatio),
|
|
std::min(1.0f, aspectRatio),
|
|
1.0f
|
|
));
|
|
|
|
switch (currentCamera) {
|
|
case ANIMATED:
|
|
{
|
|
float t = static_cast<float>(glfwGetTime()) / 20;
|
|
|
|
transform = glm::rotate(transform, t * 3, glm::vec3(1, 0, 0));
|
|
transform = glm::rotate(transform, t * 7, glm::vec3(0, 1, 0));
|
|
transform = glm::rotate(transform, t * 11, glm::vec3(0, 0, 1));
|
|
}
|
|
break;
|
|
case ISOMETRIC:
|
|
constexpr const float SQRT_2 = 1.41421356237309504880168872420969808;
|
|
constexpr const float SQRT_3 = 1.73205080756887729352744634150587236;
|
|
constexpr const float SQRT_6 = SQRT_2 * SQRT_3;
|
|
|
|
transform *= glm::mat4(
|
|
|
|
1 / SQRT_2, 0, -1 / SQRT_2, 0,
|
|
1 / SQRT_6, SQRT_2 / SQRT_3, 1 / SQRT_6, 0,
|
|
1 / SQRT_3, -1 / SQRT_3, 1 / SQRT_3, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
break;
|
|
}
|
|
|
|
transform = glm::scale(transform, glm::vec3(0.5));
|
|
|
|
set_transform(transform);
|
|
|
|
set_use_texture(true);
|
|
glDrawArrays(GL_QUADS, 0, 4*6);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_CULL_FACE);
|
|
}
|
|
|
|
void draw_plane() {
|
|
bind_coords(plane::COORDS);
|
|
bind_color(plane::COLORS);
|
|
bind_texture_coords(plane::TEX_COORDS);
|
|
|
|
GLfloat aspectRatio = static_cast<GLfloat>(width) / height;
|
|
set_transform(glm::scale(glm::identity<glm::mat4>(), glm::vec3(
|
|
std::max(1.0f, 1.0f / aspectRatio),
|
|
std::max(1.0f, aspectRatio),
|
|
1.0f
|
|
)));
|
|
|
|
set_use_texture(true);
|
|
glDrawArrays(GL_QUADS, 0, 4);
|
|
}
|
|
|
|
void bind_coords(const GLfloat *data) {
|
|
glVertexAttribPointer(
|
|
attrib_coords, 3, GL_FLOAT, GL_FALSE, 0,
|
|
data
|
|
);
|
|
}
|
|
|
|
void bind_color(const GLfloat *data) {
|
|
glVertexAttribPointer(
|
|
attrib_color, 3, GL_FLOAT, GL_FALSE, 0,
|
|
data
|
|
);
|
|
}
|
|
|
|
void bind_texture_coords(const GLfloat *data) {
|
|
glVertexAttribPointer(
|
|
attrib_textureCoords, 2, GL_FLOAT, GL_FALSE, 0,
|
|
data
|
|
);
|
|
}
|
|
|
|
void set_texture(const Texture &texture) {
|
|
glBindTexture(GL_TEXTURE_2D, texture.getId());
|
|
}
|
|
|
|
void set_use_texture(bool use) {
|
|
glUniform1i(uniform_useTexture, use ? 1 : 0);
|
|
}
|
|
|
|
void set_transform(const glm::mat4 &m) {
|
|
glUniformMatrix4fv(uniform_tranform, 1, false, glm::value_ptr(m));
|
|
}
|