ICT290 / src / scene / theArchanist / map / gameRoom.cpp
gameRoom.cpp
Raw
#include "gameRoom.h"
#include <exception>
#include <glm/gtx/rotate_vector.hpp>

gameRoom::gameRoom(int x,
                   int z,
                   int wallFillPercent,
                   int floorFillPercent,
                   int xOrigin,
                   int zOrigin,
                   const RoomModels& roomModels,
                   int seed,
                   const std::vector<std::pair<int, int>>& doors)
    : m_models(roomModels),
      m_seed(seed),
      m_doors(doors) {
    // Save x and z size
    if (x < 1) {
        x = 1;
    }
    if (z < 1) {
        z = 1;
    }

    // Save floor dimensions
    m_floor.xMax = x;
    m_floor.zMax = z;
    m_floor.max = z * x;

    // Save floor size plus walls
    const int corners{2};
    m_wall.xMax = x + corners;
    m_wall.zMax = z + corners;
    m_wall.max = x * 2 + z * 2;

    // Set room dimensions
    m_dimensions.xMax = x + corners;
    m_dimensions.zMax = z + corners;
    m_dimensions.max = m_dimensions.xMax * m_dimensions.zMax;

    // Set room map size
    m_accessible = new accessTypes[m_dimensions.max];
    // Set it empty
    memset(m_accessible,
           accessTypes::empty,
           sizeof(accessTypes) * m_dimensions.max);

    // Save origin offsets
    m_offset.xCent = xOrigin + m_dimensions.xMax / 2;
    m_offset.zCent = zOrigin + m_dimensions.zMax / 2;
    m_offset.xMax = xOrigin + m_dimensions.xMax;
    m_offset.zMax = zOrigin + m_dimensions.zMax;
    m_offset.xMin = xOrigin;
    m_offset.zMin = zOrigin;

    // Create itself
    createRoom();
    addDecoration((float)floorFillPercent, (float)wallFillPercent);
    generateWallPoints();
    generateEntityBoundingSpheres();
}

gameRoom::~gameRoom() {
    delete[] m_accessible;
}

gameRoom::gameRoom(const gameRoom& other)
    : m_accessible(nullptr),
      m_wallPoints(other.m_wallPoints),
      m_entityBoundingSpheres(other.m_entityBoundingSpheres),
      m_floor(other.m_floor),
      m_wall(other.m_wall),
      m_dimensions(other.m_dimensions),
      m_offset(other.m_offset),
      m_normals(other.m_normals),
      m_models(other.m_models),
      m_objects(other.m_objects),
      m_debugData(other.m_debugData),
      m_debugObjects(other.m_debugObjects),
      m_seed(other.m_seed),
      m_randomRotationOffset(other.m_randomRotationOffset),
      m_doors(other.m_doors) {
    m_accessible = new accessTypes[other.m_dimensions.max];
    std::memcpy(m_accessible, other.m_accessible, other.m_dimensions.max);
}

gameRoom& gameRoom::operator=(const gameRoom& other) {
    if (this != &other) {
        if (m_accessible != nullptr) {
            free(m_accessible);
            m_accessible = nullptr;
        }

        m_wallPoints = other.m_wallPoints;
        m_entityBoundingSpheres = other.m_entityBoundingSpheres;
        m_floor = other.m_floor;
        m_wall = other.m_wall;
        m_dimensions = other.m_dimensions;
        m_offset = other.m_offset;
        m_normals = other.m_normals;
        m_models = other.m_models;
        m_objects = other.m_objects;
        m_debugData = other.m_debugData;
        m_debugObjects = other.m_debugObjects;
        m_seed = other.m_seed;
        m_randomRotationOffset = other.m_randomRotationOffset;
        m_doors = other.m_doors;

        if (other.m_accessible != nullptr) {
            m_accessible = new accessTypes[other.m_dimensions.max];
            std::memcpy(m_accessible,
                        other.m_accessible,
                        other.m_dimensions.max);
        }
    }
    return *this;
}

const std::vector<std::vector<glm::vec3>>& gameRoom::getWallPoints() const {
    return m_wallPoints;
}

const std::vector<std::pair<glm::vec3, float>>& gameRoom::getBoundingSpheres()
    const {
    return m_entityBoundingSpheres;
}

glm::vec3 gameRoom::getLocation() const {
    return glm::vec3{m_offset.xCent, 0, m_offset.zCent};
}

glm::vec3 gameRoom::getMin() const {
    return glm::vec3{m_offset.xMin, 0, m_offset.zMin};
}

glm::vec3 gameRoom::getMax() const {
    return glm::vec3{m_offset.xMax, 0, m_offset.zMax};
}

void gameRoom::setDoors() {
    for (auto& door : m_doors) {
        if (isWall(door.first, door.second)) {
            m_accessible[getIndex(door.first, door.second)] = accessTypes::door;
        }
    }
}

void gameRoom::createRoom() {
    setDoors();
    for (int row{0}; row < m_dimensions.xMax; ++row) {
        for (int col{0}; col < m_dimensions.zMax; ++col) {
            if (isWall(row, col)) {
                if (m_accessible[getIndex(row, col)] == accessTypes::door) {
                    createWallType(row,
                                   col,
                                   m_models.walls[1],
                                   accessTypes::door);
                } else {
                    createWallType(row,
                                   col,
                                   m_models.walls[0],
                                   accessTypes::wall);
                }

            } else if (!isCorner(row, col)) {
                createFloorType(row,
                                col,
                                m_models.floors[0],
                                accessTypes::floor);
            }
        }
    }
}

float gameRoom::randomRotation() {
    std::mt19937 gen{static_cast<std::random_device::result_type>(
        m_seed + m_randomRotationOffset++)};             /// seed the generator
    std::uniform_int_distribution<> distribution{0, 3};  /// define the range
    float angles[4] = {0, 90, 180, 270};
    return angles[distribution(gen)];
}

bool gameRoom::isCorner(int row, int col) const {
    return ((row == 0 && col == 0) || (row == 0 && col == m_dimensions.zMax - 1)
            || (row == m_dimensions.xMax - 1 && col == 0)
            || (row == m_dimensions.xMax - 1 && col == m_dimensions.zMax - 1));
}

bool gameRoom::isWall(int row, int col) const {
    return ((row == 0 || col == 0 || row == m_dimensions.xMax - 1
             || col == m_dimensions.zMax - 1)
            && row < m_dimensions.xMax && col < m_dimensions.zMax && row >= 0
            && col >= 0 && !isCorner(row, col));
}

gameRoom::direction gameRoom::wallPosition(int row, int col) const {
    if (row == 0) {
        return direction::negX;
    } else if (row == m_dimensions.xMax - 1) {
        return direction::posX;
    } else if (col == 0) {
        return direction::negZ;
    } else if (col == m_dimensions.zMax - 1) {
        return direction::posZ;
    } else {
        return direction::NaD;
    }
}

void gameRoom::createFloorType(int row,
                               int col,
                               std::shared_ptr<Model>& model,
                               const accessTypes accessType) {
    assert(accessType == accessTypes::floor
           || accessType == accessTypes::floorEntity);

    m_accessible[getIndex(row, col)] = accessType;
    std::string name{GR_FLOOR + std::to_string(getIndex(row, col))};
    float rotationY = randomRotation();
    glm::vec3 rotation{0, rotationY, 0};

    // Set name and rotation storing depending on accessType
    if (accessType == accessTypes::floorEntity) {
        name = GR_ENTITY_FLOOR + std::to_string(getIndex(row, col));
        // Store angle for point generation
        m_rotationAngles.insert(
            {GR_ROTATION + std::to_string(getIndex(row, col)), rotationY});
    }

    glm::vec3 location{m_offset.xMin + row, 0, m_offset.zMin + col};
    glm::vec3 scale{GR_OBJ_SCALE, GR_OBJ_SCALE, GR_OBJ_SCALE};
    Object floorObj{name, model, location, rotation, scale};
    auto obj = m_objects.find(name);
    if (obj != m_objects.end()) {
        obj->second = floorObj;
    } else {
        m_objects.insert({name, floorObj});
    }
}

void gameRoom::createWallType(int row,
                              int col,
                              std::shared_ptr<Model>& model,
                              const accessTypes accessType) {
    assert(accessType == accessTypes::wall
           || accessType == accessTypes::wallEntity
           || accessType == accessTypes::door);
    // Set to wall for wall & wallEntity, this is because wall entities will
    // have no collision and can be treated the same
    m_accessible[getIndex(row, col)] = accessTypes::wall;
    std::string name{GR_WALL + std::to_string(getIndex(row, col))};
    if (accessType == accessTypes::wallEntity) {
        name = GR_ENTITY_WALL + std::to_string(getIndex(row, col));
    } else if (accessType == accessTypes::door) {
        name = GR_DOOR + std::to_string(getIndex(row, col));
        m_accessible[getIndex(row, col)] = accessTypes::door;
    }

    glm::vec3 location{m_offset.xMin + row, 0, m_offset.zMin + col};
    glm::vec3 scale{GR_OBJ_SCALE, GR_OBJ_SCALE, GR_OBJ_SCALE};
    glm::vec3 rotation{0, 0, 0};

    direction wallPos = wallPosition(row, col);
    switch (wallPos) {
        case direction::negZ:
            location.z += GR_WALL_OFFSET;
            rotation.y += 180;
            break;
        case direction::negX:
            location.x += GR_WALL_OFFSET;
            rotation.y = -90.f;
            break;
        case direction::posZ:
            location.z -= GR_WALL_OFFSET;
            break;
        case direction::posX:
            location.x -= GR_WALL_OFFSET;
            rotation.y = 90.f;
            break;
        default:
            throw std::runtime_error(
                "gameRoom::createWallType found no valid wall position.\n");
    }

    Object wallObj{name, model, location, rotation, scale};
    auto obj = m_objects.find(name);
    if (obj != m_objects.end()) {
        obj->second = wallObj;
    } else {
        m_objects.insert({name, wallObj});
    }
}

void gameRoom::addDecoration(float floorPercent, float wallPercent) {
    int targetFloorFill = (int)((float)m_dimensions.max * (floorPercent / 100));
    int targetWallFill = (int)((float)m_dimensions.max * (wallPercent / 100));
    int floorFill{0};
    int wallFill{0};
    int row{0}, col{0};

    std::mt19937 gen{static_cast<std::random_device::result_type>(m_seed)};
    std::uniform_int_distribution<> spawnDist{0, 1000};
    int floorMax = (int)m_models.floors.size() - 1;
    if (floorMax <= 0) {
        targetFloorFill = 0;
        floorMax = 1;  // For uniform distribution
    }
    int wallMax = (int)m_models.walls.size() - 1;
    if (wallMax <= 2) {
        targetWallFill = 0;
        wallMax = 2;  // For uniform distribution
    }

    // Dont include defaults / door
    std::uniform_int_distribution<> floorDist{1, floorMax};
    std::uniform_int_distribution<> wallDist{2, wallMax};

    int failCounter{0};
    const int failLimit{250};

    while ((floorFill != targetFloorFill || wallFill != targetWallFill)
           && failCounter < failLimit) {
        // 0.5% chance to spawn an entity
        if (spawnDist(gen) > 995) {
            if (m_accessible[getIndex(row, col)] == accessTypes::wall
                && wallFill != targetWallFill) {
                createWallType(row,
                               col,
                               m_models.walls[wallDist(gen)],
                               accessTypes::wallEntity);
                ++wallFill;

            } else if (m_accessible[getIndex(row, col)] == accessTypes::floor
                       && floorFill != targetFloorFill) {
                createFloorType(row,
                                col,
                                m_models.floors[floorDist(gen)],
                                accessTypes::floorEntity);
                ++floorFill;
                m_accessible[getIndex(row, col)] = accessTypes::floorEntity;
            } else {
                ++failCounter;
            }
        }

        ++row;
        if (row >= m_dimensions.xMax) {
            row = 0;
            ++col;
        }

        if (col >= m_dimensions.zMax) {
            col = 0;
        }
    }

    // Don't check, floor's empty
    if (floorFill == 0) {
        return;
    }

    // Walk from one row end to the other
    row = 1;
    bool doorFoundMin{false};
    bool doorFoundMax{false};
    int xCent = m_floor.xMax / 2;
    int zCent = m_floor.zMax / 2;
    for (col = 0; col <= m_floor.zMax; ++col) {
        if (m_accessible[getIndex(0, col)] == accessTypes::door) {
            walkRoom({row, col}, wallPosition(0, col));
            doorFoundMin = true;
        }

        if (m_accessible[getIndex(m_dimensions.xMax - 1, col)]
            == accessTypes::door) {
            walkRoom({m_floor.xMax, col},
                     wallPosition(m_dimensions.xMax - 1, col));
            doorFoundMax = true;
        }
    }

    if (!doorFoundMin) {
        walkRoom({1, zCent}, direction::negX);
    }
    if (!doorFoundMax) {
        walkRoom({m_floor.xMax, zCent}, direction::posX);
    }

    doorFoundMin = false;
    doorFoundMax = false;
    col = 1;
    for (row = 0; row <= m_floor.xMax; ++row) {
        if (m_accessible[getIndex(row, 0)] == accessTypes::door) {
            walkRoom({row, col}, wallPosition(row, 0));
            doorFoundMin = true;
        }

        if (m_accessible[getIndex(row, m_dimensions.zMax - 1)]
            == accessTypes::door) {
            walkRoom({row, m_floor.zMax},
                     wallPosition(row, m_dimensions.zMax - 1));
            doorFoundMax = true;
        }
    }

    if (!doorFoundMin) {
        walkRoom({xCent, 1}, direction::negZ);
    }
    if (!doorFoundMax) {
        walkRoom({xCent, m_floor.zMax}, direction::posZ);
    }
}

void gameRoom::walkRoom(std::pair<int, int> start, direction doorAxis) {
    if (doorAxis == NaD) {
        return;
    }

    // Door or wall centre
    int row = start.first;
    int col = start.second;

    // Walking positions
    int walkingStart{0};
    int walkingEnd{0};
    setWalkingStart(walkingStart, walkingEnd, doorAxis);

    // Strafe (side) checking
    int strafe{0};
    int strafeEnd{0};

    while (walkingStart != walkingEnd) {
        // Replace Entity if blocking
        if (isFloorEntity(row, col)) {
            removeFloorEntity(row, col);
            createFloorType(row, col, m_models.floors[0], accessTypes::floor);
        }

        // Check next step
        bool walk{false};
        bool swapped{false};
        setStrafe(strafe, strafeEnd, doorAxis, row, col);
        int startingStrafe = strafe;
        int startingRow = row, startingCol = col;

        while (strafe != strafeEnd) {
            std::pair<bool, bool> result = checkStrafeCollision(strafe,
                                                                doorAxis,
                                                                row,
                                                                col);

            // Current position is valid
            if (result.first && result.second) {
                walk = true;
                break;
            }

            // Check other direction
            if ((!result.first && !result.second) || strafe == strafeEnd) {
                if (swapped) {
                    break;
                }
                strafeEnd = 0;
                strafe = startingStrafe;
                swapped = true;
            }

            // Update strafe movement
            strafe = (strafe < strafeEnd) ? ++strafe : --strafe;
        }

        // If both directions failed, walk forward
        if (!walk) {
            row = startingRow;
            col = startingCol;
            walkForward(row, col, doorAxis);
        }

        // Increment / Decrement walking start
        updateWalking(walkingStart, doorAxis);
    }
}

void gameRoom::setWalkingStart(int& start, int& end, direction dir) {
    switch (dir) {
        case posX:
            start = m_floor.xMax;
            end = 0;
            return;
        case negX:
            start = 1;
            end = m_floor.xMax + 1;
            return;
        case posZ:
            start = m_floor.zMax;
            end = 0;
            return;
        case negZ:
            start = 1;
            end = m_floor.zMax + 1;
            return;
        default:
            throw std::runtime_error("gameRoom::setWalkingStart NaD\n");
    }
}

void gameRoom::walkForward(int& row, int& col, direction dir) {
    switch (dir) {
        case negX:
            ++row;
            return;
        case posX:
            --row;
            return;
        case negZ:
            ++col;
            return;
        case posZ:
            --col;
            return;
        default:
            throw std::runtime_error("gameRoom::walkForward NaD\n");
    }
}

std::pair<bool, bool> gameRoom::checkStrafeCollision(int strafe,
                                                     direction dir,
                                                     int& row,
                                                     int& col) const {
    if (dir == direction::negX || dir == direction::posX) {
        if (strafe <= m_floor.zMax && isFloor(row, strafe)) {
            if (dir == direction::posX) {
                if (isFloor(row - 1, strafe)) {
                    --row;
                    col = strafe;
                    return {true, true};
                }
            } else {
                if (isFloor(row + 1, strafe)) {
                    ++row;
                    col = strafe;
                    return {true, true};
                }
            }
            return {true, false};
        }
    } else {
        if (strafe <= m_floor.xMax && isFloor(strafe, col)) {
            if (dir == direction::posZ) {
                if (isFloor(strafe, col - 1)) {
                    row = strafe;
                    --col;
                    return {true, true};
                }
            } else {
                if (isFloor(strafe, col + 1)) {
                    row = strafe;
                    ++col;
                    return {true, true};
                }
            }
            return {true, false};
        }
    }
    return {false, false};
}

void gameRoom::setStrafe(int& strafe,
                         int& strafeEnd,
                         direction dir,
                         int row,
                         int col) const {
    strafe = (dir == direction::negX || dir == direction::posX) ? col : row;
    switch (dir) {
        case negX:
        case posX:
            strafeEnd = m_floor.zMax + 1;
            return;
        case posZ:
        case negZ:
            strafeEnd = m_floor.xMax + 1;
            return;
        case NaD:
            throw std::runtime_error("gameRoom::setStrafe NAD encountered\n");
    }
}

void gameRoom::updateWalking(int& walking, direction dir) {
    walking = (dir == direction::negX || dir == direction::negZ) ? ++walking
                                                                 : --walking;
}

bool gameRoom::isFloor(int row, int col) const {
    return m_accessible[getIndex(row, col)] == accessTypes::floor;
}

bool gameRoom::isFloorEntity(int row, int col) const {
    return m_accessible[getIndex(row, col)] == accessTypes::floorEntity;
}

void gameRoom::removeFloorEntity(int row, int col) {
    auto obj = m_objects.find(GR_ENTITY_FLOOR
                              + std::to_string(getIndex(row, col)));
    if (obj != m_objects.end()) {
        m_objects.erase(obj);
    }
}

std::size_t gameRoom::getIndex(int row, int col) const {
    return row * m_dimensions.zMax + col;
}

void gameRoom::draw() {
    for (auto& obj : m_objects) {
        obj.second.draw();
    }
}

void gameRoom::updateWallPointLocation(glm::vec3& location,
                                       direction wallPos) const {
    switch (wallPos) {
        case gameRoom::direction::negZ:
            location.z += GR_OBJ_SCALE;
            break;
        case gameRoom::direction::negX:
            location.x += GR_OBJ_SCALE;
            break;
        case gameRoom::direction::posZ:
            location.z -= GR_OBJ_SCALE;
            break;
        case gameRoom::direction::posX:
            location.x -= GR_OBJ_SCALE;
            break;
        default:
            throw std::runtime_error(
                "gameRoom::updateWallPointLocation found no valid wall "
                "position.\n");
    }
}

glm::vec3 gameRoom::getNormal(direction wallPos) const {
    switch (wallPos) {
        case gameRoom::direction::negZ:
            return m_normals.posZ;
        case gameRoom::direction::negX:
            return m_normals.posX;
        case gameRoom::direction::posZ:
            return m_normals.negZ;
        case gameRoom::direction::posX:
            return m_normals.negX;
        default:
            throw std::runtime_error(
                "gameRoom::getNormal found no valid wall position.\n");
    }
}

void gameRoom::insertWallPoints(int row,
                                int col,
                                std::vector<glm::vec3>& wall,
                                bool& pOneInserted,
                                int& wallCount,
                                direction dir) {
    assert(wall.size() == 3);
    direction wallPos = wallPosition(row, col);
    glm::vec3 point{m_offset.xMin + row, 0, m_offset.zMin + col};
    // Default on the x Axis
    bool lowerCorner = (col <= m_dimensions.zMax / 2);
    bool xAxisAligned{true};
    bool valid{dir == direction::negZ || dir == direction::posZ};

    if (wallPos == direction::negX || wallPos == direction::posX) {
        valid = dir == direction::negX || dir == direction::posX;
        lowerCorner = (row <= m_dimensions.xMax / 2);
        xAxisAligned = false;
    }

    if (m_accessible[getIndex(row, col)] == accessTypes::wall && valid) {
        updateWallPointLocation(point, wallPos);
        // Get the corner of the wall and set first point & normal
        if (!pOneInserted) {
            if (xAxisAligned) {
                point.x -= GR_CORNER_OFFSET;
            } else {
                point.z -= GR_CORNER_OFFSET;
            }
            wall[0] = point;
            wall[2] = getNormal(wallPos);
            pOneInserted = true;
            ++wallCount;
        } else {
            if (xAxisAligned) {
                point.x += GR_CORNER_OFFSET;
            } else {
                point.z += GR_CORNER_OFFSET;
            }
            wall[1] = point;
            ++wallCount;
        }
    } else if (pOneInserted) {
        // A one tile wall
        if (wallCount <= 1) {
            // Get the corner of the wall
            if (lowerCorner) {
                if (xAxisAligned) {
                    point.x -= GR_CORNER_OFFSET;
                    point.z += GR_CORNER_OFFSET;
                } else {
                    point.x += GR_CORNER_OFFSET;
                    point.z -= GR_CORNER_OFFSET;
                }
            } else {
                if (dir == negZ) {
                    point.x -= GR_CORNER_OFFSET;
                    point.z += GR_CORNER_OFFSET;
                } else {
                    point.x -= GR_CORNER_OFFSET;
                    point.z -= GR_CORNER_OFFSET;
                }
            }
            wall[1] = point;
        }
        m_wallPoints.push_back(wall);
        pOneInserted = false;
        wallCount = 0;
    }
}

void gameRoom::generateEntityBoundingSpheres() {
    for (int row = 1; row < m_dimensions.xMax; ++row) {
        for (int col = 1; col < m_dimensions.zMax; ++col) {
            // Add all entities
            if (m_accessible[getIndex(row, col)] == accessTypes::floorEntity) {
                auto obj = m_objects.find(GR_ENTITY_FLOOR
                                          + std::to_string(getIndex(row, col)));
                glm::vec3 centre = obj->second.model->boundingSphere.centreNoY;
                auto angle = m_rotationAngles.find(
                    GR_ROTATION + std::to_string(getIndex(row, col)));
                centre = glm::rotateY(centre, angle->second);
                centre.x += (float)(m_offset.xMin + row);
                centre.z += (float)(m_offset.zMin + col);
                float radius = obj->second.model->boundingSphere.radiusNoY
                               * GR_OBJ_SCALE;
                m_entityBoundingSpheres.emplace_back(centre, radius);
            }
        }
    }
}

void gameRoom::generateWallPoints() {
    std::vector<glm::vec3> wallMin(3);
    std::vector<glm::vec3> wallMax(3);

    bool pOneInsertedMin{false}, pOneInsertedMax{false};
    int wallCountMin{0}, wallCountMax{0};
    for (int row{1}; row < m_dimensions.xMax; ++row) {
        insertWallPoints(row,
                         0,
                         wallMin,
                         pOneInsertedMin,
                         wallCountMin,
                         direction::negZ);
        insertWallPoints(row,
                         m_dimensions.zMax - 1,
                         wallMax,
                         pOneInsertedMax,
                         wallCountMax,
                         direction::posZ);
    }
    // A wall that runs to the end of the row
    if (pOneInsertedMin) {
        m_wallPoints.push_back(wallMin);
    }
    if (pOneInsertedMax) {
        m_wallPoints.push_back(wallMax);
    }

    pOneInsertedMin = false;
    pOneInsertedMax = false;
    wallCountMin = 0;
    wallCountMax = 0;
    for (int col{1}; col < m_dimensions.zMax; ++col) {
        insertWallPoints(0,
                         col,
                         wallMin,
                         pOneInsertedMin,
                         wallCountMin,
                         direction::negX);

        insertWallPoints(m_dimensions.xMax - 1,
                         col,
                         wallMax,
                         pOneInsertedMax,
                         wallCountMax,
                         direction::posX);
    }
    // A wall that runs to the end of the col
    if (pOneInsertedMin) {
        m_wallPoints.push_back(wallMin);
    }
    if (pOneInsertedMax) {
        m_wallPoints.push_back(wallMax);
    }
}

void gameRoom::drawDebug() {
    if (!m_debugData) {
        generateDebugData();
    }
    glPushAttrib(GL_POLYGON_BIT | GL_LIGHTING_BIT);
    glDisable(GL_LIGHTING);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    for (auto& debug : m_debugObjects) {
        debug.draw();
    }
    glPopAttrib();
}

void gameRoom::generateDebugData() {
    std::string name{"debug"};
    glm::vec3 rotation{0};
    glm::vec3 scale{0.1f, 2, 0.1f};

    for (auto& wall : m_wallPoints) {
        m_debugObjects.emplace_back(name,
                                    m_models.debugCube,
                                    wall[0],
                                    rotation,
                                    scale);

        m_debugObjects.emplace_back(name,
                                    m_models.debugCube,
                                    wall[1],
                                    rotation,
                                    scale);
    }

    for (auto& sphere : m_entityBoundingSpheres) {
        glm::vec3 sScale{sphere.second};
        m_debugObjects.emplace_back(name,
                                    m_models.debugSphere,
                                    sphere.first,
                                    rotation,
                                    sScale);
    }
    m_debugData = true;
}