Utilities
This commit is contained in:
parent
a9454741d4
commit
7190568012
@ -1,10 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(tes-tiger)
|
project(tes-tiger)
|
||||||
include_directories(includes)
|
|
||||||
link_directories(libraries)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
include_directories(includes)
|
||||||
|
link_directories(libraries)
|
||||||
|
|
||||||
add_executable(tes-tiger
|
add_executable(tes-tiger
|
||||||
includes/boost/property_tree/ptree.hpp
|
includes/boost/property_tree/ptree.hpp
|
||||||
includes/boost/property_tree/json_parser.hpp
|
includes/boost/property_tree/json_parser.hpp
|
||||||
@ -14,7 +15,9 @@ add_executable(tes-tiger
|
|||||||
includes/SOIL/SOIL.h
|
includes/SOIL/SOIL.h
|
||||||
includes/GL/glew.h
|
includes/GL/glew.h
|
||||||
includes/GLFW/glfw3.h
|
includes/GLFW/glfw3.h
|
||||||
|
utilities.h
|
||||||
glew.c
|
glew.c
|
||||||
|
utilities.cpp
|
||||||
main.cpp)
|
main.cpp)
|
||||||
|
|
||||||
target_link_libraries(tes-tiger
|
target_link_libraries(tes-tiger
|
||||||
|
271
main.cpp
271
main.cpp
@ -1,189 +1,18 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <initializer_list>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#define GLEW_STATIC
|
#define GLEW_STATIC
|
||||||
#include "GL/glew.h"
|
#include <GL/glew.h>
|
||||||
#include "GLFW/glfw3.h"
|
#include <glm/glm.hpp>
|
||||||
#include "SOIL/SOIL.h"
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include "glm/glm.hpp"
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include "glm/gtc/matrix_transform.hpp"
|
#include <boost/property_tree/ptree.hpp>
|
||||||
#include "glm/gtc/type_ptr.hpp"
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
#include "boost/property_tree/ptree.hpp"
|
|
||||||
#include "boost/property_tree/json_parser.hpp"
|
|
||||||
|
|
||||||
const int windowWidth = 800;
|
#include "utilities.h"
|
||||||
const int windowHeight = 600;
|
|
||||||
|
|
||||||
const float pi = 3.14159f;
|
const float pi = 3.14159f;
|
||||||
|
|
||||||
std::string readFile(const std::string& filePath) {
|
|
||||||
std::ifstream file(filePath);
|
|
||||||
auto result = std::string(
|
|
||||||
std::istreambuf_iterator<char>(file),
|
|
||||||
std::istreambuf_iterator<char>()
|
|
||||||
);
|
|
||||||
file.close();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
const GLuint loadShader(const GLenum& shaderType, const std::string& shaderFilePath) {
|
|
||||||
const GLuint shader = glCreateShader(shaderType);
|
|
||||||
auto shaderSource = readFile(shaderFilePath);
|
|
||||||
auto shaderSourceC = shaderSource.c_str();
|
|
||||||
glShaderSource(shader, 1, &shaderSourceC, nullptr);
|
|
||||||
glCompileShader(shader);
|
|
||||||
GLint success;
|
|
||||||
GLchar infoLog[512];
|
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
|
||||||
if(!success) {
|
|
||||||
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
|
|
||||||
std::cout << "Failed to compile shader: " << infoLog << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
const GLuint linkShaderProgram(const std::initializer_list<std::pair<const GLenum, const std::string>>& shadersInfo) {
|
|
||||||
const GLuint shaderProgram = glCreateProgram();
|
|
||||||
for(const auto& shaderInfo: shadersInfo) {
|
|
||||||
auto shader = loadShader(shaderInfo.first, shaderInfo.second);
|
|
||||||
glAttachShader(shaderProgram, shader);
|
|
||||||
glDeleteShader(shader);
|
|
||||||
}
|
|
||||||
glLinkProgram(shaderProgram);
|
|
||||||
{
|
|
||||||
GLint success;
|
|
||||||
GLchar infoLog[512];
|
|
||||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
|
|
||||||
if(!success) {
|
|
||||||
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
|
|
||||||
std::cout << "Failed to link shader program: " << infoLog << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return shaderProgram;
|
|
||||||
}
|
|
||||||
GLuint loadTexture(const std::string& textureFilePath) {
|
|
||||||
int imageWidth, imageHeight;
|
|
||||||
unsigned char *imageData = SOIL_load_image(
|
|
||||||
textureFilePath.c_str(),
|
|
||||||
&imageWidth, &imageHeight,
|
|
||||||
nullptr, SOIL_LOAD_RGB
|
|
||||||
);
|
|
||||||
GLuint texture;
|
|
||||||
glGenTextures(1, &texture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageWidth, imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
SOIL_free_image_data(imageData);
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cameraPosition = glm::vec3(0.0f, 0.0f, 512.0f);
|
|
||||||
auto cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
|
|
||||||
auto cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
|
|
||||||
|
|
||||||
bool keyPressed[1024];
|
|
||||||
void keyCallback(GLFWwindow* /* window */, int key, int /* scanCode */, int action, int /* mode */) {
|
|
||||||
if(key == GLFW_KEY_W) {
|
|
||||||
if(action == GLFW_PRESS) {
|
|
||||||
keyPressed[GLFW_KEY_W] = true;
|
|
||||||
} else if(action == GLFW_RELEASE) {
|
|
||||||
keyPressed[GLFW_KEY_W] = false;
|
|
||||||
}
|
|
||||||
} else if(key == GLFW_KEY_S) {
|
|
||||||
if(action == GLFW_PRESS) {
|
|
||||||
keyPressed[GLFW_KEY_S] = true;
|
|
||||||
} else if(action == GLFW_RELEASE) {
|
|
||||||
keyPressed[GLFW_KEY_S] = false;
|
|
||||||
}
|
|
||||||
} else if(key == GLFW_KEY_A) {
|
|
||||||
if(action == GLFW_PRESS) {
|
|
||||||
keyPressed[GLFW_KEY_A] = true;
|
|
||||||
} else if(action == GLFW_RELEASE) {
|
|
||||||
keyPressed[GLFW_KEY_A] = false;
|
|
||||||
}
|
|
||||||
} else if(key == GLFW_KEY_D) {
|
|
||||||
if(action == GLFW_PRESS) {
|
|
||||||
keyPressed[GLFW_KEY_D] = true;
|
|
||||||
} else if(action == GLFW_RELEASE) {
|
|
||||||
keyPressed[GLFW_KEY_D] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void moveCamera(double deltaTime) {
|
|
||||||
float cameraSpeed = 1024.0f * static_cast<float>(deltaTime);
|
|
||||||
if(keyPressed[GLFW_KEY_W]) {
|
|
||||||
cameraPosition = cameraPosition + cameraSpeed * cameraFront;
|
|
||||||
} else if(keyPressed[GLFW_KEY_S]) {
|
|
||||||
cameraPosition = cameraPosition - cameraSpeed * cameraFront;
|
|
||||||
} else if(keyPressed[GLFW_KEY_A]) {
|
|
||||||
cameraPosition = cameraPosition - cameraSpeed * glm::normalize(glm::cross(cameraFront, cameraUp));
|
|
||||||
} else if(keyPressed[GLFW_KEY_D]) {
|
|
||||||
cameraPosition = cameraPosition + cameraSpeed * glm::normalize(glm::cross(cameraFront, cameraUp));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float lastX = windowWidth / 2.0f, lastY = windowHeight / 2.0f;
|
|
||||||
float yaw = -90.0f, pitch = 0.0f;
|
|
||||||
bool firstMouse = false;
|
|
||||||
void mouseCallback(GLFWwindow* /* window */, double x, double y) {
|
|
||||||
auto xf = static_cast<float>(x);
|
|
||||||
auto yf = static_cast<float>(y);
|
|
||||||
|
|
||||||
if(!firstMouse) {
|
|
||||||
lastX = xf; lastY = yf;
|
|
||||||
firstMouse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto offsetX = xf - lastX, offsetY = lastY - yf;
|
|
||||||
lastX = xf; lastY = yf;
|
|
||||||
|
|
||||||
float sensivity = 0.05f;
|
|
||||||
offsetX *= sensivity;
|
|
||||||
offsetY *= sensivity;
|
|
||||||
|
|
||||||
yaw += offsetX;
|
|
||||||
pitch += offsetY;
|
|
||||||
|
|
||||||
if(pitch > 89.0f) {
|
|
||||||
pitch = 89.0f;
|
|
||||||
} else if(pitch < -89.0f) {
|
|
||||||
pitch = -89.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 newCameraFront;
|
|
||||||
newCameraFront.x = cosf(glm::radians(pitch)) * cosf(glm::radians(yaw));
|
|
||||||
newCameraFront.y = sinf(glm::radians(pitch));
|
|
||||||
newCameraFront.z = cosf(glm::radians(pitch)) * sinf(glm::radians(yaw));
|
|
||||||
cameraFront = glm::normalize(newCameraFront);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::pair<const glm::vec3, const glm::vec3> findPlaneBasis(const glm::vec3& normal) {
|
|
||||||
std::pair<glm::vec3, glm::vec3> result;
|
|
||||||
glm::vec3 e0, e1;
|
|
||||||
if(normal.z != 0.0f) {
|
|
||||||
e0 = glm::normalize(glm::vec3(1.0f, 0.0f, -normal.x / normal.z));
|
|
||||||
e1 = glm::vec3(0.0f, 1.0f, -normal.y / normal.z);
|
|
||||||
} else if(normal.y != 0.0f) {
|
|
||||||
e0 = glm::normalize(glm::vec3(1.0f, -normal.x / normal.y, 0.0f));
|
|
||||||
e1 = glm::vec3(0.0f, -normal.z / normal.y, 1.0f);
|
|
||||||
} else {
|
|
||||||
e0 = glm::normalize(glm::vec3(-normal.y / normal.x, 1.0f, 0.0f));
|
|
||||||
e1 = glm::vec3(-normal.z / normal.x, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
e1 = glm::normalize(e1 - (glm::dot(e1, e0) / glm::dot(e0, e0)) * e0);
|
|
||||||
|
|
||||||
result.first = e0;
|
|
||||||
result.second = e1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float radius = 8.0f;
|
const float radius = 8.0f;
|
||||||
const float step = 100.0f;
|
const float step = 100.0f;
|
||||||
const float angle = pi / 6.0f;
|
const float angle = pi / 6.0f;
|
||||||
@ -269,37 +98,7 @@ void bufferVertices(
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
if(glfwInit() != GLFW_TRUE) {
|
setUp();
|
||||||
std::cout << "Failed to initialize glfw." << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
|
||||||
|
|
||||||
GLFWwindow* window = glfwCreateWindow(windowWidth, windowHeight, "gl", nullptr, nullptr);
|
|
||||||
if(window == nullptr) {
|
|
||||||
std::cout << "Failed to create window." << std::endl;
|
|
||||||
glfwTerminate();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
glfwSetKeyCallback(window, keyCallback);
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
|
||||||
glfwSetCursorPosCallback(window, mouseCallback);
|
|
||||||
|
|
||||||
glewExperimental = GL_TRUE;
|
|
||||||
if(glewInit() != GLEW_OK) {
|
|
||||||
std::cout << "Failed to initialize glew." << std::endl;
|
|
||||||
glfwTerminate();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int frameBufferWidth, frameBufferHeight;
|
|
||||||
glfwGetFramebufferSize(window, &frameBufferWidth, &frameBufferHeight);
|
|
||||||
glViewport(0, 0, frameBufferWidth, frameBufferHeight);
|
|
||||||
|
|
||||||
auto shaderProgram = linkShaderProgram({
|
auto shaderProgram = linkShaderProgram({
|
||||||
{GL_VERTEX_SHADER, "../resources/shader.vertex"},
|
{GL_VERTEX_SHADER, "../resources/shader.vertex"},
|
||||||
@ -339,9 +138,9 @@ int main() {
|
|||||||
});
|
});
|
||||||
auto threadTexture = loadTexture("../resources/fabric.jpg");
|
auto threadTexture = loadTexture("../resources/fabric.jpg");
|
||||||
|
|
||||||
|
setWindowTitle("parsing lines.json");
|
||||||
boost::property_tree::ptree root;
|
boost::property_tree::ptree root;
|
||||||
glfwSetWindowTitle(window, "parsing lines.json...");
|
boost::property_tree::read_json("../resources/line.json", root);
|
||||||
boost::property_tree::read_json("../resources/lines100500.json", root);
|
|
||||||
|
|
||||||
size_t linesCount = 0;
|
size_t linesCount = 0;
|
||||||
for(const auto& line: root.get_child("lines")) {
|
for(const auto& line: root.get_child("lines")) {
|
||||||
@ -385,7 +184,7 @@ int main() {
|
|||||||
lineIndex++;
|
lineIndex++;
|
||||||
std::stringstream progressString;
|
std::stringstream progressString;
|
||||||
progressString << "loading " << lineIndex << "/" << linesCount;
|
progressString << "loading " << lineIndex << "/" << linesCount;
|
||||||
glfwSetWindowTitle(window, progressString.str().c_str());
|
setWindowTitle(progressString.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint threadVAO;
|
GLuint threadVAO;
|
||||||
@ -406,31 +205,21 @@ int main() {
|
|||||||
glEnableVertexAttribArray(3);
|
glEnableVertexAttribArray(3);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
auto threadModelTransform = glm::mat4(1.0f);
|
auto threadModelTransform = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 100.0f));
|
||||||
threadModelTransform = glm::translate(threadModelTransform, glm::vec3(0.0f, 0.0f, 100.0f));
|
|
||||||
auto projectionTransform = glm::infinitePerspective(
|
|
||||||
glm::radians(45.0f),
|
|
||||||
static_cast<float>(frameBufferWidth) / static_cast<float>(frameBufferHeight),
|
|
||||||
0.1f
|
|
||||||
);
|
|
||||||
double lastTime = 0.0f;
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
while(!glfwWindowShouldClose(window)) {
|
|
||||||
glfwPollEvents();
|
|
||||||
|
|
||||||
double currentTime = glfwGetTime();
|
|
||||||
double deltaTime = currentTime - lastTime;
|
|
||||||
lastTime = currentTime;
|
|
||||||
moveCamera(deltaTime);
|
|
||||||
auto viewTransform = glm::lookAt(
|
|
||||||
cameraPosition,
|
|
||||||
cameraPosition + cameraFront,
|
|
||||||
cameraUp
|
|
||||||
);
|
|
||||||
|
|
||||||
glfwSetWindowTitle(window, std::to_string(static_cast<size_t>(1.0 / deltaTime)).c_str());
|
|
||||||
|
|
||||||
|
renderCycle([
|
||||||
|
shaderProgram,
|
||||||
|
texture,
|
||||||
|
vertexArrayObject,
|
||||||
|
threadShaderProgram,
|
||||||
|
threadTexture,
|
||||||
|
threadModelTransform,
|
||||||
|
threadVAO,
|
||||||
|
verticesBuffer
|
||||||
|
] () {
|
||||||
glClearColor(0.5f, 0.5f, 1.0f, 1.0f);
|
glClearColor(0.5f, 0.5f, 1.0f, 1.0f);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
@ -448,13 +237,13 @@ int main() {
|
|||||||
glGetUniformLocation(shaderProgram, "viewTransform"),
|
glGetUniformLocation(shaderProgram, "viewTransform"),
|
||||||
1,
|
1,
|
||||||
GL_FALSE,
|
GL_FALSE,
|
||||||
glm::value_ptr(viewTransform)
|
glm::value_ptr(getViewTransform())
|
||||||
);
|
);
|
||||||
glUniformMatrix4fv(
|
glUniformMatrix4fv(
|
||||||
glGetUniformLocation(shaderProgram, "projectionTransform"),
|
glGetUniformLocation(shaderProgram, "projectionTransform"),
|
||||||
1,
|
1,
|
||||||
GL_FALSE,
|
GL_FALSE,
|
||||||
glm::value_ptr(projectionTransform)
|
glm::value_ptr(getProjectionTransform())
|
||||||
);
|
);
|
||||||
glBindVertexArray(vertexArrayObject);
|
glBindVertexArray(vertexArrayObject);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
@ -474,21 +263,19 @@ int main() {
|
|||||||
glGetUniformLocation(threadShaderProgram, "viewTransform"),
|
glGetUniformLocation(threadShaderProgram, "viewTransform"),
|
||||||
1,
|
1,
|
||||||
GL_FALSE,
|
GL_FALSE,
|
||||||
glm::value_ptr(viewTransform)
|
glm::value_ptr(getViewTransform())
|
||||||
);
|
);
|
||||||
glUniformMatrix4fv(
|
glUniformMatrix4fv(
|
||||||
glGetUniformLocation(threadShaderProgram, "projectionTransform"),
|
glGetUniformLocation(threadShaderProgram, "projectionTransform"),
|
||||||
1,
|
1,
|
||||||
GL_FALSE,
|
GL_FALSE,
|
||||||
glm::value_ptr(projectionTransform)
|
glm::value_ptr(getProjectionTransform())
|
||||||
);
|
);
|
||||||
glBindVertexArray(threadVAO);
|
glBindVertexArray(threadVAO);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, verticesBuffer.size());
|
glDrawArrays(GL_TRIANGLES, 0, verticesBuffer.size());
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
});
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
tearDown();
|
||||||
}
|
|
||||||
|
|
||||||
glfwTerminate();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
305
utilities.cpp
Normal file
305
utilities.cpp
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
#include <string>
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
using std::ifstream;
|
||||||
|
using std::istreambuf_iterator;
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
using std::exception;
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
using std::initializer_list;
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
using std::pair;
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
using std::function;
|
||||||
|
|
||||||
|
#define GLEW_STATIC
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <SOIL/SOIL.h>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
using glm::vec3;
|
||||||
|
using glm::cross;
|
||||||
|
using glm::dot;
|
||||||
|
using glm::normalize;
|
||||||
|
using glm::radians;
|
||||||
|
using glm::mat4;
|
||||||
|
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
using glm::lookAt;
|
||||||
|
using glm::infinitePerspective;
|
||||||
|
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
const int windowWidth = 1600;
|
||||||
|
const int windowHeight = 900;
|
||||||
|
vec3 cameraPosition, cameraFront, cameraUp;
|
||||||
|
bool keyPressed[1024];
|
||||||
|
|
||||||
|
void keyCallback(GLFWwindow* /* window */, int key, int /* scanCode */, int action, int /* mode */) {
|
||||||
|
if(key == GLFW_KEY_W) {
|
||||||
|
if(action == GLFW_PRESS) {
|
||||||
|
keyPressed[GLFW_KEY_W] = true;
|
||||||
|
} else if(action == GLFW_RELEASE) {
|
||||||
|
keyPressed[GLFW_KEY_W] = false;
|
||||||
|
}
|
||||||
|
} else if(key == GLFW_KEY_S) {
|
||||||
|
if(action == GLFW_PRESS) {
|
||||||
|
keyPressed[GLFW_KEY_S] = true;
|
||||||
|
} else if(action == GLFW_RELEASE) {
|
||||||
|
keyPressed[GLFW_KEY_S] = false;
|
||||||
|
}
|
||||||
|
} else if(key == GLFW_KEY_A) {
|
||||||
|
if(action == GLFW_PRESS) {
|
||||||
|
keyPressed[GLFW_KEY_A] = true;
|
||||||
|
} else if(action == GLFW_RELEASE) {
|
||||||
|
keyPressed[GLFW_KEY_A] = false;
|
||||||
|
}
|
||||||
|
} else if(key == GLFW_KEY_D) {
|
||||||
|
if(action == GLFW_PRESS) {
|
||||||
|
keyPressed[GLFW_KEY_D] = true;
|
||||||
|
} else if(action == GLFW_RELEASE) {
|
||||||
|
keyPressed[GLFW_KEY_D] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveCamera(double deltaTime) {
|
||||||
|
float cameraSpeed = 1024.0f * static_cast<float>(deltaTime);
|
||||||
|
if(keyPressed[GLFW_KEY_W]) {
|
||||||
|
cameraPosition = cameraPosition + cameraSpeed * cameraFront;
|
||||||
|
} else if(keyPressed[GLFW_KEY_S]) {
|
||||||
|
cameraPosition = cameraPosition - cameraSpeed * cameraFront;
|
||||||
|
} else if(keyPressed[GLFW_KEY_A]) {
|
||||||
|
cameraPosition = cameraPosition - cameraSpeed * normalize(cross(cameraFront, cameraUp));
|
||||||
|
} else if(keyPressed[GLFW_KEY_D]) {
|
||||||
|
cameraPosition = cameraPosition + cameraSpeed * normalize(cross(cameraFront, cameraUp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float lastX = windowWidth / 2.0f, lastY = windowHeight / 2.0f;
|
||||||
|
float yaw = -90.0f, pitch = 0.0f;
|
||||||
|
bool firstMouse = false;
|
||||||
|
void mouseCallback(GLFWwindow* /* window */, double x, double y) {
|
||||||
|
auto xf = static_cast<float>(x);
|
||||||
|
auto yf = static_cast<float>(y);
|
||||||
|
|
||||||
|
if(!firstMouse) {
|
||||||
|
lastX = xf; lastY = yf;
|
||||||
|
firstMouse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto offsetX = xf - lastX, offsetY = lastY - yf;
|
||||||
|
lastX = xf; lastY = yf;
|
||||||
|
|
||||||
|
float sensivity = 0.05f;
|
||||||
|
offsetX *= sensivity;
|
||||||
|
offsetY *= sensivity;
|
||||||
|
|
||||||
|
yaw += offsetX;
|
||||||
|
pitch += offsetY;
|
||||||
|
|
||||||
|
if(pitch > 89.0f) {
|
||||||
|
pitch = 89.0f;
|
||||||
|
} else if(pitch < -89.0f) {
|
||||||
|
pitch = -89.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 newCameraFront;
|
||||||
|
newCameraFront.x = cosf(radians(pitch)) * cosf(radians(yaw));
|
||||||
|
newCameraFront.y = sinf(radians(pitch));
|
||||||
|
newCameraFront.z = cosf(radians(pitch)) * sinf(radians(yaw));
|
||||||
|
cameraFront = normalize(newCameraFront);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* window = nullptr;
|
||||||
|
void setUp() noexcept(false) {
|
||||||
|
if(glfwInit() != GLFW_TRUE) {
|
||||||
|
cerr << "Failed to initialize glfw." << endl;
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
|
|
||||||
|
window = glfwCreateWindow(windowWidth, windowHeight, "tes-tiger", nullptr, nullptr);
|
||||||
|
if(window == nullptr) {
|
||||||
|
cerr << "Failed to create window." << endl;
|
||||||
|
glfwTerminate();
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
|
cameraPosition = vec3(0.0f, 0.0f, 512.0f);
|
||||||
|
cameraFront = vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
cameraUp = vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
glfwSetKeyCallback(window, keyCallback);
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
glfwSetCursorPosCallback(window, mouseCallback);
|
||||||
|
|
||||||
|
glewExperimental = GL_TRUE;
|
||||||
|
if(glewInit() != GLEW_OK) {
|
||||||
|
cerr << "Failed to initialize glew." << endl;
|
||||||
|
glfwTerminate();
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
int frameBufferWidth, frameBufferHeight;
|
||||||
|
glfwGetFramebufferSize(window, &frameBufferWidth, &frameBufferHeight);
|
||||||
|
glViewport(0, 0, frameBufferWidth, frameBufferHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown() noexcept {
|
||||||
|
glfwTerminate();
|
||||||
|
window = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWindowTitle(const char* title) noexcept {
|
||||||
|
glfwSetWindowTitle(window, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderCycle(const function<void ()>& renderRoutine) noexcept {
|
||||||
|
double lastTime = 0.0f;
|
||||||
|
|
||||||
|
while(!glfwWindowShouldClose(window)) {
|
||||||
|
glfwPollEvents();
|
||||||
|
|
||||||
|
double currentTime = glfwGetTime();
|
||||||
|
double deltaTime = currentTime - lastTime;
|
||||||
|
lastTime = currentTime;
|
||||||
|
moveCamera(deltaTime);
|
||||||
|
setWindowTitle(std::to_string(static_cast<size_t>(1.0 / deltaTime)).c_str());
|
||||||
|
|
||||||
|
renderRoutine();
|
||||||
|
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 getViewTransform() noexcept {
|
||||||
|
return lookAt(
|
||||||
|
cameraPosition,
|
||||||
|
cameraPosition + cameraFront,
|
||||||
|
cameraUp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 getProjectionTransform() noexcept {
|
||||||
|
int frameBufferWidth, frameBufferHeight;
|
||||||
|
glfwGetFramebufferSize(window, &frameBufferWidth, &frameBufferHeight);
|
||||||
|
auto ratio = static_cast<float>(frameBufferWidth) / static_cast<float>(frameBufferHeight);
|
||||||
|
|
||||||
|
return infinitePerspective(radians(45.0f), ratio, 0.1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
string readFile(const string& filePath) noexcept(false) {
|
||||||
|
ifstream file(filePath);
|
||||||
|
if(!file.good()) {
|
||||||
|
cerr << "Failed to open file '" << filePath << "'." << endl;
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = string(
|
||||||
|
istreambuf_iterator<char>(file),
|
||||||
|
istreambuf_iterator<char>()
|
||||||
|
);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLuint loadShader(const GLenum& shaderType, const string& shaderFilePath) noexcept(false) {
|
||||||
|
const GLuint shader = glCreateShader(shaderType);
|
||||||
|
auto shaderSource = readFile(shaderFilePath);
|
||||||
|
auto shaderSourceC = shaderSource.c_str();
|
||||||
|
glShaderSource(shader, 1, &shaderSourceC, nullptr);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
GLint success;
|
||||||
|
GLchar infoLog[512];
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||||
|
if(!success) {
|
||||||
|
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
|
||||||
|
cerr << "Failed to compile shader '" << shaderFilePath << "': " << infoLog << endl;
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLuint linkShaderProgram(const initializer_list<pair<const GLenum, const string>>& shadersInfo) noexcept(false) {
|
||||||
|
const GLuint shaderProgram = glCreateProgram();
|
||||||
|
for(const auto& shaderInfo: shadersInfo) {
|
||||||
|
auto shader = loadShader(shaderInfo.first, shaderInfo.second);
|
||||||
|
glAttachShader(shaderProgram, shader);
|
||||||
|
glDeleteShader(shader);
|
||||||
|
}
|
||||||
|
glLinkProgram(shaderProgram);
|
||||||
|
{
|
||||||
|
GLint success;
|
||||||
|
GLchar infoLog[512];
|
||||||
|
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
|
||||||
|
if(!success) {
|
||||||
|
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
|
||||||
|
cerr << "Failed to link shader program: " << infoLog << endl;
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shaderProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint loadTexture(const string& textureFilePath) noexcept {
|
||||||
|
int imageWidth, imageHeight;
|
||||||
|
unsigned char *imageData = SOIL_load_image(
|
||||||
|
textureFilePath.c_str(),
|
||||||
|
&imageWidth, &imageHeight,
|
||||||
|
nullptr, SOIL_LOAD_RGB
|
||||||
|
);
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageWidth, imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
SOIL_free_image_data(imageData);
|
||||||
|
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pair<const vec3, const vec3> findPlaneBasis(const vec3& normal) noexcept {
|
||||||
|
pair<vec3, vec3> result;
|
||||||
|
vec3 e0, e1;
|
||||||
|
if(normal.z != 0.0f) {
|
||||||
|
e0 = normalize(vec3(1.0f, 0.0f, -normal.x / normal.z));
|
||||||
|
e1 = vec3(0.0f, 1.0f, -normal.y / normal.z);
|
||||||
|
} else if(normal.y != 0.0f) {
|
||||||
|
e0 = normalize(vec3(1.0f, -normal.x / normal.y, 0.0f));
|
||||||
|
e1 = vec3(0.0f, -normal.z / normal.y, 1.0f);
|
||||||
|
} else {
|
||||||
|
e0 = normalize(vec3(-normal.y / normal.x, 1.0f, 0.0f));
|
||||||
|
e1 = vec3(-normal.z / normal.x, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
e1 = normalize(e1 - (dot(e1, e0) / dot(e0, e0)) * e0);
|
||||||
|
|
||||||
|
result.first = e0;
|
||||||
|
result.second = e1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
23
utilities.h
Normal file
23
utilities.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#define GLEW_STATIC
|
||||||
|
#include "GL/glew.h"
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
void moveCamera(double);
|
||||||
|
void setUp() noexcept(false);
|
||||||
|
void tearDown() noexcept;
|
||||||
|
void setWindowTitle(const char*) noexcept;
|
||||||
|
void renderCycle(const std::function<void ()>&) noexcept;
|
||||||
|
glm::mat4 getViewTransform() noexcept;
|
||||||
|
glm::mat4 getProjectionTransform() noexcept;
|
||||||
|
std::string readFile(const std::string&) noexcept(false);
|
||||||
|
const GLuint loadShader(const GLenum&, const std::string&) noexcept(false);
|
||||||
|
const GLuint linkShaderProgram(const std::initializer_list<std::pair<const GLenum, const std::string>>&) noexcept(false);
|
||||||
|
GLuint loadTexture(const std::string&) noexcept;
|
||||||
|
const std::pair<const glm::vec3, const glm::vec3> findPlaneBasis(const glm::vec3& normal) noexcept;
|
Loading…
Reference in New Issue
Block a user