summaryrefslogtreecommitdiffstats
path: root/code/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'code/graphics')
-rw-r--r--code/graphics/AssetManager.cpp143
-rw-r--r--code/graphics/AssetManager.hpp52
-rw-r--r--code/graphics/Camera3D.cpp79
-rw-r--r--code/graphics/Camera3D.hpp66
-rw-r--r--code/graphics/Display.cpp268
-rw-r--r--code/graphics/Display.hpp33
-rw-r--r--code/graphics/Shader.cpp90
-rw-r--r--code/graphics/Shader.hpp22
-rw-r--r--code/graphics/Texture.cpp39
-rw-r--r--code/graphics/Texture.hpp12
10 files changed, 804 insertions, 0 deletions
diff --git a/code/graphics/AssetManager.cpp b/code/graphics/AssetManager.cpp
new file mode 100644
index 0000000..1840c63
--- /dev/null
+++ b/code/graphics/AssetManager.cpp
@@ -0,0 +1,143 @@
+#include "AssetManager.hpp"
+
+const std::string pathToAssets = "./assets/";
+const std::string pathToObjects = pathToAssets + "objects/";
+const std::string pathToIndexFile = pathToAssets + "indexes/1.11.json";
+const std::string pathToAssetsMc = "./assetsMc/";
+
+const std::map<Asset::AssetType, std::string> assetTypeFileExtensions{
+ std::make_pair(Asset::AssetType::Texture, ".png"),
+ std::make_pair(Asset::AssetType::Lang, ".lang"),
+ std::make_pair(Asset::AssetType::Sound, ".ogg"),
+};
+
+AssetManager::AssetManager() {
+ std::ifstream indexFile(pathToIndexFile);
+ if (!indexFile) {
+ std::cerr << "Can't open file " << pathToIndexFile << std::endl;
+ }
+ nlohmann::json json = nlohmann::json::parse(indexFile)["objects"];
+ for (auto it = json.begin(); it != json.end(); ++it) {
+ size_t fileNameExtensionPos = -1;
+ std::string name = it.key();
+ Asset::AssetType type = Asset::Unknown;
+ for (auto &it:assetTypeFileExtensions) {
+ if ((fileNameExtensionPos = name.find(it.second)) != std::string::npos) {
+ type = it.first;
+ name = name.substr(0, fileNameExtensionPos);
+ break;
+ }
+ }
+ std::string hash = it.value()["hash"].get<std::string>();
+ size_t size = it.value()["size"].get<int>();
+ Asset asset{name, hash, Asset::AssetData(), size, type};
+ this->assets[name] = asset;
+ }
+}
+
+AssetManager::~AssetManager() {
+
+}
+
+Asset &AssetManager::GetAsset(std::string AssetName) {
+ if (instance().assets.find(AssetName) == instance().assets.end() || !instance().assets[AssetName].isParsed())
+ LoadAsset(AssetName);
+ return instance().assets[AssetName];
+}
+
+void AssetManager::LoadAsset(std::string AssetName) {
+ if (instance().assets.find(AssetName) != instance().assets.end() && instance().assets[AssetName].isParsed())
+ return;
+ std::string AssetFileName = GetPathToAsset(AssetName);
+ Asset &asset = instance().assets[AssetName];
+
+
+ if (asset.type == Asset::Texture) {
+ asset.data.texture = new Texture(AssetFileName,GL_CLAMP_TO_BORDER,GL_NEAREST);
+ //asset.data.texture.loadFromFile((asset.name + assetTypeFileExtensions.at(asset.type)));
+ }
+}
+
+std::string AssetManager::GetPathToAsset(std::string AssetName) {
+ if (instance().assets.find(AssetName) != instance().assets.end()){
+ auto it = instance().assets.find(AssetName);
+ return pathToObjects + std::string(instance().assets[AssetName].hash.c_str(), 2) + "/" +
+ instance().assets[AssetName].hash;
+ }
+
+ instance().assets[AssetName].hash="";
+ instance().assets[AssetName].type=Asset::AssetType::Texture;
+ instance().assets[AssetName].name=AssetName;
+ instance().assets[AssetName].size=0;
+ return pathToAssetsMc + "" + instance().assets[AssetName].name +
+ assetTypeFileExtensions.at(instance().assets[AssetName].type);
+}
+
+std::string AssetManager::GetAssetNameByBlockId(unsigned short id) {
+ std::string assetBase = "minecraft/textures/blocks/";
+ std::string textureName;
+ switch (id){
+ case 0:
+ textureName="air";
+ break;
+ case 1:
+ textureName="stone";
+ break;
+ case 2:
+ textureName="grass";
+ break;
+ case 3:
+ textureName="dirt";
+ break;
+ case 16:
+ textureName="coal_ore";
+ break;
+ case 17:
+ textureName="log_oak";
+ break;
+ case 31:
+ textureName="air";
+ break;
+ default:
+ //std::cout<<id<<std::endl;
+ textureName="beacon";
+ break;
+ }
+ return assetBase+textureName;
+}
+
+bool Asset::isParsed() {
+ switch (type) {
+ case Unknown:
+ return false;
+ break;
+ case Texture:
+ return this->data.texture != nullptr;
+ break;
+ case Sound:
+ return false;
+ break;
+ case Model:
+ return false;
+ break;
+ case Lang:
+ return false;
+ break;
+ }
+}
+
+Asset::~Asset() {
+ switch (type) {
+ case Unknown:
+ break;
+ case Texture:
+ delete this->data.texture;
+ break;
+ case Sound:
+ break;
+ case Model:
+ break;
+ case Lang:
+ break;
+ }
+}
diff --git a/code/graphics/AssetManager.hpp b/code/graphics/AssetManager.hpp
new file mode 100644
index 0000000..c7ef81a
--- /dev/null
+++ b/code/graphics/AssetManager.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <fstream>
+#include <string>
+#include <map>
+#include "../json.hpp"
+#include "Texture.hpp"
+
+struct Asset {
+ std::string name = "";
+ std::string hash = "";
+ union AssetData{
+ Texture *texture;
+ } data;
+ size_t size = 0;
+ enum AssetType {
+ Unknown,
+ Texture,
+ Sound,
+ Model,
+ Lang,
+ } type = Unknown;
+ bool isParsed();
+ ~Asset();
+};
+
+class AssetManager {
+ AssetManager();
+
+ ~AssetManager();
+
+ AssetManager(const AssetManager &);
+
+ AssetManager &operator=(const AssetManager &);
+
+ std::map<std::string, Asset> assets;
+
+ static AssetManager &instance() {
+ static AssetManager assetManager;
+ return assetManager;
+ }
+
+ static std::string GetPathToAsset(std::string AssetName);
+public:
+
+ static Asset &GetAsset(std::string AssetName);
+
+ static void LoadAsset(std::string AssetName);
+
+ static std::string GetAssetNameByBlockId(unsigned short id);
+};
+
diff --git a/code/graphics/Camera3D.cpp b/code/graphics/Camera3D.cpp
new file mode 100644
index 0000000..eb740e4
--- /dev/null
+++ b/code/graphics/Camera3D.cpp
@@ -0,0 +1,79 @@
+#include "Camera3D.hpp"
+
+Camera3D::Camera3D(glm::vec3 position, glm::vec3 up, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)),
+ MovementSpeed(SPEED),
+ MouseSensitivity(SENSITIVTY),
+ Zoom(ZOOM) {
+ this->Position = position;
+ this->WorldUp = up;
+ this->Yaw = yaw;
+ this->Pitch = pitch;
+ this->updateCameraVectors();
+}
+
+Camera3D::Camera3D(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw,
+ GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY),
+ Zoom(ZOOM) {
+ this->Position = glm::vec3(posX, posY, posZ);
+ this->WorldUp = glm::vec3(upX, upY, upZ);
+ this->Yaw = yaw;
+ this->Pitch = pitch;
+ this->updateCameraVectors();
+}
+
+glm::mat4 Camera3D::GetViewMatrix() {
+ return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
+}
+
+void Camera3D::ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime) {
+ GLfloat velocity = this->MovementSpeed * deltaTime;
+ if (direction == FORWARD)
+ this->Position += this->Front * velocity;
+ if (direction == BACKWARD)
+ this->Position -= this->Front * velocity;
+ if (direction == LEFT)
+ this->Position -= this->Right * velocity;
+ if (direction == RIGHT)
+ this->Position += this->Right * velocity;
+}
+
+void Camera3D::ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch) {
+ xoffset *= this->MouseSensitivity;
+ yoffset *= this->MouseSensitivity;
+
+ this->Yaw += xoffset;
+ this->Pitch += yoffset;
+
+ // Make sure that when pitch is out of bounds, screen doesn't get flipped
+ if (constrainPitch) {
+ if (this->Pitch > 89.0f)
+ this->Pitch = 89.0f;
+ if (this->Pitch < -89.0f)
+ this->Pitch = -89.0f;
+ }
+
+ // Update Front, Right and Up Vectors using the updated Eular angles
+ this->updateCameraVectors();
+}
+
+void Camera3D::ProcessMouseScroll(GLfloat yoffset) {
+ if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
+ this->Zoom -= yoffset/5.0f;
+ if (this->Zoom <= 1.0f)
+ this->Zoom = 1.0f;
+ if (this->Zoom >= 45.0f)
+ this->Zoom = 45.0f;
+}
+
+void Camera3D::updateCameraVectors() {
+ // Calculate the new Front vector
+ glm::vec3 front;
+ front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
+ front.y = sin(glm::radians(this->Pitch));
+ front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
+ this->Front = glm::normalize(front);
+ // Also re-calculate the Right and Up vector
+ this->Right = glm::normalize(glm::cross(this->Front,
+ this->WorldUp)); // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
+ this->Up = glm::normalize(glm::cross(this->Right, this->Front));
+}
diff --git a/code/graphics/Camera3D.hpp b/code/graphics/Camera3D.hpp
new file mode 100644
index 0000000..eac1f47
--- /dev/null
+++ b/code/graphics/Camera3D.hpp
@@ -0,0 +1,66 @@
+#pragma once
+
+// Std. Includes
+#include <vector>
+
+// GL Includes
+#include <GL/glew.h>
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+
+// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods
+enum Camera_Movement {
+ FORWARD,
+ BACKWARD,
+ LEFT,
+ RIGHT
+};
+
+// Default camera values
+const GLfloat YAW = -90.0f;
+const GLfloat PITCH = 0.0f;
+const GLfloat SPEED = 30.0f;
+const GLfloat SENSITIVTY = 0.2f;
+const GLfloat ZOOM = 45.0f;
+
+// An abstract camera class that processes input and calculates the corresponding Eular Angles, Vectors and Matrices for use in OpenGL
+class Camera3D {
+public:
+ // Camera3D Attributes
+ glm::vec3 Position;
+ glm::vec3 Front;
+ glm::vec3 Up;
+ glm::vec3 Right;
+ glm::vec3 WorldUp;
+ // Eular Angles
+ GLfloat Yaw;
+ GLfloat Pitch;
+ // Camera3D options
+ GLfloat MovementSpeed;
+ GLfloat MouseSensitivity;
+ GLfloat Zoom;
+
+ // Constructor with vectors
+ explicit Camera3D(glm::vec3 position = glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f),
+ GLfloat yaw = YAW, GLfloat pitch = PITCH);
+
+ // Constructor with scalar values
+ Camera3D(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch);
+
+ // Returns the view matrix calculated using Eular Angles and the LookAt Matrix
+ glm::mat4 GetViewMatrix();
+
+ // Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
+ void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime);
+
+ // Processes input received from a mouse input system. Expects the offset value in both the x and y direction.
+ void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true);
+
+ // Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
+ void ProcessMouseScroll(GLfloat yoffset);
+
+private:
+ // Calculates the front vector from the Camera3D's (updated) Eular Angles
+ void updateCameraVectors();
+}; \ No newline at end of file
diff --git a/code/graphics/Display.cpp b/code/graphics/Display.cpp
new file mode 100644
index 0000000..a68c35b
--- /dev/null
+++ b/code/graphics/Display.cpp
@@ -0,0 +1,268 @@
+#include <iomanip>
+#include "Display.hpp"
+#include "AssetManager.hpp"
+
+Display::Display(unsigned int winWidth, unsigned int winHeight, const char *winTitle, World *worldPtr) : world(
+ worldPtr) {
+ sf::ContextSettings contextSetting;
+ contextSetting.majorVersion = 3;
+ contextSetting.minorVersion = 3;
+ contextSetting.attributeFlags = contextSetting.Core;
+ contextSetting.depthBits = 24;
+ window = new sf::Window(sf::VideoMode(winWidth, winHeight), winTitle, sf::Style::Default, contextSetting);
+ window->setVerticalSyncEnabled(true);
+ window->setMouseCursorVisible(false);
+ sf::Mouse::setPosition(sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2), *window);
+
+ //Glew
+ glewExperimental = GL_TRUE;
+ if (glewInit() != GLEW_OK) {
+ std::cout << "Failed to initialize GLEW" << std::endl;
+ throw 3;
+ }
+ glViewport(0, 0, width(), height());
+ glEnable(GL_DEPTH_TEST);
+}
+
+bool Display::IsClosed() {
+ return !window->isOpen();
+}
+
+void Display::SetPlayerPos(double playerX, double playerY, double playerZ) {
+ camera.Position = glm::vec3(playerX, playerY, playerZ);
+ const int ChunkDistance = 1;
+ PositionI playerChunk = PositionI((int) playerX / 16, (int) playerZ / 16, (int) playerY / 16);
+ /*std::cout << "Player chunk position: " << playerChunk.GetX() << " "
+ << playerChunk.GetZ() << " " << playerChunk.GetY() << std::endl;*/
+ for (auto &it:world->m_sections) {
+ PositionI chunkPosition = it.first;
+ PositionI delta = chunkPosition - playerChunk;
+ if (delta.GetDistance() > ChunkDistance)
+ continue;
+ /*std::cout << "Rendering " << delta.GetDistance() << " Detailed: " << delta.GetX() << " " << delta.GetZ() << " "
+ << delta.GetY() << std::endl <<
+ "\t" << chunkPosition.GetX() << " " << chunkPosition.GetZ() << " "
+ << chunkPosition.GetY() << std::endl;*/
+ toRender.push_back(it.first);
+ }
+ std::cout << "Chunks to render: " << toRender.size() << std::endl;
+}
+
+void Display::MainLoop() {
+ Shader shader("./shaders/simple.vs", "./shaders/simple.fs");
+
+ GLfloat vertices[] = {
+ -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
+ 0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
+ 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
+ -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
+ -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
+
+ -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
+ 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
+ 0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
+ -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
+
+ -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
+ -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
+ -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
+ -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
+
+ 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
+ 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
+ 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
+
+ -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
+ -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
+
+ -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
+ 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
+ -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
+ };
+ GLuint indices[] = {
+ 0, 1, 2,
+ 0, 2, 3
+ };
+ GLuint VBO, VAO, EBO;
+ glGenBuffers(1, &VBO);
+ glGenBuffers(1, &EBO);
+ glGenVertexArrays(1, &VAO);
+
+ glBindVertexArray(VAO);
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *) (3 * sizeof(GLfloat)));
+ glEnableVertexAttribArray(2);
+ }
+ glBindVertexArray(0);
+
+ shader.Use();
+
+ bool captureMouse = true;
+
+ bool isRunning = true;
+ while (isRunning) {
+ static sf::Clock clock, clock1;
+ float deltaTime = clock.getElapsedTime().asSeconds();
+ float absTime = clock1.getElapsedTime().asSeconds();
+ clock.restart();
+ sf::Event event;
+ while (window->pollEvent(event)) {
+ switch (event.type) {
+ case sf::Event::Closed:
+ window->close();
+ isRunning = false;
+ break;
+ case sf::Event::Resized:
+ glViewport(0, 0, width(), height());
+ break;
+ case sf::Event::KeyPressed:
+ switch (event.key.code) {
+ case sf::Keyboard::Escape:
+ isRunning = false;
+ break;
+ case sf::Keyboard::T:
+ captureMouse = !captureMouse;
+ window->setMouseCursorVisible(!captureMouse);
+ sf::Mouse::setPosition(sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2),
+ *window);
+ break;
+ case sf::Keyboard::R:
+ shader.Reload();
+ break;
+ default:
+ break;
+ }
+ case sf::Event::MouseWheelScrolled:
+ camera.ProcessMouseScroll(event.mouseWheelScroll.delta);
+ break;
+ default:
+ break;
+ }
+ }
+ std::ostringstream toWindow;
+ glm::highp_vec3 cameraPosition(camera.Position);
+ toWindow << std::setprecision(2) << std::fixed << "Pos: " << cameraPosition.x << ", " << cameraPosition.y
+ << ", " << cameraPosition.z << "; ";
+ toWindow << "FPS: " << (1.0f / deltaTime) << " ";
+ window->setTitle(toWindow.str());
+ if (captureMouse) {
+ sf::Vector2i mousePos = sf::Mouse::getPosition(*window);
+ sf::Vector2i center = sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2);
+ sf::Mouse::setPosition(center, *window);
+ int deltaX = (mousePos - center).x, deltaY = (center - mousePos).y;
+ camera.ProcessMouseMovement(deltaX, deltaY);
+ }
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
+ camera.ProcessKeyboard(Camera_Movement::FORWARD, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
+ camera.ProcessKeyboard(Camera_Movement::BACKWARD, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
+ camera.ProcessKeyboard(Camera_Movement::LEFT, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
+ camera.ProcessKeyboard(Camera_Movement::RIGHT, deltaTime);
+
+
+ //Render code
+ glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ shader.Use();
+
+ GLint modelLoc = glGetUniformLocation(shader.Program, "model");
+ GLint projectionLoc = glGetUniformLocation(shader.Program, "projection");
+ GLint viewLoc = glGetUniformLocation(shader.Program, "view");
+ GLint blockLoc = glGetUniformLocation(shader.Program, "block");
+ GLint timeLoc = glGetUniformLocation(shader.Program, "time");
+ glm::mat4 projection = glm::perspective(camera.Zoom, (float) width() / (float) height(), 0.1f, 1000.0f);
+ glm::mat4 view = camera.GetViewMatrix();
+ glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
+ glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
+ glUniform1f(timeLoc, absTime);
+
+ glBindVertexArray(VAO);
+ /*for (GLuint i = 0; i < 10; i++) {
+ glm::mat4 model;
+ glm::vec3 cubePositions[] = {
+ glm::vec3(0, 0, 0),
+ glm::vec3(0, 0, 1),
+ glm::vec3(0, 0, 2),
+ glm::vec3(1, 0, 0),
+ glm::vec3(1, 0, 1),
+ glm::vec3(1, 0, 2),
+ glm::vec3(2, 0, 0),
+ glm::vec3(2, 0, 1),
+ glm::vec3(2, 0, 2),
+ glm::vec3(3, 0, 3),
+ };
+ if (toRender.size()<1)
+ continue;
+ model = glm::translate(model,
+ glm::vec3(toRender[0].GetX() * 16, toRender[0].GetZ() * 16,
+ toRender[0].GetY() * 16));
+ model = glm::translate(model, cubePositions[i]);
+
+ GLfloat angle = 20.0f * (i);
+ //model = glm::rotate(model, glm::radians(angle * absTime), glm::vec3(1.0f, 0.3f, 0.5f));
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+ }*/
+
+ for (auto &sectionPos:toRender) {
+ Section &section = world->m_sections[sectionPos];
+ for (int y = 0; y < 16; y++) {
+ for (int z = 0; z < 16; z++) {
+ for (int x = 0; x < 16; x++) {
+ glm::mat4 model;
+ model = glm::translate(model,
+ glm::vec3(sectionPos.GetX() * 16, sectionPos.GetY() * 16,
+ sectionPos.GetZ() * 16));
+ model = glm::translate(model, glm::vec3(x, y, z));
+
+ Block block = section.GetBlock(PositionI(x, z, y));
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+ glUniform1i(blockLoc, block.id);
+
+ std::string textureName = AssetManager::GetAssetNameByBlockId(block.id);
+ if (textureName.find("air") != std::string::npos)
+ continue;
+ Texture &texture1 = *(AssetManager::GetAsset(textureName).data.texture);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture1.texture);
+ glUniform1i(glGetUniformLocation(shader.Program, "blockTexture"), 0);
+
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+ }
+ }
+ }
+ }
+ glBindVertexArray(0);
+
+ //End of render code
+
+ window->display();
+ }
+
+}
diff --git a/code/graphics/Display.hpp b/code/graphics/Display.hpp
new file mode 100644
index 0000000..314ef5d
--- /dev/null
+++ b/code/graphics/Display.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <SFML/Window.hpp>
+#include "../World.hpp"
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtc/type_ptr.hpp>
+#include "Shader.hpp"
+#include "Texture.hpp"
+#include "Camera3D.hpp"
+
+class Display {
+ sf::Window *window;
+ World* world;
+ std::vector<PositionI> toRender;
+ Camera3D camera;
+public:
+ Display(unsigned int winWidth, unsigned int winHeight, const char winTitle[9], World *worldPtr);
+
+ bool IsClosed();
+
+ void SetPlayerPos(double playerX, double playerY, double playerZ);
+
+ void MainLoop();
+
+ unsigned int width() {
+ return window->getSize().x;
+ }
+
+ unsigned int height() {
+ return window->getSize().y;
+ }
+}; \ No newline at end of file
diff --git a/code/graphics/Shader.cpp b/code/graphics/Shader.cpp
new file mode 100644
index 0000000..c84e169
--- /dev/null
+++ b/code/graphics/Shader.cpp
@@ -0,0 +1,90 @@
+#include "Shader.hpp"
+
+Shader::Shader(const GLchar *vertexPath, const GLchar *fragmentPath) {
+ vertex = vertexPath;
+ fragment = fragmentPath;
+ // 1. Получаем исходный код шейдера из filePath
+ std::string vertexCode;
+ std::string fragmentCode;
+ std::ifstream vShaderFile;
+ std::ifstream fShaderFile;
+ // Удостоверимся, что ifstream объекты могут выкидывать исключения
+ vShaderFile.exceptions(std::ifstream::failbit);
+ fShaderFile.exceptions(std::ifstream::failbit);
+ try {
+ // Открываем файлы
+ vShaderFile.open(vertexPath);
+ fShaderFile.open(fragmentPath);
+ std::stringstream vShaderStream, fShaderStream;
+ // Считываем данные в потоки
+ vShaderStream << vShaderFile.rdbuf();
+ fShaderStream << fShaderFile.rdbuf();
+ // Закрываем файлы
+ vShaderFile.close();
+ fShaderFile.close();
+ // Преобразовываем потоки в массив GLchar
+ vertexCode = vShaderStream.str();
+ fragmentCode = fShaderStream.str();
+ }
+ catch (std::ifstream::failure e) {
+ std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
+ }
+ const GLchar *vShaderCode = vertexCode.c_str();
+ const GLchar *fShaderCode = fragmentCode.c_str();
+
+
+ // 2. Сборка шейдеров
+ GLuint vertex, fragment;
+ GLint success;
+ GLchar infoLog[512];
+
+ // Вершинный шейдер
+ vertex = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex, 1, &vShaderCode, NULL);
+ glCompileShader(vertex);
+ // Если есть ошибки - вывести их
+ glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(vertex, 512, NULL, infoLog);
+ std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
+ };
+
+ // Вершинный шейдер
+ fragment = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragment, 1, &fShaderCode, NULL);
+ glCompileShader(fragment);
+ // Если есть ошибки - вывести их
+ glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(fragment, 512, NULL, infoLog);
+ std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
+ };
+
+ // Шейдерная программа
+ this->Program = glCreateProgram();
+ glAttachShader(this->Program, vertex);
+ glAttachShader(this->Program, fragment);
+ glLinkProgram(this->Program);
+ //Если есть ошибки - вывести их
+ glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
+ if (!success) {
+ glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
+ std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
+ }
+
+ // Удаляем шейдеры, поскольку они уже в программу и нам больше не нужны.
+ glDeleteShader(vertex);
+ glDeleteShader(fragment);
+}
+
+void Shader::Use() {
+ glUseProgram(this->Program);
+}
+
+void Shader::Reload() {
+ const GLchar *vertexPath = vertex;
+ const GLchar *fragmentPath = fragment;
+ this->~Shader();
+ new(this) Shader(vertexPath, fragmentPath);
+ std::cout<<"Shader is realoded!"<<std::endl;
+}
diff --git a/code/graphics/Shader.hpp b/code/graphics/Shader.hpp
new file mode 100644
index 0000000..8178d2a
--- /dev/null
+++ b/code/graphics/Shader.hpp
@@ -0,0 +1,22 @@
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+
+#include <GL/glew.h>
+
+class Shader
+{
+private:
+ const GLchar *vertex;
+ const GLchar *fragment;
+public:
+ // Идентификатор программы
+ GLuint Program;
+ // Конструктор считывает и собирает шейдер
+ Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
+ // Использование программы
+ void Use();
+
+ void Reload();
+}; \ No newline at end of file
diff --git a/code/graphics/Texture.cpp b/code/graphics/Texture.cpp
new file mode 100644
index 0000000..0104530
--- /dev/null
+++ b/code/graphics/Texture.cpp
@@ -0,0 +1,39 @@
+#include <iostream>
+#include <SFML/Graphics.hpp>
+#include "Texture.hpp"
+
+Texture::Texture(std::string filename, GLenum textureWrapping, GLenum textureFiltering) {
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ //Texture options
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapping);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapping);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,textureFiltering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ //Image load
+ sf::Image image;
+ if (!image.loadFromFile(filename)) {
+ std::cout << "Can't open image " << filename << std::endl;
+ throw 201;
+ }
+ if (image.getPixelsPtr()==nullptr){
+ std::cout<<"Image data is corrupted!"<<std::endl;
+ throw 202;
+ }
+ image.flipVertically();
+
+
+ //Creating texture
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ (GLvoid *) image.getPixelsPtr());
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+}
+
+Texture::~Texture() {
+ glDeleteTextures(1, &texture);
+}
diff --git a/code/graphics/Texture.hpp b/code/graphics/Texture.hpp
new file mode 100644
index 0000000..8e3f1af
--- /dev/null
+++ b/code/graphics/Texture.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <GL/glew.h>
+
+class Texture {
+ Texture(Texture&);
+ Texture&operator=(Texture&);
+public:
+ GLuint texture;
+ Texture(std::string filename, GLenum textureWrapping = GL_CLAMP_TO_BORDER, GLenum textureFiltering = GL_NEAREST);
+ ~Texture();
+}; \ No newline at end of file