Files
OpenSceneGraph/src/osgPlugins/bsp/Q3BSPLoad.cpp
Robert Osfield bf8c3cc07e From Jason Daly, "This is a plugin (two, actually) that will allow OSG to load .bsp map files from Valve's Source Engine games (Half-Life 2, etc.). One plugin (called "vbsp" to distinguish it from the Quake 3 bsp loader) reads the .bsp file itself, and the other ("vtf") reads the texture files.
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.
2008-11-24 11:39:02 +00:00

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);
}