490 lines
14 KiB
C++
490 lines
14 KiB
C++
#pragma once
|
|
|
|
#ifndef MAP_READER_H
|
|
#define MAP_READER_H
|
|
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <random>
|
|
|
|
#include <glad/glad.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include <glm/glm.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#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<Wall> 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<Sector> sectors;
|
|
|
|
unsigned int wallVAO;
|
|
unsigned int wallVBO, wallEBO, wallNBO, wallCBO;
|
|
unsigned int floorVAO;
|
|
unsigned int floorVBO, floorEBO, floorNBO, floorCBO;
|
|
|
|
std::vector<float> wallVertices, wallNormals, wallColors;
|
|
std::vector<unsigned int> wallIndices;
|
|
|
|
std::vector<float> floorVertices, floorNormals, floorColors;
|
|
std::vector<unsigned int> 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<float> 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<glm::vec3> _floorVertices;
|
|
std::vector<glm::vec3> _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<glm::vec3> _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
|