#include "Main.h"
#include "Camera.h"
#include "Quake3Bsp.h"
#include "Frustum.h"
// This is our maximum height that the user can climb over
const float kMaxStepHeight = 10.0f;
// We use the camera in our TryToStep() function so we extern the global camera
extern CCamera g_Camera;
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// This is our global frustum class, which is used to cull BSP leafs
extern CFrustum g_Frustum;
// This will store how many faces are drawn and are seen by the camera
extern int g_VisibleFaces;
// This tells us if we want to render the lightmaps
extern bool g_bLightmaps;
// This holds the gamma value that was stored in the config file
extern float g_Gamma;
// This tells us if we want to render the textures
extern bool g_bTextures;
//////////////////////////// CQUAKE3BSP \\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This is our object's constructor to initial all it's data members
/////
//////////////////////////// CQUAKE3BSP \\\\\\\\\\\\\\\\\\\\\\\\\\\*
CQuake3BSP::CQuake3BSP()
{
// Here we simply initialize our member variables to 0
m_numOfVerts = 0;
m_numOfFaces = 0;
m_numOfIndices = 0;
m_numOfTextures = 0;
m_numOfLightmaps = 0;
m_numOfNodes = 0;
m_numOfLeafs = 0;
m_numOfLeafFaces = 0;
m_numOfPlanes = 0;
m_numOfBrushes = 0;
m_numOfBrushSides = 0;
m_numOfLeafBrushes = 0;
m_traceRatio = 0;
m_traceType = 0;
m_traceRadius = 0;
bool m_bCollided = false;
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// Initialize our variables to start off
bool m_bGrounded = false;
bool m_bTryStep = false;
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// We need to initialize our Min and Max and Extent variables
m_vTraceMins = CVector3(0, 0, 0);
m_vTraceMaxs = CVector3(0, 0, 0);
m_vExtents = CVector3(0, 0, 0);
// This will store the normal of the plane we collided with
m_vCollisionNormal = CVector3(0, 0, 0);
// Initialize all the dynamic BSP data pointers to NULL
m_pVerts = NULL;
m_pFaces = NULL;
m_pIndices = NULL;
m_pNodes = NULL;
m_pLeafs = NULL;
m_pPlanes = NULL;
m_pLeafFaces = NULL;
memset(&m_clusters, 0, sizeof(tBSPVisData));
// Here we initialize our dynamic arrays of data for the brush information of the BSP
m_pBrushes = NULL;
m_pBrushSides = NULL;
m_pTextures = NULL;
m_pLeafBrushes = NULL;
}
//////////////////////////// CHANGE GAMMA \\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This manually changes the gamma of an image
/////
//////////////////////////// CHANGE GAMMA \\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CQuake3BSP::ChangeGamma(byte *pImage, int size, float factor)
{
// Go through every pixel in the lightmap
for(int i = 0; i < size / 3; i++, pImage += 3)
{
float scale = 1.0f, temp = 0.0f;
float r = 0, g = 0, b = 0;
// extract the current RGB values
r = (float)pImage[0];
g = (float)pImage[1];
b = (float)pImage[2];
// Multiply the factor by the RGB values, while keeping it to a 255 ratio
r = r * factor / 255.0f;
g = g * factor / 255.0f;
b = b * factor / 255.0f;
// Check if the the values went past the highest value
if(r > 1.0f && (temp = (1.0f/r)) < scale) scale=temp;
if(g > 1.0f && (temp = (1.0f/g)) < scale) scale=temp;
if(b > 1.0f && (temp = (1.0f/b)) < scale) scale=temp;
// Get the scale for this pixel and multiply it by our pixel values
scale*=255.0f;
r*=scale; g*=scale; b*=scale;
// Assign the new gamma'nized RGB values to our image
pImage[0] = (byte)r;
pImage[1] = (byte)g;
pImage[2] = (byte)b;
}
}
////////////////////////////// CREATE LIGHTMAP TEXTURE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This creates a texture map from the light map image bits
/////
////////////////////////////// CREATE LIGHTMAP TEXTURE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CQuake3BSP::CreateLightmapTexture(UINT &texture, byte *pImageBits, int width, int height)
{
// Generate a texture with the associative texture ID stored in the array
glGenTextures(1, &texture);
// This sets the alignment requirements for the start of each pixel row in memory.
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
// Bind the texture to the texture arrays index and init the texture
glBindTexture(GL_TEXTURE_2D, texture);
// Change the lightmap gamma values by our desired gamma
ChangeGamma(pImageBits, width*height*3, g_Gamma);
// Build Mipmaps (builds different versions of the picture for distances - looks better)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, pImageBits);
//Assign the mip map levels
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
//////////////////////////// FIND TEXTURE EXTENSION \\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This attaches the image extension to the texture name, if found
/////
//////////////////////////// FIND TEXTURE EXTENSION \\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CQuake3BSP::FindTextureExtension(char *strFileName)
{
char strJPGPath[MAX_PATH] = {0};
char strTGAPath[MAX_PATH] = {0};
FILE *fp = NULL;
// Get the current path we are in
GetCurrentDirectory(MAX_PATH, strJPGPath);
// Add on a '\' and the file name to the end of the current path.
// We create 2 seperate strings to test each image extension.
strcat(strJPGPath, "\\");
strcat(strJPGPath, strFileName);
strcpy(strTGAPath, strJPGPath);
// Add the extensions on to the file name and path
strcat(strJPGPath, ".jpg");
strcat(strTGAPath, ".tga");
// Check if there is a jpeg file with the texture name
if((fp = fopen(strJPGPath, "rb")) != NULL)
{
// If so, then let's add ".jpg" onto the file name and return
strcat(strFileName, ".jpg");
return;
}
// Check if there is a targa file with the texture name
if((fp = fopen(strTGAPath, "rb")) != NULL)
{
// If so, then let's add a ".tga" onto the file name and return
strcat(strFileName, ".tga");
return;
}
}
//////////////////////////// LOAD BSP \\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This loads in all of the .bsp data for the level
/////
//////////////////////////// LOAD BSP \\\\\\\\\\\\\\\\\\\\\\\\\\\*
bool CQuake3BSP::LoadBSP(const char *strFileName)
{
FILE *fp = NULL;
int i = 0;
// Check if the .bsp file could be opened
if((fp = fopen(strFileName, "rb")) == NULL)
{
// Display an error message and quit if the file can't be found.
MessageBox(g_hWnd, "Could not find BSP file!", "Error", MB_OK);
return false;
}
// Initialize the header and lump structures
tBSPHeader header = {0};
tBSPLump lumps[kMaxLumps] = {0};
// Read in the header and lump data
fread(&header, 1, sizeof(tBSPHeader), fp);
fread(&lumps, kMaxLumps, sizeof(tBSPLump), fp);
// Now we know all the information about our file. We can
// then allocate the needed memory for our member variables.
// Allocate the vertex memory
m_numOfVerts = lumps[kVertices].length / sizeof(tBSPVertex);
m_pVerts = new tBSPVertex [m_numOfVerts];
// Allocate the face memory
m_numOfFaces = lumps[kFaces].length / sizeof(tBSPFace);
m_pFaces = new tBSPFace [m_numOfFaces];
// Allocate the index memory
m_numOfIndices = lumps[kIndices].length / sizeof(int);
m_pIndices = new int [m_numOfIndices];
// Allocate memory to read in the texture information.
m_numOfTextures = lumps[kTextures].length / sizeof(tBSPTexture);
m_pTextures = new tBSPTexture [m_numOfTextures];
// Allocate memory to read in the lightmap data.
m_numOfLightmaps = lumps[kLightmaps].length / sizeof(tBSPLightmap);
tBSPLightmap *pLightmaps = new tBSPLightmap