/**
* Simple Q3 Map loader.
*
* For comments or bug reports, contact : nicolas.baudrey@wanadoo.fr
*/
#include "Q3Loader.h"
#pragma pack(push, Q3LOADER_H)
#include <cstdio>
#pragma pack(pop, Q3LOADER_H)
/**
* Check if the header of the map is valid.
*
* @param pMap The map to test.
*
* @return True if the map is valid, false otherwise.
*/
bool isValid(const TMapQ3& pMap)
{
// Check if the header is equal to ID Software Magic Number.
if
(strncmp(pMap.mHeader.mMagicNumber, cMagicNumber.c_str(), 4) != 0)
{
return false;
}
// Check if the version number is equal to the Q3 map.
if
(pMap.mHeader.mVersion != cVersion)
{
return false;
}
return true;
}
/**
* Read the header of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
bool readHeader(FILE* pFile, TMapQ3& pMap)
{
fread(&pMap.mHeader, 1, sizeof(THeader), pFile);
return isValid(pMap);
}
/**
* Read the texture lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readTexture(FILE* pFile, TMapQ3& pMap)
{
int lNbTextures = pMap.mHeader.mLumpes[cTextureLump].mLength / sizeof(TTexture);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cTextureLump].mOffset, SEEK_SET);
for
(int lTextureCounter = 0; lTextureCounter < lNbTextures; ++lTextureCounter)
{
TTexture lTexture;
fread(&lTexture, 1, sizeof(TTexture), pFile);
pMap.mTextures.push_back(lTexture);
}
}
/**
* Read the entity lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readEntity(FILE* pFile, TMapQ3& pMap)
{
// Set the entity size.
pMap.mEntity.mSize = pMap.mHeader.mLumpes[cEntityLump].mLength;
// Allocate the entity buffer.
pMap.mEntity.mBuffer = new char[pMap.mEntity.mSize];
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cEntityLump].mOffset, SEEK_SET);
// Read the buffer.
fread(pMap.mEntity.mBuffer, pMap.mEntity.mSize, sizeof(char), pFile);
};
/**
* Read the plane lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readPlane(FILE* pFile, TMapQ3& pMap)
{
int lNbPlanes = pMap.mHeader.mLumpes[cPlaneLump].mLength / sizeof(TPlane);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cPlaneLump].mOffset, SEEK_SET);
for
(int lPlaneCounter = 0; lPlaneCounter < lNbPlanes; ++lPlaneCounter)
{
TPlane lPlane;
fread(&lPlane, 1, sizeof(TPlane), pFile);
pMap.mPlanes.push_back(lPlane);
}
}
/**
* Read the node lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readNode(FILE* pFile, TMapQ3& pMap)
{
int lNbNodes = pMap.mHeader.mLumpes[cNodeLump].mLength / sizeof(TNode);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cNodeLump].mOffset, SEEK_SET);
for
(int lNodeCounter = 0; lNodeCounter < lNbNodes; ++lNodeCounter)
{
TNode lNode;
fread(&lNode, 1, sizeof(TNode), pFile);
pMap.mNodes.push_back(lNode);
}
}
/**
* Read the leaf lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readLeaf(FILE* pFile, TMapQ3& pMap)
{
int lNbLeaves = pMap.mHeader.mLumpes[cLeafLump].mLength / sizeof(TLeaf);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cLeafLump].mOffset, SEEK_SET);
for
(int lLeafCounter = 0; lLeafCounter < lNbLeaves; ++lLeafCounter)
{
TLeaf lLeaf;
fread(&lLeaf, 1, sizeof(TLeaf), pFile);
pMap.mLeaves.push_back(lLeaf);
}
}
/**
* Read the leafface lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readLeafFace(FILE* pFile, TMapQ3& pMap)
{
int lNbLeafFaces = pMap.mHeader.mLumpes[cLeafFaceLump].mLength / sizeof(TLeafFace);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cLeafFaceLump].mOffset, SEEK_SET);
for
(int lLeafFaceCounter = 0; lLeafFaceCounter < lNbLeafFaces; ++lLeafFaceCounter)
{
TLeafFace lLeafFace;
fread(&lLeafFace, 1, sizeof(TLeafFace), pFile);
pMap.mLeafFaces.push_back(lLeafFace);
}
}
/**
* Read the leafbrush lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readLeafBrush(FILE* pFile, TMapQ3& pMap)
{
int lNbLeafBrushes = pMap.mHeader.mLumpes[cLeafBrushLump].mLength / sizeof(TLeafBrush);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cLeafBrushLump].mOffset, SEEK_SET);
for
(int lLeafBrusheCounter = 0; lLeafBrusheCounter < lNbLeafBrushes; ++lLeafBrusheCounter)
{
TLeafBrush lLeafBrush;
fread(&lLeafBrush, 1, sizeof(TLeafBrush), pFile);
pMap.mLeafBrushes.push_back(lLeafBrush);
}
}
/**
* Read the model lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readModel(FILE* pFile, TMapQ3& pMap)
{
int lNbModels = pMap.mHeader.mLumpes[cModelLump].mLength / sizeof(TModel);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cModelLump].mOffset, SEEK_SET);
for
(int lModelCounter = 0; lModelCounter < lNbModels; ++lModelCounter)
{
TModel lModel;
fread(&lModel, 1, sizeof(TModel), pFile);
pMap.mModels.push_back(lModel);
}
}
/**
* Read the brush lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readBrush(FILE* pFile, TMapQ3& pMap)
{
int lNbBrushes = pMap.mHeader.mLumpes[cBrushLump].mLength / sizeof(TBrush);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cBrushLump].mOffset, SEEK_SET);
for
(int lBrusheCounter = 0; lBrusheCounter < lNbBrushes; ++lBrusheCounter)
{
TBrush lBrush;
fread(&lBrush, 1, sizeof(TBrush), pFile);
pMap.mBrushes.push_back(lBrush);
}
}
/**
* Read the brush side lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readBrushSide(FILE* pFile, TMapQ3& pMap)
{
int lNbBrushSides = pMap.mHeader.mLumpes[cBrushSideLump].mLength / sizeof(TBrushSide);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cBrushSideLump].mOffset, SEEK_SET);
for
(int lBrushSideCounter = 0; lBrushSideCounter < lNbBrushSides; ++lBrushSideCounter)
{
TBrushSide lBrushSide;
fread(&lBrushSide, 1, sizeof(TBrushSide), pFile);
pMap.mBrushSides.push_back(lBrushSide);
}
}
/**
* Read the vertex lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readVertex(FILE* pFile, TMapQ3& pMap)
{
int lNbVertices = pMap.mHeader.mLumpes[cVertexLump].mLength / sizeof(TVertex);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cVertexLump].mOffset, SEEK_SET);
for
(int lVerticeCounter = 0; lVerticeCounter < lNbVertices; ++lVerticeCounter)
{
TVertex lVertex;
fread(&lVertex, 1, sizeof(TVertex), pFile);
pMap.mVertices.push_back(lVertex);
}
}
/**
* Read the meshvert lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readMeshVert(FILE* pFile, TMapQ3& pMap)
{
int lNbMeshVertices = pMap.mHeader.mLumpes[cMeshVertLump].mLength / sizeof(TMeshVert);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cMeshVertLump].mOffset, SEEK_SET);
for
(int lVerticeCounter = 0; lVerticeCounter < lNbMeshVertices; ++lVerticeCounter)
{
TMeshVert lMeshVertex;
fread(&lMeshVertex, 1, sizeof(TMeshVert), pFile);
pMap.mMeshVertices.push_back(lMeshVertex);
}
}
/**
* Read the effect lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readEffect(FILE* pFile, TMapQ3& pMap)
{
int lNbEffects = pMap.mHeader.mLumpes[cEffectLump].mLength / sizeof(TEffect);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cEffectLump].mOffset, SEEK_SET);
for
(int lEffectCounter = 0; lEffectCounter < lNbEffects; ++lEffectCounter)
{
TEffect lEffect;
fread(&lEffect, 1, sizeof(TEffect), pFile);
pMap.mEffects.push_back(lEffect);
}
}
/**
* Read the face lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readFace(FILE* pFile, TMapQ3& pMap)
{
int lNbFaces = pMap.mHeader.mLumpes[cFaceLump].mLength / sizeof(TFace);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cFaceLump].mOffset, SEEK_SET);
for
(int lFaceCounter = 0; lFaceCounter < lNbFaces; ++lFaceCounter)
{
TFace lFace;
fread(&lFace, 1, sizeof(TFace), pFile);
pMap.mFaces.push_back(lFace);
}
}
/**
* Read the effect lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readLightMap(FILE* pFile, TMapQ3& pMap)
{
int lNbLightMaps = pMap.mHeader.mLumpes[cLightMapLump].mLength / sizeof(TLightMap);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cLightMapLump].mOffset, SEEK_SET);
for
(int lLightMapCounter = 0; lLightMapCounter < lNbLightMaps; ++lLightMapCounter)
{
TLightMap lLightMap;
fread(&lLightMap, 1, sizeof(TLightMap), pFile);
pMap.mLightMaps.push_back(lLightMap);
}
}
/**
* Read the effect lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readLightVol(FILE* pFile, TMapQ3& pMap)
{
int lNbLightVols = pMap.mHeader.mLumpes[cLightVolLump].mLength / sizeof(TLightVol);
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cLightVolLump].mOffset, SEEK_SET);
for
(int lLightVolCounter = 0; lLightVolCounter < lNbLightVols; ++lLightVolCounter)
{
TLightVol lLightVol;
fread(&lLightVol, 1, sizeof(TLightVol), pFile);
pMap.mLightVols.push_back(lLightVol);
}
}
/**
* Read the effect lump of the Q3 map.
*
* @param pFile The stream on the Q3 file data.
* @param pMap The map structure to fill.
*/
void readVisData(FILE* pFile, TMapQ3& pMap)
{
// Go to the start of the chunk.
fseek(pFile, pMap.mHeader.mLumpes[cVisDataLump].mOffset, SEEK_SET);
fread(&pMap.mVisData.mNbClusters, 1, sizeof(int), pFile);
fread(&pMap.mVisData.mBytesPerCluster, 1, sizeof(int), pFile);
// Allocate the buffer.
int lBufferSize = pMap.mVisData.mNbClusters * pMap.mVisData.mBytesPerCluster;
pMap.mVisData.mBuffer = new unsigned char[lBufferSize];
fread(pMap.mVisData.mBuffer, lBufferSize, sizeof(unsigned char), pFile);
}
/**
* Dump all the Q3 map in a text file.
* Must be used only for debug purpose.
*
* @param pFile The file to dump the informations.
* @param pMap The Q3 map to dump in string.
*/
void debugInformations(const TMapQ3& pMap, FILE* pFile)
{
// Check if the given stream is valid.
if
(! pFile)
{
printf("debugInformations :: Invalid stream handle.\n");
return ;
}
// Check if the map is valid.
if
(! isValid(pMap))
{
printf("debugInformations :: Invalid Q3 map header.\n");
return;
}
fprintf(pFile, "********* Header *********\n");
fprintf(pFile, "Magic Number : %s\n", pMap.mHeader.mMagicNumber);
fprintf(pFile, "Version : %d\n", pMap.mHeader.mVersion);
for
(int lLumpCounter = 0; lLumpCounter < 17; ++lLumpCounter)
{
fprintf(pFile, "Lump %d\n", lLumpCounter);
fprintf(pFile, "\tOffset : %d\n", pMap.mHeader.mLumpes[lLumpCounter].mOffset);
fprintf(pFile, "\tLength : %d\n", pMap.mHeader.mLumpes[lLumpCounter].mLength);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Entity Lump *********\n");
fprintf(pFile, "Size : %d\n", pMap.mEntity.mSize);
if
(pMap.mEntity.mSize != 0)
{
fprintf(pFile, "Buffer : %s\n", pMap.mEntity.mBuffer);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Texture Lump *********\n");
for
(int lTextureCounter = 0; lTextureCounter < pMap.mTextures.size(); ++lTextureCounter)
{
fprintf(pFile, "Texture %d\n", lTextureCounter);
fprintf(pFile, "\tName : %s\n", pMap.mTextures[lTextureCounter].mName);
fprintf(pFile, "\tFlags : %d\n", pMap.mTextures[lTextureCounter].mFlags);
fprintf(pFile, "\tContents : %d\n", pMap.mTextures[lTextureCounter].mContents);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Plane Lump *********\n");
for
(int lPlaneCounter = 0; lPlaneCounter < pMap.mPlanes.size(); ++lPlaneCounter)
{
fprintf(pFile, "Plane %d\n", lPlaneCounter);
fprintf(pFile, "\tNormal : %f %f %f\n", pMap.mPlanes[lPlaneCounter].mNormal[0], pMap.mPlanes[lPlaneCounter].mNormal[1], pMap.mPlanes[lPlaneCounter].mNormal[2]);
fprintf(pFile, "\tDistance : %f\n", pMap.mPlanes[lPlaneCounter].mDistance);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Node Lump *********\n");
for
(int lNodeCounter = 0; lNodeCounter < pMap.mNodes.size(); ++lNodeCounter)
{
fprintf(pFile, "Node %d\n", lNodeCounter);
fprintf(pFile, "\tPlane index : %d\n", pMap.mNodes[lNodeCounter].mPlane);
fprintf(pFile, "\tChildren index : %d %d\n", pMap.mNodes[lNodeCounter].mChildren[0], pMap.mNodes[lNodeCounter].mChildren[1]);
fprintf(pFile, "\tMin Bounding Box : %d %d %d\n", pMap.mNodes[lNodeCounter].mMins[0], pMap.mNodes[lNodeCounter].mMins[1], pMap.mNodes[lNodeCounter].mMins[2]);
fprintf(pFile, "\tMax Bounding Box : %d %d %d\n", pMap.mNodes[lNodeCounter].mMaxs[0], pMap.mNodes[lNodeCounter].mMaxs[1], pMap.mNodes[lNodeCounter].mMaxs[2]);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Leaf Lump *********\n");
for
(int lLeafCounter = 0; lLeafCounter < pMap.mLeaves.size(); ++lLeafCounter)
{
fprintf(pFile, "Leaf %d\n", lLeafCounter);
fprintf(pFile, "\tCluster %d\n", pMap.mLeaves[lLeafCounter].mCluster);
fprintf(pFile, "\tMin Bounding Box : %d %d %d\n", pMap.mLeaves[lLeafCounter].mMins[0], pMap.mLeaves[lLeafCounter].mMins[1], pMap.mLeaves[lLeafCounter].mMins[2]);
fprintf(pFile, "\tMax Bounding Box : %d %d %d\n", pMap.mLeaves[lLeafCounter].mMaxs[0], pMap.mLeaves[lLeafCounter].mMaxs[1], pMap.mLeaves[lLeafCounter].mMaxs[2]);
fprintf(pFile, "\tLeafFace %d\n", pMap.mLeaves[lLeafCounter].mLeafFace);
fprintf(pFile, "\tNb LeafFace %d\n", pMap.mLeaves[lLeafCounter].mNbLeafFaces);
fprintf(pFile, "\tLeafBrush %d\n", pMap.mLeaves[lLeafCounter].mLeafBrush);
fprintf(pFile, "\tNb LeafBrushes %d\n", pMap.mLeaves[lLeafCounter].mNbLeafBrushes);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* LeafFace Lump *********\n");
for
(int lLeafFaceCounter = 0; lLeafFaceCounter < pMap.mLeafFaces.size(); ++lLeafFaceCounter)
{
fprintf(pFile, "LeafFace %d\n", lLeafFaceCounter);
fprintf(pFile, "\tFaceIndex %d\n", pMap.mLeafFaces[lLeafFaceCounter].mFaceIndex);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* LeafBrush Lump *********\n");
for
(int lLeafBrushCounter = 0; lLeafBrushCounter < pMap.mLeafBrushes.size(); ++lLeafBrushCounter)
{
fprintf(pFile, "LeafBrush %d\n", lLeafBrushCounter);
fprintf(pFile, "\tBrushIndex %d\n", pMap.mLeafBrushes[lLeafBrushCounter].mBrushIndex);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Model Lump *********\n");
for
(int lModelCounter = 0; lModelCounter < pMap.mModels.size(); ++lModelCounter)
{
fprintf(pFile, "Model %d\n", lModelCounter);
fprintf(pFile, "\tMin Bounding Box : %d %d %d\n", pMap.mModels[lModelCounter].mMins[0], pMap.mModels[lModelCounter].mMins[1], pMap.mModels[lModelCounter].mMins[2]);
fprintf(pFile, "\tMax Bounding Box : %d %d %d\n", pMap.mModels[lModelCounter].mMaxs[0], pMap.mModels[lModelCounter].mMaxs[1], pMap.mModels[lModelCounter].mMaxs[2]);
fprintf(pFile, "\tFace %d\n", pMap.mModels[lModelCounter].mFace);
fprintf(pFile, "\tNbFaces %d\n", pMap.mModels[lModelCounter].mNbFaces);
fprintf(pFile, "\tBrush %d\n", pMap.mModels[lModelCounter].mBrush);
fprintf(pFile, "\tNbBrushes %d\n", pMap.mModels[lModelCounter].mNBrushes);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Brush Lump *********\n");
for
(int lBrushCounter = 0; lBrushCounter < pMap.mBrushes.size(); ++lBrushCounter)
{
fprintf(pFile, "Brush %d\n", lModelCounter);
fprintf(pFile, "\tBrushSide %d\n", pMap.mBrushes[lBrushCounter].mBrushSide);
fprintf(pFile, "\tNbBrushSides %d\n", pMap.mBrushes[lBrushCounter].mNbBrushSides);
fprintf(pFile, "\tTextureIndex %d\n", pMap.mBrushes[lBrushCounter].mTextureIndex);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* BrushSide Lump *********\n");
for
(int lBrushSideCounter = 0; lBrushSideCounter < pMap.mBrushSides.size(); ++lBrushSideCounter)
{
fprintf(pFile, "BrushSide %d\n", lBrushSideCounter);
fprintf(pFile, "\tPlaneIndex %d\n", pMap.mBrushSides[lBrushSideCounter].mPlaneIndex);
fprintf(pFile, "\tTextureIndex %d\n", pMap.mBrushSides[lBrushSideCounter].mTextureIndex);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Vertex Lump *********\n");
for
(int lVertexCounter = 0; lVertexCounter < pMap.mVertices.size(); ++lVertexCounter)
{
fprintf(pFile, "Vertex %d\n", lVertexCounter);
fprintf(pFile, "\tPosition : %f %f %f\n", pMap.mVertices[lVertexCounter].mPosition[0], pMap.mVertices[lVertexCounter].mPosition[1], pMap.mVertices[lVertexCounter].mPosition[2]);
fprintf(pFile, "\tTexCoord0 : %f %f\n", pMap.mVertices[lVertexCounter].mTexCoord[0], pMap.mVertices[lVertexCounter].mTexCoord[1]);
fprintf(pFile, "\tTexCoord0 : %f %f\n", pMap.mVertices[lVertexCounter].mTexCoord[2], pMap.mVertices[lVertexCounter].mTexCoord[3]);
fprintf(pFile, "\tNormal : %f %f %f\n", pMap.mVertices[lVertexCounter].mNormal[0], pMap.mVertices[lVertexCounter].mNormal[1], pMap.mVertices[lVertexCounter].mNormal[2]);
fprintf(pFile, "\tColor : %d %d %d %d\n", pMap.mVertices[lVertexCounter].mColor[0], pMap.mVertices[lVertexCounter].mColor[1], pMap.mVertices[lVertexCounter].mColor[2], pMap.mVertices[lVertexCounter].mColor[3]);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* MeshVert Lump *********\n");
for
(int lMeshVertCounter = 0; lMeshVertCounter < pMap.mMeshVertices.size(); ++lMeshVertCounter)
{
fprintf(pFile, "MeshVert %d\n", lMeshVertCounter);
fprintf(pFile, "\tVertex Index : %d\n", pMap.mMeshVertices[lMeshVertCounter].mMeshVert);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Effect Lump *********\n");
for
(int lEffectCounter = 0; lEffectCounter < pMap.mEffects.size(); ++lEffectCounter)
{
fprintf(pFile, "Effect %d\n", lEffectCounter);
fprintf(pFile, "\tName : %s\n", pMap.mEffects[lEffectCounter].mName);
fprintf(pFile, "\tBrush : %d\n", pMap.mEffects[lEffectCounter].mBrush);
fprintf(pFile, "\tUnknown : %d\n", pMap.mEffects[lEffectCounter].mUnknown);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* Face Lump *********\n");
for
(int lFaceCounter = 0; lFaceCounter < pMap.mFaces.size(); ++lFaceCounter)
{
fprintf(pFile, "Face %d\n", lFaceCounter);
fprintf(pFile, "\tTextureIndex : %d\n", pMap.mFaces[lFaceCounter].mTextureIndex);
fprintf(pFile, "\tEffectIndex : %d\n", pMap.mFaces[lFaceCounter].mEffectIndex);
fprintf(pFile, "\tType : %d\n", pMap.mFaces[lFaceCounter].mType);
fprintf(pFile, "\tVertex : %d\n", pMap.mFaces[lFaceCounter].mVertex);
fprintf(pFile, "\tNbVertices : %d\n", pMap.mFaces[lFaceCounter].mNbVertices);
fprintf(pFile, "\tMeshVertex : %d\n", pMap.mFaces[lFaceCounter].mMeshVertex);
fprintf(pFile, "\tNbMeshVertices : %d\n", pMap.mFaces[lFaceCounter].mNbMeshVertices);
fprintf(pFile, "\tLightMapIndex : %d\n", pMap.mFaces[lFaceCounter].mLightmapIndex);
fprintf(pFile, "\tLightMapCorner : %d %d\n", pMap.mFaces[lFaceCounter].mLightmapCorner[0], pMap.mFaces[lFaceCounter].mLightmapCorner[1]);
fprintf(pFile, "\tLightmapSize : %d %d\n", pMap.mFaces[lFaceCounter].mLightmapSize[0], pMap.mFaces[lFaceCounter].mLightmapSize[1]);
fprintf(pFile, "\tLightmapOrigin : %f %f %f\n", pMap.mFaces[lFaceCounter].mLightmapOrigin[0], pMap.mFaces[lFaceCounter].mLightmapOrigin[1], pMap.mFaces[lFaceCounter].mLightmapOrigin[2]);
fprintf(pFile, "\tLightmapVecs S : %f %f %f\n", pMap.mFaces[lFaceCounter].mLightmapVecs[0][0], pMap.mFaces[lFaceCounter].mLightmapVecs[0][1], pMap.mFaces[lFaceCounter].mLightmapVecs[0][2]);
fprintf(pFile, "\tLightmapVecs T : %f %f %f\n", pMap.mFaces[lFaceCounter].mLightmapVecs[1][0], pMap.mFaces[lFaceCounter].mLightmapVecs[1][1], pMap.mFaces[lFaceCounter].mLightmapVecs[1][2]);
fprintf(pFile, "\tNormal : %f %f %f\n", pMap.mFaces[lFaceCounter].mNormal[0], pMap.mFaces[lFaceCounter].mNormal[1], pMap.mFaces[lFaceCounter].mNormal[2]);
fprintf(pFile, "\tPatchSize : %d %d\n", pMap.mFaces[lFaceCounter].mPatchSize[0], pMap.mFaces[lFaceCounter].mPatchSize[1]);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* LightMap Lump *********\n");
fprintf(pFile, "NbLightMaps %d\n", pMap.mLightMaps.size());
fprintf(pFile, "\n");
fprintf(pFile, "********* LightVol Lump *********\n");
for
(int lLightVolCounter = 0; lLightVolCounter < pMap.mLightVols.size(); ++lLightVolCounter)
{
fprintf(pFile, "LightVol %d\n", lLightVolCounter);
fprintf(pFile, "\tAmbient : %d %d %d\n", pMap.mLightVols[lLightVolCounter].mAmbient[0], pMap.mLightVols[lLightVolCounter].mAmbient[1], pMap.mLightVols[lLightVolCounter].mAmbient[2]);
fprintf(pFile, "\tDirectional : %d %d %d\n", pMap.mLightVols[lLightVolCounter].mDirectional[0], pMap.mLightVols[lLightVolCounter].mDirectional[1], pMap.mLightVols[lLightVolCounter].mDirectional[2]);
fprintf(pFile, "\tDir : %d %d\n", pMap.mLightVols[lLightVolCounter].mDir[0], pMap.mLightVols[lLightVolCounter].mDir[1]);
}
fprintf(pFile, "\n");
fprintf(pFile, "********* VisData Lump *********\n");
fprintf(pFile, "\tNbCluster %d\n", pMap.mVisData.mNbClusters);
fprintf(pFile, "\tBytePerCluster %d\n", pMap.mVisData.mBytesPerCluster);
fprintf(pFile, "\n");
}
/**
* Read the map.
*
* @param pFilename The filename of the map to read.
*
* @return true if the loading successed, false otherwise.
*/
bool readMap(const std::string& pFilename, TMapQ3& pMap)
{
// Open the file.
FILE* lFile = fopen(pFilename.c_str(), "r+b");
// Check if the file exists.
if
(! lFile)
{
printf("readMap :: Invalid stream handle.\n");
return false;
}
// Read the header.
if
(readHeader(lFile, pMap) == false)
{
printf("readMap :: Invalid Q3 map header.\n");
return false;
}
// Read the entity lump.
readEntity(lFile, pMap);
// Read the texture lump.
readTexture(lFile, pMap);
// Read the plane lump.
readPlane(lFile, pMap);
// Read the node lump.
readNode(lFile, pMap);
// Read the leaf lump.
readLeaf(lFile, pMap);
// Read the leaf face lump.
readLeafFace(lFile, pMap);
// Read the leaf brush lump.
readLeafBrush(lFile, pMap);
// Read the model lump.
readModel(lFile, pMap);
// Read the brush lump.
readBrush(lFile, pMap);
// Read the brushside lump.
readBrushSide(lFile, pMap);
// Read the vertex lump.
readVertex(lFile, pMap);
// Read the meshvert lump.
readMeshVert(lFile, pMap);
// Read the effect lump.
readEffect(lFile, pMap);
// Read the face lump.
readFace(lFile, pMap);
// Read the lightmap lump.
readLightMap(lFile, pMap);
// Read the lightvol lump.
readLightVol(lFile, pMap);
// read the visdata lump.
readVisData(lFile, pMap);
// Close the file.
fclose(lFile);
return true;
};
/**
* Free all the datas of the map.
*tLightmapVecs
* @param pMap The Q3 map to free.
*/
void freeMap(TMapQ3& pMap)
{
if
(pMap.mEntity.mBuffer)
{
delete [] pMap.mEntity.mBuffer;
pMap.mEntity.mBuffer = NULL;
}
if
(pMap.mVisData.mBuffer)
{
delete [] pMap.mVisData.mBuffer;
pMap.mVisData.mBuffer = NULL;
}
pMap.mTextures.clear();
pMap.mPlanes.clear();
pMap.mNodes.clear();
pMap.mLeaves.clear();
pMap.mLeafFaces.clear();
pMap.mLeafBrushes.clear();
pMap.mModels.clear();
pMap.mBrushes.clear();
pMap.mBrushSides.clear();
pMap.mVertices.clear();
pMap.mMeshVertices.clear();
pMap.mEffects.clear();
pMap.mFaces.clear();
pMap.mLightMaps.clear();
pMap.mLightVols.clear();
}
|