Files
LearningOpenGL/map_reader.h
onTheZero 4bf6b02255 GameObjects
Began to add GameObjects, starting with the player.
2025-08-13 00:59:03 -04:00

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