#pragma once
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW
#include <GL/glew.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#define FACE_POLYGON 1
enum LUMPS
{
LUMP_ENTITIES = 0, // Game-related object descriptions
LUMP_TEXTURE, // Surface descriptions.
LUMP_PLANES, // Planes used by map geometry.
LUMP_NODES, // BSP tree nodes.
LUMP_LEAFS, // BSP tree leaves.
LUMP_LEAFFACES, // Lists of face indices, one list per leaf.
LUMP_LEAFBRUSHES, // Lists of brush indices, one list per leaf.
LUMP_MODELS, // Descriptions of rigid world geometry in map.
LUMP_BRUSHES, // Convex polyhedra used to describe solid space.
LUMP_BRUSHSIDES, // Brush surfaces.
LUMP_VERTEXES, // Vertices used to describe faces.
LUMP_INDICES, // Lists of offsets, one list per mesh.
LUMP_EFFECTS, // List of special map effects.
LUMP_FACES, // Surface geometry.
LUMP_LIGHTMAPS, // Packed lightmap data.
LUMP_LIGHTVOLS, // Local illumination data.
LUMP_VISDATA, // Cluster-cluster visibility data.
LUMP_ALL_DATA // A constant to store the number of lumps
};
struct Lump
{
int offset;
int length;
};
struct Header
{
char magic[4]; // Magic number.Always "IBSP".
int version; // Version number. 0x2e for the BSP files distributed with Quake 3.
};
struct Faces
{
int textureID; // The index into the texture array
int effect; // The index for the effects (or -1 = n/a)
int type; // 1=polygon, 2=patch, 3=mesh, 4=billboard
int startVertIndex; // The starting index into this face's first vertex
int numOfVerts; // The number of vertices for this face
int startIndex; // The starting index into the indices array for this face
int numOfIndices; // The number of indices for this face
int lightmapID; // The texture index for the lightmap
int lMapCorner[2]; // The face's lightmap corner in the image
int lMapSize[2]; // The size of the lightmap section
glm::vec3 lMapPos; // The 3D origin of lightmap.
glm::vec3 lMapVecs[2]; // The 3D space for s and t unit vectors.
glm::vec3 vNormal; // The face normal.
int size[2]; // The bezier patch dimensions.
};
struct Vertexes
{
glm::vec3 position; // vertex position
glm::vec2 texCoord; // vertex texture coords
glm::vec2 lightMapCoord; // vertex lightmap coords
glm::vec3 normal; // vertex normal
char color[4]; // vertex color
};
struct Meshverts
{
int offset; // Vertex index offset, relative to first vertex of corresponding face.
};
struct Textures
{
char name[64]; // Texture name.
int flags; // Surface flags.
int contents; // Content flags.
};
class BSPLoader
{
public:
void LoadBSP(const char* bspFile);
void DrawBSP();
void DrawFaces(int index);
GLuint numOfFaces;
GLuint numOfVertexes;
GLuint numOfIndices;
GLuint numOfTextures;
Faces* pointerFaces;
Vertexes* pointerVertexes;
Meshverts* pointerIndices;
Textures* pointerTextures;
GLuint indiceVbo;
Faces* pFace;
unsigned int maxTextures[1000];
private:
};
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
// Include GLEWa
#include <GL/glew.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <maps/bspLoader.hpp>
#include <common/texture.hpp>
void BSPLoader::LoadBSP(const char* bspFile)
{
FILE* file = std::fopen(bspFile, "rb");
std::printf("Successfully opened %s\n", bspFile);
Header head = { 0 };
Lump lump[LUMPS::LUMP_ALL_DATA] = { 0 };
// read through header and lump data
std::fread(&head, 1, sizeof(Header), file);
std::fread(lump, LUMPS::LUMP_ALL_DATA, sizeof(Lump), file);
numOfFaces = lump[LUMPS::LUMP_FACES].length / sizeof(Faces); // as specified by the Q3 map specs, divide the length of the lump itself by the sizeof the struct
pointerFaces = new Faces[numOfFaces]; // allocate memory for the faces pointer
numOfVertexes = lump[LUMPS::LUMP_VERTEXES].length / sizeof(Vertexes);
pointerVertexes = new Vertexes[numOfVertexes];
numOfIndices = lump[LUMPS::LUMP_INDICES].length / sizeof(Meshverts);
pointerIndices = new Meshverts[numOfIndices];
std::fseek(file, lump[LUMPS::LUMP_VERTEXES].offset, SEEK_SET);
for (int i = 0; i < numOfVertexes; i++)
{
printf("Vertexes = %i\n", i);
std::fread(&pointerVertexes[0], sizeof(pointerVertexes[0]), numOfVertexes, file);
}
std::fseek(file, lump[LUMPS::LUMP_INDICES].offset, SEEK_SET);
std::fread(&pointerIndices[0], sizeof(pointerIndices), numOfIndices, file);
std::fseek(file, lump[LUMPS::LUMP_FACES].offset, SEEK_SET);
std::fread(&pointerFaces[0], sizeof(pointerFaces), numOfFaces, file);
std::fclose(file);
}
void BSPLoader::DrawFaces(int index)
{
Faces* pFace = &pointerFaces[index];
glVertexPointer(3, GL_FLOAT, sizeof(Vertexes), &(pointerVertexes[pFace->startVertIndex].position));
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLES, numOfIndices, GL_UNSIGNED_INT, &(pointerIndices[pFace->startIndex]));
}
void BSPLoader::DrawBSP()
{
for (int i = 0; i < numOfFaces; i++) // go through faces
{
if (pointerFaces[i].type != FACE_POLYGON)
{
continue;
}
DrawFaces(i);
}
}
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw/glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <common/shader.hpp>
#include <common/texture.hpp>
#include <common/controls.hpp>
#include <maps/bspLoader.hpp>
BSPLoader bsp;
int main(void)
{
// Initialise GLFW
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow(1024, 768, "Vire", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Hide the mouse and enable unlimited mouvement
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set the mouse at the center of the screen
glfwPollEvents();
glfwSetCursorPos(window, 1024 / 2, 768 / 2);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
// Cull triangles which normal is not towards the camera
glEnable(GL_CULL_FACE);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders("TransformVertexShader.vertexshader", "TextureFragmentShader.fragmentshader");
// Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
// Load the texture
GLuint Texture = loadDDS("uvtemplate.DDS");
// Get a handle for our "myTextureSampler" uniform
GLuint TextureID = glGetUniformLocation(programID, "myTextureSampler");
// Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle.
// A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
// Two UV coordinatesfor each vertex. They were created with Blender.
static const GLfloat g_uv_buffer_data[] = {
0.000059f, 0.000004f,
0.000103f, 0.336048f,
0.335973f, 0.335903f,
1.000023f, 0.000013f,
0.667979f, 0.335851f,
0.999958f, 0.336064f,
0.667979f, 0.335851f,
0.336024f, 0.671877f,
0.667969f, 0.671889f,
1.000023f, 0.000013f,
0.668104f, 0.000013f,
0.667979f, 0.335851f,
0.000059f, 0.000004f,
0.335973f, 0.335903f,
0.336098f, 0.000071f,
0.667979f, 0.335851f,
0.335973f, 0.335903f,
0.336024f, 0.671877f,
1.000004f, 0.671847f,
0.999958f, 0.336064f,
0.667979f, 0.335851f,
0.668104f, 0.000013f,
0.335973f, 0.335903f,
0.667979f, 0.335851f,
0.335973f, 0.335903f,
0.668104f, 0.000013f,
0.336098f, 0.000071f,
0.000103f, 0.336048f,
0.000004f, 0.671870f,
0.336024f, 0.671877f,
0.000103f, 0.336048f,
0.336024f, 0.671877f,
0.335973f, 0.335903f,
0.667969f, 0.671889f,
1.000004f, 0.671847f,
0.667979f, 0.335851f
};
GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_uv_buffer_data), g_uv_buffer_data, GL_STATIC_DRAW);
bsp.LoadBSP("maps/Level.bsp");
bsp.DrawBSP();
do
{
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
// Compute the MVP matrix from keyboard and mouse input
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
// Set our "myTextureSampler" sampler to user Texture Unit 0
glUniform1i(TextureID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_VERTEX_ARRAY, bsp.numOfFaces);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
2, // size : U+V => 2
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
bsp.DrawBSP();
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Cleanup VBO and shader
glDeleteBuffers(1, &uvbuffer);
glDeleteProgram(programID);
glDeleteTextures(1, &TextureID);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}