#ifndef __C_Q3_LEVEL_MESH_H_INCLUDED__
#define __C_Q3_LEVEL_MESH_H_INCLUDED__
#include "IQ3LevelMesh.h"
#include "IReadFile.h"
#include "IFileSystem.h"
#include "SMesh.h"
#include "SMeshBufferLightMap.h"
#include "IVideoDriver.h"
#include "irrString.h"
#include "ISceneManager.h"
#include "os.h"
namespace irr
{
namespace scene
{
class CQ3LevelMesh : public IQ3LevelMesh
{
public:
CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr,
const quake3::Q3LevelLoadParameter &loadParam);
virtual ~CQ3LevelMesh();
bool loadFile(io::IReadFile* file);
virtual u32 getFrameCount() const;
virtual IMesh* getMesh(s32 frameInMs, s32 detailLevel=255,
s32 startFrameLoop=-1, s32 endFrameLoop=-1);
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual void setBoundingBox( const core::aabbox3df& box);
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
virtual void getShader( io::IReadFile* file );
virtual const quake3::IShader * getShader( const c8 * filename, bool fileNameIsValid=true );
virtual const quake3::IShader * getShader( u32 index ) const;
virtual void getConfiguration( io::IReadFile* file );
virtual quake3::tQ3EntityList & getEntityList();
virtual u32 getMeshBufferCount() const
{
return 0;
}
virtual IMeshBuffer* getMeshBuffer(u32 nr) const
{
return 0;
}
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const
{
return 0;
}
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
{
return;
}
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX)
{
return;
}
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX)
{
return;
}
private:
void constructMesh();
void solveTJunction();
void loadTextures();
struct STexShader
{
video::ITexture* Texture;
s32 ShaderID;
};
core::array< STexShader > Tex;
core::array<video::ITexture*> Lightmap;
enum eLumps
{
kEntities = 0,
kShaders = 1,
kPlanes = 2,
kNodes = 3,
kLeafs = 4,
kLeafFaces = 5,
kLeafBrushes = 6,
kModels = 7,
kBrushes = 8,
kBrushSides = 9,
kVertices = 10,
kMeshVerts = 11,
kFogs = 12,
kFaces = 13,
kLightmaps = 14,
kLightGrid = 15,
kVisData = 16,
kLightArray = 17,
kMaxLumps
};
enum eBspSurfaceType
{
BSP_MST_BAD,
BSP_MST_PLANAR,
BSP_MST_PATCH,
BSP_MST_TRIANGLE_SOUP,
BSP_MST_FLARE,
BSP_MST_FOLIAGE
};
struct tBSPHeader
{
s32 strID;
s32 version;
};
tBSPHeader header;
struct tBSPLump
{
s32 offset;
s32 length;
};
struct tBSPVertex
{
f32 vPosition[3];
f32 vTextureCoord[2];
f32 vLightmapCoord[2];
f32 vNormal[3];
u8 color[4];
};
struct tBSPFace
{
s32 textureID;
s32 fogNum;
s32 type;
s32 vertexIndex;
s32 numOfVerts;
s32 meshVertIndex;
s32 numMeshVerts;
s32 lightmapID;
s32 lMapCorner[2];
s32 lMapSize[2];
f32 lMapPos[3];
f32 lMapBitsets[2][3];
f32 vNormal[3];
s32 size[2];
};
struct tBSPTexture
{
c8 strName[64];
u32 flags;
u32 contents;
};
struct tBSPLightmap
{
u8 imageBits[128][128][3];
};
struct tBSPNode
{
s32 plane;
s32 front;
s32 back;
s32 mins[3];
s32 maxs[3];
};
struct tBSPLeaf
{
s32 cluster;
s32 area;
s32 mins[3];
s32 maxs[3];
s32 leafface;
s32 numOfLeafFaces;
s32 leafBrush;
s32 numOfLeafBrushes;
};
struct tBSPPlane
{
f32 vNormal[3];
f32 d;
};
struct tBSPVisData
{
s32 numOfClusters;
s32 bytesPerCluster;
c8 *pBitsets;
};
struct tBSPBrush
{
s32 brushSide;
s32 numOfBrushSides;
s32 textureID;
};
struct tBSPBrushSide
{
s32 plane;
s32 textureID;
};
struct tBSPModel
{
f32 min[3];
f32 max[3];
s32 faceIndex;
s32 numOfFaces;
s32 brushIndex;
s32 numOfBrushes;
};
struct tBSPFog
{
c8 shader[64];
s32 brushIndex;
s32 visibleSide;
};
core::array < STexShader > FogMap;
struct tBSPLights
{
u8 ambient[3];
u8 directional[3];
u8 direction[2];
};
void loadTextures (tBSPLump* l, io::IReadFile* file);
void loadLightmaps (tBSPLump* l, io::IReadFile* file);
void loadVerts (tBSPLump* l, io::IReadFile* file);
void loadFaces (tBSPLump* l, io::IReadFile* file);
void loadPlanes (tBSPLump* l, io::IReadFile* file);
void loadNodes (tBSPLump* l, io::IReadFile* file);
void loadLeafs (tBSPLump* l, io::IReadFile* file);
void loadLeafFaces (tBSPLump* l, io::IReadFile* file);
void loadVisData (tBSPLump* l, io::IReadFile* file);
void loadEntities (tBSPLump* l, io::IReadFile* file);
void loadModels (tBSPLump* l, io::IReadFile* file);
void loadMeshVerts (tBSPLump* l, io::IReadFile* file);
void loadBrushes (tBSPLump* l, io::IReadFile* file);
void loadBrushSides (tBSPLump* l, io::IReadFile* file);
void loadLeafBrushes(tBSPLump* l, io::IReadFile* file);
void loadFogs (tBSPLump* l, io::IReadFile* file);
void createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer,
s32 faceIndex, s32 patchTesselation, s32 storevertexcolor);
void createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer,
s32 faceIndex, s32 patchTesselation, s32 storevertexcolor);
struct S3DVertex2TCoords_64
{
core::vector3d<f64> Pos;
core::vector3d<f64> Normal;
video::SColorf Color;
core::vector2d<f64> TCoords;
core::vector2d<f64> TCoords2;
void copy( video::S3DVertex2TCoords &dest ) const;
S3DVertex2TCoords_64() {}
S3DVertex2TCoords_64(const core::vector3d<f64>& pos, const core::vector3d<f64>& normal, const video::SColorf& color,
const core::vector2d<f64>& tcoords, const core::vector2d<f64>& tcoords2)
: Pos(pos), Normal(normal), Color(color), TCoords(tcoords), TCoords2(tcoords2) {}
S3DVertex2TCoords_64 getInterpolated_quadratic(const S3DVertex2TCoords_64& v2,
const S3DVertex2TCoords_64& v3, const f64 d) const
{
return S3DVertex2TCoords_64 (
Pos.getInterpolated_quadratic ( v2.Pos, v3.Pos, d ),
Normal.getInterpolated_quadratic ( v2.Normal, v3.Normal, d ),
Color.getInterpolated_quadratic ( v2.Color, v3.Color, (f32) d ),
TCoords.getInterpolated_quadratic ( v2.TCoords, v3.TCoords, d ),
TCoords2.getInterpolated_quadratic ( v2.TCoords2, v3.TCoords2, d ));
}
};
inline void copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source,
s32 vertexcolor ) const;
void copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const;
struct SBezier
{
SMeshBufferLightMap *Patch;
S3DVertex2TCoords_64 control[9];
void tesselate(s32 level);
private:
s32 Level;
core::array<S3DVertex2TCoords_64> column[3];
};
SBezier Bezier;
quake3::Q3LevelLoadParameter LoadParam;
tBSPLump Lumps[kMaxLumps];
tBSPTexture* Textures;
s32 NumTextures;
tBSPLightmap* LightMaps;
s32 NumLightMaps;
tBSPVertex* Vertices;
s32 NumVertices;
tBSPFace* Faces;
s32 NumFaces;
tBSPPlane* Planes;
s32 NumPlanes;
tBSPNode* Nodes;
s32 NumNodes;
tBSPLeaf* Leafs;
s32 NumLeafs;
s32 *LeafFaces;
s32 NumLeafFaces;
s32 *MeshVerts;
s32 NumMeshVerts;
tBSPBrush* Brushes;
s32 NumBrushes;
scene::SMesh* Mesh[quake3::E_Q3_MESH_SIZE];
video::IVideoDriver* Driver;
core::stringc LevelName;
io::IFileSystem* FileSystem;
scene::ISceneManager* SceneManager;
enum eToken
{
Q3_TOKEN_UNRESOLVED = 0,
Q3_TOKEN_EOF = 1,
Q3_TOKEN_START_LIST,
Q3_TOKEN_END_LIST,
Q3_TOKEN_ENTITY,
Q3_TOKEN_TOKEN,
Q3_TOKEN_EOL,
Q3_TOKEN_COMMENT,
Q3_TOKEN_MATH_DIVIDE,
Q3_TOKEN_MATH_ADD,
Q3_TOKEN_MATH_MULTIPY
};
struct SQ3Parser
{
const c8 *source;
u32 sourcesize;
u32 index;
core::stringc token;
eToken tokenresult;
};
SQ3Parser Parser;
typedef void( CQ3LevelMesh::*tParserCallback ) ( quake3::SVarGroupList *& groupList, eToken token );
void parser_parse( const void * data, u32 size, tParserCallback callback );
void parser_nextToken();
void dumpVarGroup( const quake3::SVarGroup * group, s32 stack ) const;
void scriptcallback_entity( quake3::SVarGroupList *& grouplist, eToken token );
void scriptcallback_shader( quake3::SVarGroupList *& grouplist, eToken token );
void scriptcallback_config( quake3::SVarGroupList *& grouplist, eToken token );
core::array < quake3::IShader > Shader;
core::array < quake3::IShader > Entity;
quake3::tStringList ShaderFile;
void InitShader();
void ReleaseShader();
void ReleaseEntity();
s32 setShaderMaterial( video::SMaterial & material, const tBSPFace * face ) const;
s32 setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const;
struct SToBuffer
{
s32 takeVertexColor;
u32 index;
};
void cleanMeshes();
void cleanLoader ();
void calcBoundingBoxes();
c8 buf[128];
};
}
}
#endif