#pragma once #ifndef MAP_READER_H #define MAP_READER_H #include #include #include #include #include #include #include #include #include #include #include #include "Shader.h" struct Wall { glm::vec2 a, b; int portal; }; struct Sector { int id; int index; int numberOfWalls; float floorHeight; float ceilingHeight; bool outwardFacing; glm::vec3 color; std::vector walls; }; class Map { public: Map(std::string filename) : wallShader(Shader("wall_test.vert", "wall_test.frag")), floorShader(Shader("wall_test.vert", "wall_test.frag")) { parseMapFile(filename); setupBuffers(); } void render(glm::mat4 projection, glm::mat4 view, glm::vec3 lightPos) { wallShader.use(); wallShader.setMat4("projection", projection); wallShader.setMat4("view", view); glm::mat4 model = glm::mat4(1.0f); wallShader.setMat4("model", model); //shader.setVec3("objectColor", 1.0f, 0.0f, 0.0f); wallShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f); wallShader.setVec3("lightPos", lightPos); glBindVertexArray(wallVAO); // Use glDrawElements since we are using indices //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDrawElements(GL_TRIANGLES, wallIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); floorShader.use(); floorShader.setMat4("projection", projection); floorShader.setMat4("view", view); model = glm::mat4(1.0f); floorShader.setMat4("model", model); floorShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f); floorShader.setVec3("lightPos", lightPos); glBindVertexArray(floorVAO); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDrawElements(GL_TRIANGLES, floorIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); } void render(glm::mat4 projection, glm::mat4 view, glm::vec3 lightPos, float deltaTime, glm::vec3 resolution, float far_plane) { time += deltaTime; wallShader.use(); wallShader.setMat4("projection", projection); wallShader.setMat4("view", view); wallShader.setVec3("iResolution", resolution); wallShader.setFloat("iTime", time); wallShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f); wallShader.setVec3("lightPos", lightPos); wallShader.setInt("shadows", 1); wallShader.setFloat("far_plane", far_plane); wallShader.setInt("diffuseTexture", 0); wallShader.setInt("shadowMap", 1); glm::mat4 model = glm::mat4(1.0f); wallShader.setMat4("model", model); //shader.setVec3("objectColor", 1.0f, 0.0f, 0.0f); glBindVertexArray(wallVAO); // Use glDrawElements since we are using indices //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDrawElements(GL_TRIANGLES, wallIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); floorShader.use(); floorShader.setMat4("projection", projection); floorShader.setMat4("view", view); floorShader.setVec3("iResolution", resolution); floorShader.setFloat("iTime", time); floorShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f); floorShader.setVec3("lightPos", lightPos); floorShader.setInt("shadows", 1); floorShader.setFloat("far_plane", far_plane); floorShader.setInt("diffuseTexture", 0); floorShader.setInt("shadowMap", 1); model = glm::mat4(1.0f); floorShader.setMat4("model", model); glBindVertexArray(floorVAO); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDrawElements(GL_TRIANGLES, floorIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); } void render(glm::mat4 projection, glm::mat4 view, glm::vec3 lightPos, Shader _shader) { glm::mat4 model = glm::mat4(1.0f); _shader.setMat4("model", model); glBindVertexArray(wallVAO); // Use glDrawElements since we are using indices //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDrawElements(GL_TRIANGLES, wallIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); glBindVertexArray(floorVAO); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDrawElements(GL_TRIANGLES, floorIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); /*floorShader.use(); floorShader.setMat4("projection", projection); floorShader.setMat4("view", view); model = glm::mat4(1.0f); floorShader.setMat4("model", model); floorShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f); floorShader.setVec3("lightPos", lightPos); glBindVertexArray(floorVAO); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDrawElements(GL_TRIANGLES, floorIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0);*/ } private: std::vector sectors; unsigned int wallVAO; unsigned int wallVBO, wallEBO, wallNBO, wallCBO; unsigned int floorVAO; unsigned int floorVBO, floorEBO, floorNBO, floorCBO; std::vector wallVertices, wallNormals, wallColors; std::vector wallIndices; std::vector floorVertices, floorNormals, floorColors; std::vector floorIndices; Shader wallShader; Shader floorShader; float time; Sector parseSector(std::string& line) { Sector sector; std::stringstream ss(line); ss >> sector.id >> sector.index >> sector.numberOfWalls >> sector.floorHeight >> sector.ceilingHeight >> sector.outwardFacing; static std::random_device rd; // Obtain a random number from hardware static std::mt19937 eng(rd()); // Seed the generator std::uniform_real_distribution distr(0.0f, 1.0f); // Define the range glm::vec3 randomColor(distr(eng), distr(eng), distr(eng)); sector.color = randomColor; return sector; } Wall parseWall(std::string& line) { Wall wall; std::stringstream ss(line); ss >> wall.a.x >> wall.a.y >> wall.b.x >> wall.b.y >> wall.portal; return wall; } void parseMapFile(std::string filename) { //std::cout << "Parsing map file: " << filename << std::endl; std::ifstream file(filename); std::string line; bool inSector = false, inWall = false; while (std::getline(file, line)) { //std::cout << "Line: " << line << std::endl; if (line.empty() || line[0] == '#') continue; if (line.find("[SECTOR]") != std::string::npos) { inSector = true; inWall = false; continue; } else if (line.find("[WALL]") != std::string::npos) { inSector = false; inWall = true; continue; } if (inSector) { sectors.push_back(parseSector(line)); } if (inWall && !sectors.empty()) { Wall wall = parseWall(line); sectors.back().walls.push_back(wall); } } } void setupBuffers() { std::cout << "Setting up buffers" << std::endl; int wallBaseIndex = 0; int floorBaseIndex = 0; for (Sector sector : sectors) { std::vector _floorVertices; std::vector _ceilingVertices; for (Wall wall : sector.walls) { glm::vec3 v0(wall.a.x, sector.floorHeight, wall.a.y); glm::vec3 v1(wall.b.x, sector.floorHeight, wall.b.y); glm::vec3 v2(wall.b.x, sector.ceilingHeight, wall.b.y); glm::vec3 v3(wall.a.x, sector.ceilingHeight, wall.a.y); _floorVertices.push_back(v0); _ceilingVertices.push_back(v3); if (wall.portal != 0) { Sector& portalSector = sectors[wall.portal - 1]; if (portalSector.floorHeight > sector.floorHeight) { v2.y = portalSector.floorHeight; v3.y = portalSector.floorHeight; addWallVectors(v0, v1, v2, v3, sector.color, wallBaseIndex, sector.outwardFacing); } if (portalSector.ceilingHeight < sector.ceilingHeight) { v0.y = portalSector.ceilingHeight; v1.y = portalSector.ceilingHeight; v2.y = sector.ceilingHeight; v3.y = sector.ceilingHeight; addWallVectors(v0, v1, v2, v3, sector.color, wallBaseIndex, sector.outwardFacing); } continue; } addWallVectors(v0, v1, v2, v3, sector.color, wallBaseIndex, sector.outwardFacing); continue; } addFloorVectors(_floorVertices, floorBaseIndex, true); addFloorVectors(_ceilingVertices, floorBaseIndex, false); } glGenVertexArrays(1, &wallVAO); glGenBuffers(1, &wallVBO); glGenBuffers(1, &wallEBO); glGenBuffers(1, &wallNBO); glGenBuffers(1, &wallCBO); glBindVertexArray(wallVAO); glBindBuffer(GL_ARRAY_BUFFER, wallVBO); glBufferData(GL_ARRAY_BUFFER, wallVertices.size() * sizeof(float), wallVertices.data(), GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, wallNBO); glBufferData(GL_ARRAY_BUFFER, wallNormals.size() * sizeof(float), wallNormals.data(), GL_STATIC_DRAW); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, wallCBO); glBufferData(GL_ARRAY_BUFFER, wallColors.size() * sizeof(float), wallColors.data(), GL_STATIC_DRAW); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(2); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wallEBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, wallIndices.size() * sizeof(unsigned int), wallIndices.data(), GL_STATIC_DRAW); glBindVertexArray(0); glGenVertexArrays(1, &floorVAO); glGenBuffers(1, &floorVBO); glGenBuffers(1, &floorEBO); glGenBuffers(1, &floorNBO); glGenBuffers(1, &floorCBO); glBindVertexArray(floorVAO); glBindBuffer(GL_ARRAY_BUFFER, floorVBO); glBufferData(GL_ARRAY_BUFFER, floorVertices.size() * sizeof(float), floorVertices.data(), GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, floorNBO); glBufferData(GL_ARRAY_BUFFER, floorNormals.size() * sizeof(float), floorNormals.data(), GL_STATIC_DRAW); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, floorCBO); glBufferData(GL_ARRAY_BUFFER, floorColors.size() * sizeof(float), floorColors.data(), GL_STATIC_DRAW); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(2); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, floorEBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, floorIndices.size() * sizeof(unsigned int), floorIndices.data(), GL_STATIC_DRAW); glBindVertexArray(0); } void addWallVectors(glm::vec3 v0, glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, glm::vec3 color, int& baseIndex, bool outward) { wallVertices.push_back(v0.x); wallVertices.push_back(v0.y); wallVertices.push_back(v0.z); wallVertices.push_back(v1.x); wallVertices.push_back(v1.y); wallVertices.push_back(v1.z); wallVertices.push_back(v2.x); wallVertices.push_back(v2.y); wallVertices.push_back(v2.z); wallVertices.push_back(v3.x); wallVertices.push_back(v3.y); wallVertices.push_back(v3.z); glm::vec3 normal = glm::normalize(glm::cross(v1 - v0, v3 - v0)); normal = outward ? normal : -normal; wallNormals.push_back(normal.x); wallNormals.push_back(normal.y); wallNormals.push_back(normal.z); wallNormals.push_back(normal.x); wallNormals.push_back(normal.y); wallNormals.push_back(normal.z); wallNormals.push_back(normal.x); wallNormals.push_back(normal.y); wallNormals.push_back(normal.z); wallNormals.push_back(normal.x); wallNormals.push_back(normal.y); wallNormals.push_back(normal.z); wallColors.push_back(color.x); wallColors.push_back(color.y); wallColors.push_back(color.z); wallColors.push_back(color.x); wallColors.push_back(color.y); wallColors.push_back(color.z); wallColors.push_back(color.x); wallColors.push_back(color.y); wallColors.push_back(color.z); wallColors.push_back(color.x); wallColors.push_back(color.y); wallColors.push_back(color.z); // First triangle wallIndices.push_back(baseIndex); wallIndices.push_back(baseIndex + 1); wallIndices.push_back(baseIndex + 2); // Second triangle wallIndices.push_back(baseIndex); wallIndices.push_back(baseIndex + 2); wallIndices.push_back(baseIndex + 3); baseIndex += 4; } void addFloorVectors(std::vector _vertices, int& baseIndex, bool floor) { for (int i = 0; i + 2 < _vertices.size() ; i+=1) { this->floorVertices.push_back(_vertices[0].x); this->floorVertices.push_back(_vertices[0].y); this->floorVertices.push_back(_vertices[0].z); this->floorVertices.push_back(_vertices[i + 1].x); this->floorVertices.push_back(_vertices[i + 1].y); this->floorVertices.push_back(_vertices[i + 1].z); this->floorVertices.push_back(_vertices[i + 2].x); this->floorVertices.push_back(_vertices[i + 2].y); this->floorVertices.push_back(_vertices[i + 2].z); glm::vec3 normal = glm::normalize(glm::cross(_vertices[i + 1] - _vertices[0], _vertices[i + 2] - _vertices[0])); normal = floor ? -normal : normal; floorNormals.push_back(normal.x); floorNormals.push_back(normal.y); floorNormals.push_back(normal.z); floorNormals.push_back(normal.x); floorNormals.push_back(normal.y); floorNormals.push_back(normal.z); floorNormals.push_back(normal.x); floorNormals.push_back(normal.y); floorNormals.push_back(normal.z); glm::vec3 color; color = floor ? glm::vec3(0.75f, 0.5f, 0.25f) : glm::vec3(0.25f, 0.5f, 0.75f); this->floorColors.push_back(color.x); this->floorColors.push_back(color.y); this->floorColors.push_back(color.z); this->floorColors.push_back(color.x); this->floorColors.push_back(color.y); this->floorColors.push_back(color.z); this->floorColors.push_back(color.x); this->floorColors.push_back(color.y); this->floorColors.push_back(color.z); floorIndices.push_back(baseIndex); floorIndices.push_back(baseIndex + 1); floorIndices.push_back(baseIndex + 2); baseIndex += 3; } } }; #endif