The set up for this to work is a bit more complex than most files, since the engine expects all files to be in a certain place, and it tends to mix case a lot. I tried to explain everything in the VBSP_README.txt file." This plugin has been integrated with the pre-exisiting bsp plugin.
280 lines
7.0 KiB
C++
280 lines
7.0 KiB
C++
|
|
#include "Q3BSPLoad.h"
|
|
|
|
|
|
using namespace bsp;
|
|
|
|
|
|
bool Q3BSPLoad::Load(const std::string& filename, int curveTessellation)
|
|
{
|
|
std::ifstream file(filename.c_str(),std::ios::binary);
|
|
if(!file.is_open())
|
|
{
|
|
//errorLog.OutputError("Unable to open %s", filename);
|
|
return false;
|
|
}
|
|
|
|
//read in header
|
|
file.read((char*)&m_header, sizeof(BSP_HEADER));
|
|
|
|
//check header data is correct
|
|
if( m_header.m_string[0]!='I' || m_header.m_string[1]!='B' ||
|
|
m_header.m_string[2]!='S' || m_header.m_string[3]!='P' ||
|
|
m_header.m_version !=0x2E )
|
|
{
|
|
//errorLog.OutputError("%s is not a version 0x2E .bsp map file", filename);
|
|
return false;
|
|
}
|
|
|
|
|
|
//Load in vertices
|
|
LoadVertices(file);
|
|
|
|
//Load in mesh indices
|
|
//Calculate number of indices
|
|
int numMeshIndices=m_header.m_directoryEntries[bspMeshIndices].m_length/sizeof(int);
|
|
|
|
//Create space
|
|
m_loadMeshIndices.resize(numMeshIndices);
|
|
|
|
//read in the mesh indices
|
|
file.seekg(m_header.m_directoryEntries[bspMeshIndices].m_offset,std::ios::beg);
|
|
file.read((char*) &m_loadMeshIndices[0], m_header.m_directoryEntries[bspMeshIndices].m_length);
|
|
|
|
|
|
//Load in faces
|
|
LoadFaces(file, curveTessellation);
|
|
|
|
//Load textures
|
|
LoadTextures(file);
|
|
|
|
//Load Lightmaps
|
|
LoadLightmaps(file);
|
|
|
|
//Load BSP Data
|
|
LoadBSPData(file);
|
|
|
|
//Load in entity string
|
|
m_entityString.resize(m_header.m_directoryEntries[bspEntities].m_length);
|
|
|
|
//Go to entity string in file
|
|
file.seekg(m_header.m_directoryEntries[bspEntities].m_offset,std::ios::beg);
|
|
file.read(&m_entityString[0], m_header.m_directoryEntries[bspEntities].m_length);
|
|
|
|
//errorLog.OutputSuccess("%s Loaded successfully", filename);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Q3BSPLoad::LoadVertices(std::ifstream& aFile)
|
|
{
|
|
//calculate number of vertices
|
|
int num_vertices=m_header.m_directoryEntries[bspVertices].m_length/sizeof(BSP_LOAD_VERTEX);
|
|
|
|
//Create space for this many BSP_LOAD_VERTICES
|
|
m_loadVertices.resize(num_vertices);
|
|
|
|
//go to vertices in file
|
|
aFile.seekg(m_header.m_directoryEntries[bspVertices].m_offset,std::ios::beg);
|
|
|
|
//read in the vertices
|
|
aFile.read((char*)&m_loadVertices[0], m_header.m_directoryEntries[bspVertices].m_length);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Q3BSPLoad::LoadFaces(std::ifstream& aFile, int /*curveTessellation*/)
|
|
{
|
|
//calculate number of load faces
|
|
int numTotalFaces=m_header.m_directoryEntries[bspFaces].m_length/sizeof(BSP_LOAD_FACE);
|
|
|
|
//Create space for this many BSP_LOAD_FACES
|
|
m_loadFaces.resize(numTotalFaces);
|
|
|
|
//go to faces in file
|
|
aFile.seekg(m_header.m_directoryEntries[bspFaces].m_offset,std::ios::beg);
|
|
|
|
//read in the faces
|
|
aFile.read((char*)&m_loadFaces[0], m_header.m_directoryEntries[bspFaces].m_length);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Q3BSPLoad::LoadTextures(std::ifstream& aFile)
|
|
{
|
|
//Calculate number of textures
|
|
int num_textures=m_header.m_directoryEntries[bspTextures].m_length/sizeof(BSP_LOAD_TEXTURE);
|
|
|
|
//Create space for this many BSP_LOAD_TEXTUREs
|
|
m_loadTextures.resize(num_textures);
|
|
|
|
//Load textures
|
|
aFile.seekg(m_header.m_directoryEntries[bspTextures].m_offset,std::ios::beg);
|
|
aFile.read((char*)&m_loadTextures[0], m_header.m_directoryEntries[bspTextures].m_length);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Q3BSPLoad::LoadLightmaps(std::ifstream& aFile)
|
|
{
|
|
//Calculate number of lightmaps
|
|
int num_lightmaps=m_header.m_directoryEntries[bspLightmaps].m_length/sizeof(BSP_LOAD_LIGHTMAP);
|
|
|
|
//Create space for this many BSP_LOAD_LIGHTMAPs
|
|
m_loadLightmaps.resize(num_lightmaps);
|
|
|
|
//Load textures
|
|
aFile.seekg(m_header.m_directoryEntries[bspLightmaps].m_offset,std::ios::beg);
|
|
aFile.read((char*)&m_loadLightmaps[0], m_header.m_directoryEntries[bspLightmaps].m_length);
|
|
|
|
//Change the gamma settings on the lightmaps (make them brighter)
|
|
float gamma=2.5f;
|
|
for(int i=0; i<num_lightmaps; ++i)
|
|
{
|
|
for(int j=0; j<128*128; ++j)
|
|
{
|
|
float r, g, b;
|
|
r=m_loadLightmaps[i].m_lightmapData[j*3+0];
|
|
g=m_loadLightmaps[i].m_lightmapData[j*3+1];
|
|
b=m_loadLightmaps[i].m_lightmapData[j*3+2];
|
|
|
|
r*=gamma/255.0f;
|
|
g*=gamma/255.0f;
|
|
b*=gamma/255.0f;
|
|
|
|
//find the value to scale back up
|
|
float scale=1.0f;
|
|
float temp;
|
|
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;
|
|
|
|
// scale up color values
|
|
scale*=255.0f;
|
|
r*=scale;
|
|
g*=scale;
|
|
b*=scale;
|
|
|
|
//fill data back in
|
|
m_loadLightmaps[i].m_lightmapData[j*3+0]=(unsigned char)r;
|
|
m_loadLightmaps[i].m_lightmapData[j*3+1]=(unsigned char)g;
|
|
m_loadLightmaps[i].m_lightmapData[j*3+2]=(unsigned char)b;
|
|
//m_loadLightmaps[i].m_lightmapData[j*3+0]=(GLubyte)255;
|
|
//m_loadLightmaps[i].m_lightmapData[j*3+1]=(GLubyte)255;
|
|
//m_loadLightmaps[i].m_lightmapData[j*3+2]=(GLubyte)255;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Q3BSPLoad::LoadBSPData(std::ifstream& aFile)
|
|
{
|
|
//Load leaves
|
|
//Calculate number of leaves
|
|
int numLeaves=m_header.m_directoryEntries[bspLeaves].m_length/sizeof(BSP_LOAD_LEAF);
|
|
|
|
//Create space for this many BSP_LOAD_LEAFS
|
|
m_loadLeaves.resize(numLeaves);
|
|
|
|
//Load leaves
|
|
aFile.seekg(m_header.m_directoryEntries[bspLeaves].m_offset,std::ios::beg);
|
|
aFile.read((char*)&m_loadLeaves[0], m_header.m_directoryEntries[bspLeaves].m_length);
|
|
|
|
|
|
|
|
|
|
//Load leaf faces array
|
|
int num_leaf_faces=m_header.m_directoryEntries[bspLeafFaces].m_length/sizeof(int);
|
|
|
|
//Create space for this many leaf faces
|
|
m_loadLeafFaces.resize(num_leaf_faces);
|
|
|
|
//Load leaf faces
|
|
aFile.seekg(m_header.m_directoryEntries[bspLeafFaces].m_offset,std::ios::beg);
|
|
aFile.read((char*)&m_loadLeafFaces[0], m_header.m_directoryEntries[bspLeafFaces].m_length);
|
|
|
|
|
|
|
|
|
|
|
|
//Load Planes
|
|
int num_planes=m_header.m_directoryEntries[bspPlanes].m_length/sizeof(BSP_LoadPlane);
|
|
|
|
//Create space for this many planes
|
|
m_loadPlanes.resize(num_planes);
|
|
|
|
aFile.seekg(m_header.m_directoryEntries[bspPlanes].m_offset,std::ios::beg);
|
|
aFile.read((char*)&m_loadPlanes[0], m_header.m_directoryEntries[bspPlanes].m_length);
|
|
|
|
|
|
|
|
//Load nodes
|
|
int num_nodes=m_header.m_directoryEntries[bspNodes].m_length/sizeof(BSP_NODE);
|
|
|
|
//Create space for this many nodes
|
|
m_loadNodes.resize(num_nodes);
|
|
|
|
aFile.seekg(m_header.m_directoryEntries[bspNodes].m_offset,std::ios::beg);
|
|
aFile.read((char*)&m_loadNodes[0], m_header.m_directoryEntries[bspNodes].m_length);
|
|
|
|
|
|
|
|
//Load visibility data
|
|
//load numClusters and bytesPerCluster
|
|
aFile.seekg(m_header.m_directoryEntries[bspVisData].m_offset,std::ios::beg);
|
|
aFile.read((char*)&m_loadVisibilityData, 2 * sizeof(int));
|
|
|
|
//Calculate the size of the bitset
|
|
int bitsetSize=m_loadVisibilityData.m_numClusters*m_loadVisibilityData.m_bytesPerCluster;
|
|
|
|
//Create space for bitset
|
|
m_loadVisibilityData.m_bitset.resize(bitsetSize);
|
|
//read bitset
|
|
aFile.read((char*)&m_loadVisibilityData.m_bitset[0], bitsetSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|