Tools/MeshExtractor:

* Added the option to output debug information on ADTs.
* Tweaked rcConfig options and fixed some mistakes about it.
* Generate 64 tiles per ADT, this should give us a more accurate mesh on large maps.
* Speedup compilation time by moving function bodies from Utils.h to Utils.cpp
This commit is contained in:
Subv
2012-09-30 15:47:39 -05:00
parent 4c3266c7af
commit fa57ecddac
8 changed files with 319 additions and 272 deletions

View File

@@ -2,7 +2,6 @@
#include "DoodadHandler.h"
#include "LiquidHandler.h"
#include "WorldModelHandler.h"
#include "Cache.h"
ADT::ADT( std::string file ) : ObjectData(NULL), Data(NULL), _DoodadHandler(NULL), _WorldModelHandler(NULL), _LiquidHandler(NULL), HasObjectData(false)
{

View File

@@ -7,13 +7,14 @@
#include "ace/Task.h"
#include "Recast.h"
class BuilderThread : public ACE_Task<ACE_MT_SYNCH>
class BuilderThread : public ACE_Task_Base
{
private:
int X, Y, MapId;
std::string Continent;
bool debug;
public:
BuilderThread() : Free(true) {}
BuilderThread(bool deb) : Free(true), debug(deb) {}
void SetData(int x, int y, int map, std::string cont) { X = x; Y = y; MapId = map; Continent = cont; }
int svc()
@@ -22,23 +23,23 @@ public:
printf("[%02i,%02i] Building tile\n", X, Y);
TileBuilder builder(Continent, X, Y, MapId);
char buff[100];
sprintf(buff, "mmaps/%03u%02u%02u.mmtile", MapId, X, Y);
sprintf(buff, "mmaps/%03u%02u%02u.mmtile", MapId, Y, X);
FILE* f = fopen(buff, "r");
if (f) // Check if file already exists.
{
printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y);
fclose(f);
Free = true;
return 1;
return 0;
}
uint8* nav = builder.Build();
uint8* nav = builder.Build(debug);
if (nav)
{
f = fopen(buff, "wb");
if (!f)
{
printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
return -1;
return 0;
}
MmapTileHeader header;
header.size = builder.DataSize;
@@ -73,7 +74,7 @@ void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, floa
bmin[2] = bmax[2] - Constants::TileSize;
}
void ContinentBuilder::Build()
void ContinentBuilder::Build(bool debug)
{
char buff[50];
sprintf(buff, "mmaps/%03u.mmap", MapId);
@@ -107,7 +108,7 @@ void ContinentBuilder::Build()
fclose(mmap);
std::vector<BuilderThread*> Threads;
for (uint32 i = 0; i < NumberOfThreads; ++i)
Threads.push_back(new BuilderThread());
Threads.push_back(new BuilderThread(debug));
printf("Map %s ( %i ) has %i tiles. Building them with %i threads\n", Continent.c_str(), MapId, TileMap->TileTable.size(), NumberOfThreads);
for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr)
{

View File

@@ -8,7 +8,7 @@ class ContinentBuilder
{
public:
ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt, uint32 tn) : MapId(mapId), Continent(continent), TileMap(wdt), NumberOfThreads(tn) {}
void Build();
void Build(bool debug);
private:
std::string Continent;
WDT* TileMap;

View File

@@ -14,7 +14,7 @@ LoginDatabaseWorkerPool LoginDatabase;
MPQManager* MPQHandler;
CacheClass* Cache;
void ExtractAllMaps(std::set<uint32>& mapIds, uint32 threads)
void ExtractAllMaps(std::set<uint32>& mapIds, uint32 threads, bool debug)
{
DBC* dbc = MPQHandler->GetDBC("Map");
for (std::vector<Record*>::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr)
@@ -31,11 +31,11 @@ void ExtractAllMaps(std::set<uint32>& mapIds, uint32 threads)
continue;
printf("Building %s MapId %u\n", name.c_str(), mapId);
ContinentBuilder builder(name, mapId, &wdt, threads);
builder.Build();
builder.Build(debug);
}
}
bool HandleArgs(int argc, char** argv, uint32& threads, std::set<uint32>& mapList)
bool HandleArgs(int argc, char** argv, uint32& threads, std::set<uint32>& mapList, bool& debugOutput)
{
char* param = NULL;
for (int i = 1; i < argc; ++i)
@@ -62,6 +62,14 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set<uint32>& mapLis
printf("Extracting only provided list of maps (%u).\n", mapList.size());
}
if (strcmp(argv[i], "--debug") == 0)
{
param = argv[++i];
if (!param)
return false;
debugOutput = atoi(param);
printf("Output will contain debug information (.obj files)\n");
}
}
return true;
}
@@ -71,6 +79,7 @@ void PrintUsage()
printf("MeshExtractor help.\n");
printf("* Use \"--threads <number>\" to specify <number> threads, default to 4\n");
printf("* Use \"--maps a,b,c,d,e\" to extract only the maps specified ( do not use spaces )\n");
printf("* Use \"--debug 1\" to generate debug information of the tiles.\n");
}
int main(int argc, char* argv[])
@@ -81,14 +90,14 @@ int main(int argc, char* argv[])
MPQHandler->Initialize();
uint32 threads = 4;
std::set<uint32> mapIds;
bool debug = false;
if (!HandleArgs(argc, argv, threads, mapIds))
if (!HandleArgs(argc, argv, threads, mapIds, debug))
{
PrintUsage();
return -1;
}
ExtractAllMaps(mapIds, threads);
ExtractAllMaps(mapIds, threads, debug);
return 0;
}
}

View File

@@ -17,20 +17,22 @@ TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geome
// 1800 = TileVoxelSize
Config.cs = Constants::TileSize / 1800;
// Cell Height
Config.ch = 0.3f;
// Min Region Area = 6^2
Config.minRegionArea = 36;
// Merge Region Area = 12^2
Config.mergeRegionArea = 144;
Config.ch = 0.4f;
// Min Region Area = 20^2
Config.minRegionArea = 20*20;
// Merge Region Area = 40^2
Config.mergeRegionArea = 40*40;
Config.tileSize = Constants::TileSize / 4;
Config.walkableSlopeAngle = 50.0f;
Config.detailSampleDist = 3.0f;
Config.detailSampleMaxError = 1.25f;
Config.walkableClimb = 1.0f / Config.ch;
Config.walkableHeight = 2.1f / Config.ch;
Config.walkableRadius = 0.6f / Config.cs;
Config.walkableHeight = 1.652778f / Config.ch;
Config.walkableRadius = 0.2951389f / Config.cs;
Config.maxEdgeLen = Config.walkableRadius * 8;
Config.borderSize = Config.walkableRadius + 8;
Config.width = 1800;
Config.borderSize = Config.walkableRadius + 4;
Config.width = 1800 + Config.borderSize * 2;
Config.height = 1800 + Config.borderSize * 2;
Config.maxVertsPerPoly = 6;
Config.maxSimplificationError = 1.3f;
@@ -47,7 +49,7 @@ void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax )
bmax[2] = Constants::Origin[2] + (Constants::TileSize * (Y + 1));
}
uint8* TileBuilder::Build()
uint8* TileBuilder::Build(bool dbg)
{
_Geometry = new Geometry();
_Geometry->Transform = true;
@@ -65,9 +67,9 @@ uint8* TileBuilder::Build()
_Geometry->CalculateMinMaxHeight(bbMin[1], bbMax[1]);
// again, we load everything - wasteful but who cares
for (int ty = Y - 1; ty <= Y + 1; ty++)
for (int ty = Y - 4; ty <= Y + 4; ty++)
{
for (int tx = X - 1; tx <= X + 1; tx++)
for (int tx = X - 4; tx <= X + 4; tx++)
{
// don't load main tile again
if (tx == X && ty == Y)
@@ -85,6 +87,19 @@ uint8* TileBuilder::Build()
delete _adt;
}
}
if (dbg)
{
char buff[100];
sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X);
FILE* debug = fopen(buff, "wb");
for (int i = 0; i < _Geometry->Vertices.size(); ++i)
fprintf(debug, "v %f %f %f\n", _Geometry->Vertices[i].x, _Geometry->Vertices[i].y, _Geometry->Vertices[i].z);
for (int i = 0; i < _Geometry->Triangles.size(); ++i)
fprintf(debug, "f %i %i %i\n", _Geometry->Triangles[i].V0 + 1, _Geometry->Triangles[i].V1 + 1, _Geometry->Triangles[i].V2 + 1);
fclose(debug);
}
uint32 numVerts = _Geometry->Vertices.size();
uint32 numTris = _Geometry->Triangles.size();
float* vertices;
@@ -100,8 +115,7 @@ uint8* TileBuilder::Build()
bbMax[0] += Config.borderSize * Config.cs;
rcHeightfield* hf = rcAllocHeightfield();
int width = Config.width + (Config.borderSize * 2);
rcCreateHeightfield(Context, *hf, width, width, bbMin, bbMax, Config.cs, Config.ch);
rcCreateHeightfield(Context, *hf, Config.width, Config.height, bbMin, bbMax, Config.cs, Config.ch);
rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas);
rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb);
@@ -208,14 +222,14 @@ uint8* TileBuilder::Build()
params.walkableRadius = Config.walkableRadius;
params.tileX = X;
params.tileY = Y;
params.tileSize = Config.width;
params.tileSize = 1800;
// Offmesh-connection settings
params.offMeshConCount = 0; // none for now
int navDataSize;
uint8* navData;
printf("[%02i,%02i] Creating the navmesh!\n", X, Y);
printf("[%02i,%02i] Creating the navmesh with %i vertices, %i polys, %i triangles!\n", X, Y, pmesh->nverts, pmesh->npolys, dmesh->ntris);
bool result = dtCreateNavMeshData(&params, &navData, &navDataSize);
// Free some memory

View File

@@ -14,7 +14,7 @@ public:
~TileBuilder();
void CalculateTileBounds(float*& bmin, float*& bmax);
uint8* Build();
uint8* Build(bool dbg);
std::string World;
int X;

View File

@@ -180,3 +180,253 @@ G3D::Matrix4 Utils::GetWmoDoodadTransformation( DoodadInstance inst, WorldModelD
return scale * rotation * quatRotation ** translation * rootTransformation;
}
void MapChunkHeader::Read(FILE* stream)
{
fread(&Flags, sizeof(uint32), 1, stream);
fread(&IndexX, sizeof(uint32), 1, stream);
fread(&IndexY, sizeof(uint32), 1, stream);
fread(&Layers, sizeof(uint32), 1, stream);
fread(&DoodadRefs, sizeof(uint32), 1, stream);
fread(&OffsetMCVT, sizeof(uint32), 1, stream);
fread(&OffsetMCNR, sizeof(uint32), 1, stream);
fread(&OffsetMCLY, sizeof(uint32), 1, stream);
fread(&OffsetMCRF, sizeof(uint32), 1, stream);
fread(&OffsetMCAL, sizeof(uint32), 1, stream);
fread(&SizeMCAL, sizeof(uint32), 1, stream);
fread(&OffsetMCSH, sizeof(uint32), 1, stream);
fread(&SizeMCSH, sizeof(uint32), 1, stream);
fread(&AreaId, sizeof(uint32), 1, stream);
fread(&MapObjectRefs, sizeof(uint32), 1, stream);
fread(&Holes, sizeof(uint32), 1, stream);
LowQualityTextureMap = new uint32[4];
fread(LowQualityTextureMap, sizeof(uint32), 4, stream);
fread(&PredTex, sizeof(uint32), 1, stream);
fread(&NumberEffectDoodad, sizeof(uint32), 1, stream);
fread(&OffsetMCSE, sizeof(uint32), 1, stream);
fread(&SoundEmitters, sizeof(uint32), 1, stream);
fread(&OffsetMCLQ, sizeof(uint32), 1, stream);
fread(&SizeMCLQ, sizeof(uint32), 1, stream);
Position = Vector3::Read(stream);
fread(&OffsetMCCV, sizeof(uint32), 1, stream);
}
void MHDR::Read(FILE* stream)
{
fread(&Flags, sizeof(uint32), 1, stream);
fread(&OffsetMCIN, sizeof(uint32), 1, stream);
fread(&OffsetMTEX, sizeof(uint32), 1, stream);
fread(&OffsetMMDX, sizeof(uint32), 1, stream);
fread(&OffsetMMID, sizeof(uint32), 1, stream);
fread(&OffsetMWMO, sizeof(uint32), 1, stream);
fread(&OffsetMWID, sizeof(uint32), 1, stream);
fread(&OffsetMDDF, sizeof(uint32), 1, stream);
fread(&OffsetMODF, sizeof(uint32), 1, stream);
fread(&OffsetMFBO, sizeof(uint32), 1, stream);
fread(&OffsetMH2O, sizeof(uint32), 1, stream);
fread(&OffsetMTFX, sizeof(uint32), 1, stream);
}
void ModelHeader::Read(FILE* stream)
{
fread(&Magic, sizeof(char), 4, stream);
Magic[4] = '\0'; // null-terminate it.
fread(&Version, sizeof(uint32), 1, stream);
fread(&LengthModelName, sizeof(uint32), 1, stream);
fread(&OffsetName, sizeof(uint32), 1, stream);
fread(&ModelFlags, sizeof(uint32), 1, stream);
fread(&CountGlobalSequences, sizeof(uint32), 1, stream);
fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream);
fread(&CountAnimations, sizeof(uint32), 1, stream);
fread(&OffsetAnimations, sizeof(uint32), 1, stream);
fread(&CountAnimationLookup, sizeof(uint32), 1, stream);
fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream);
fread(&CountBones, sizeof(uint32), 1, stream);
fread(&OffsetBones, sizeof(uint32), 1, stream);
fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream);
fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream);
fread(&CountVertices, sizeof(uint32), 1, stream);
fread(&OffsetVertices, sizeof(uint32), 1, stream);
fread(&CountViews, sizeof(uint32), 1, stream);
fread(&CountColors, sizeof(uint32), 1, stream);
fread(&OffsetColors, sizeof(uint32), 1, stream);
fread(&CountTextures, sizeof(uint32), 1, stream);
fread(&OffsetTextures, sizeof(uint32), 1, stream);
fread(&CountTransparency, sizeof(uint32), 1, stream);
fread(&OffsetTransparency, sizeof(uint32), 1, stream);
fread(&CountUvAnimation, sizeof(uint32), 1, stream);
fread(&OffsetUvAnimation, sizeof(uint32), 1, stream);
fread(&CountTexReplace, sizeof(uint32), 1, stream);
fread(&OffsetTexReplace, sizeof(uint32), 1, stream);
fread(&CountRenderFlags, sizeof(uint32), 1, stream);
fread(&OffsetRenderFlags, sizeof(uint32), 1, stream);
fread(&CountBoneLookup, sizeof(uint32), 1, stream);
fread(&OffsetBoneLookup, sizeof(uint32), 1, stream);
fread(&CountTexLookup, sizeof(uint32), 1, stream);
fread(&OffsetTexLookup, sizeof(uint32), 1, stream);
fread(&CountTexUnits, sizeof(uint32), 1, stream);
fread(&OffsetTexUnits, sizeof(uint32), 1, stream);
fread(&CountTransLookup, sizeof(uint32), 1, stream);
fread(&OffsetTransLookup, sizeof(uint32), 1, stream);
fread(&CountUvAnimLookup, sizeof(uint32), 1, stream);
fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream);
fread(&CountColors, sizeof(uint32), 1, stream);
fread(&OffsetColors, sizeof(uint32), 1, stream);
fread(&CountTextures, sizeof(uint32), 1, stream);
fread(&OffsetTextures, sizeof(uint32), 1, stream);
fread(&CountTransparency, sizeof(uint32), 1, stream);
fread(&OffsetTransparency, sizeof(uint32), 1, stream);
fread(&CountUvAnimation, sizeof(uint32), 1, stream);
fread(&OffsetUvAnimation, sizeof(uint32), 1, stream);
fread(&CountTexReplace, sizeof(uint32), 1, stream);
fread(&OffsetTexReplace, sizeof(uint32), 1, stream);
VertexBox[0] = Vector3::Read(stream);
VertexBox[1] = Vector3::Read(stream);
fread(&VertexRadius, sizeof(float), 1, stream);
BoundingBox[0] = Vector3::Read(stream);
BoundingBox[1] = Vector3::Read(stream);
fread(&BoundingRadius, sizeof(float), 1, stream);
fread(&CountBoundingTriangles, sizeof(uint32), 1, stream);
fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream);
fread(&CountBoundingVertices, sizeof(uint32), 1, stream);
fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream);
fread(&CountBoundingNormals, sizeof(uint32), 1, stream);
fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream);
}
WorldModelHeader WorldModelHeader::Read(FILE* stream)
{
WorldModelHeader ret;
fread(&ret.CountMaterials, sizeof(uint32), 1, stream);
fread(&ret.CountGroups, sizeof(uint32), 1, stream);
fread(&ret.CountPortals, sizeof(uint32), 1, stream);
fread(&ret.CountLights, sizeof(uint32), 1, stream);
fread(&ret.CountModels, sizeof(uint32), 1, stream);
fread(&ret.CountDoodads, sizeof(uint32), 1, stream);
fread(&ret.CountSets, sizeof(uint32), 1, stream);
fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream);
fread(&ret.WmoId, sizeof(uint32), 1, stream);
ret.BoundingBox[0] = Vector3::Read(stream);
ret.BoundingBox[1] = Vector3::Read(stream);
fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream);
return ret;
}
DoodadInstance DoodadInstance::Read(FILE* stream)
{
DoodadInstance ret;
fread(&ret.FileOffset, sizeof(uint32), 1, stream);
ret.Position = Vector3::Read(stream);
fread(&ret.QuatW, sizeof(float), 1, stream);
fread(&ret.QuatX, sizeof(float), 1, stream);
fread(&ret.QuatY, sizeof(float), 1, stream);
fread(&ret.QuatZ, sizeof(float), 1, stream);
fread(&ret.Scale, sizeof(float), 1, stream);
fread(&ret.LightColor, sizeof(uint32), 1, stream);
return ret;
}
DoodadSet DoodadSet::Read(FILE* stream)
{
DoodadSet ret;
char name[21];
fread(&name, sizeof(char), 20, stream);
name[20] = '\0';
ret.Name = name;
fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream);
fread(&ret.CountInstances, sizeof(uint32), 1, stream);
fread(&ret.UnknownZero, sizeof(uint32), 1, stream);
return ret;
}
LiquidHeader LiquidHeader::Read(FILE* stream)
{
LiquidHeader ret;
fread(&ret.CountXVertices, sizeof(uint32), 1, stream);
fread(&ret.CountYVertices, sizeof(uint32), 1, stream);
fread(&ret.Width, sizeof(uint32), 1, stream);
fread(&ret.Height, sizeof(uint32), 1, stream);
ret.BaseLocation = Vector3::Read(stream);
fread(&ret.MaterialId, sizeof(uint16), 1, stream);
return ret;
}
LiquidData LiquidData::Read(FILE* stream, LiquidHeader& header)
{
LiquidData ret;
ret.HeightMap = new float*[header.CountXVertices];
for (uint32 i = 0; i < header.CountXVertices; ++i)
ret.HeightMap[i] = new float[header.CountYVertices];
ret.RenderFlags = new uint8*[header.Width];
for (uint32 i = 0; i < header.Width; ++i)
ret.RenderFlags[i] = new uint8[header.Height];
for (uint32 y = 0; y < header.CountYVertices; y++)
{
for (uint32 x = 0; x < header.CountXVertices; x++)
{
uint32 discard;
fread(&discard, sizeof(uint32), 1, stream);
float tmp;
fread(&tmp, sizeof(float), 1, stream);
ret.HeightMap[x][y] = tmp;
}
}
for (uint32 y = 0; y < header.Height; y++)
{
for (uint32 x = 0; x < header.Width; x++)
{
uint8 tmp;
fread(&tmp, sizeof(uint8), 1, stream);
ret.RenderFlags[x][y] = tmp;
}
}
return ret;
}
H2ORenderMask H2ORenderMask::Read(FILE* stream)
{
H2ORenderMask ret;
fread(&ret.Mask, sizeof(uint8), 8, stream);
return ret;
}
bool MCNKLiquidData::IsWater(int x, int y, float height)
{
if (!Heights)
return false;
if (!Mask.ShouldRender(x, y))
return false;
float diff = Heights[x][y] - height;
if (diff > Constants::MaxStandableHeight)
return true;
return false;
}
H2OHeader H2OHeader::Read(FILE* stream)
{
H2OHeader ret;
fread(&ret.OffsetInformation, sizeof(uint32), 1, stream);
fread(&ret.LayerCount, sizeof(uint32), 1, stream);
fread(&ret.OffsetRender, sizeof(uint32), 1, stream);
return ret;
}
H2OInformation H2OInformation::Read(FILE* stream)
{
H2OInformation ret;
fread(&ret.LiquidType, sizeof(uint16), 1, stream);
fread(&ret.Flags, sizeof(uint16), 1, stream);
fread(&ret.HeightLevel1, sizeof(float), 1, stream);
fread(&ret.HeightLevel2, sizeof(float), 1, stream);
fread(&ret.OffsetX, sizeof(uint8), 1, stream);
fread(&ret.OffsetY, sizeof(uint8), 1, stream);
fread(&ret.Width, sizeof(uint8), 1, stream);
fread(&ret.Height, sizeof(uint8), 1, stream);
fread(&ret.OffsetMask2, sizeof(uint32), 1, stream);
fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream);
return ret;
}

View File

@@ -77,35 +77,7 @@ public:
Vector3 Position;
uint32 OffsetMCCV;
void Read(FILE* stream)
{
fread(&Flags, sizeof(uint32), 1, stream);
fread(&IndexX, sizeof(uint32), 1, stream);
fread(&IndexY, sizeof(uint32), 1, stream);
fread(&Layers, sizeof(uint32), 1, stream);
fread(&DoodadRefs, sizeof(uint32), 1, stream);
fread(&OffsetMCVT, sizeof(uint32), 1, stream);
fread(&OffsetMCNR, sizeof(uint32), 1, stream);
fread(&OffsetMCLY, sizeof(uint32), 1, stream);
fread(&OffsetMCRF, sizeof(uint32), 1, stream);
fread(&OffsetMCAL, sizeof(uint32), 1, stream);
fread(&SizeMCAL, sizeof(uint32), 1, stream);
fread(&OffsetMCSH, sizeof(uint32), 1, stream);
fread(&SizeMCSH, sizeof(uint32), 1, stream);
fread(&AreaId, sizeof(uint32), 1, stream);
fread(&MapObjectRefs, sizeof(uint32), 1, stream);
fread(&Holes, sizeof(uint32), 1, stream);
LowQualityTextureMap = new uint32[4];
fread(LowQualityTextureMap, sizeof(uint32), 4, stream);
fread(&PredTex, sizeof(uint32), 1, stream);
fread(&NumberEffectDoodad, sizeof(uint32), 1, stream);
fread(&OffsetMCSE, sizeof(uint32), 1, stream);
fread(&SoundEmitters, sizeof(uint32), 1, stream);
fread(&OffsetMCLQ, sizeof(uint32), 1, stream);
fread(&SizeMCLQ, sizeof(uint32), 1, stream);
Position = Vector3::Read(stream);
fread(&OffsetMCCV, sizeof(uint32), 1, stream);
}
void Read(FILE* stream);
};
class MHDR
@@ -125,21 +97,7 @@ public:
uint32 OffsetMH2O;
uint32 OffsetMTFX;
void Read(FILE* stream)
{
fread(&Flags, sizeof(uint32), 1, stream);
fread(&OffsetMCIN, sizeof(uint32), 1, stream);
fread(&OffsetMTEX, sizeof(uint32), 1, stream);
fread(&OffsetMMDX, sizeof(uint32), 1, stream);
fread(&OffsetMMID, sizeof(uint32), 1, stream);
fread(&OffsetMWMO, sizeof(uint32), 1, stream);
fread(&OffsetMWID, sizeof(uint32), 1, stream);
fread(&OffsetMDDF, sizeof(uint32), 1, stream);
fread(&OffsetMODF, sizeof(uint32), 1, stream);
fread(&OffsetMFBO, sizeof(uint32), 1, stream);
fread(&OffsetMH2O, sizeof(uint32), 1, stream);
fread(&OffsetMTFX, sizeof(uint32), 1, stream);
}
void Read(FILE* stream);
};
class ModelHeader
@@ -196,72 +154,7 @@ public:
uint32 CountBoundingNormals;
uint32 OffsetBoundingNormals;
void Read(FILE* stream)
{
fread(&Magic, sizeof(char), 4, stream);
Magic[4] = '\0'; // null-terminate it.
fread(&Version, sizeof(uint32), 1, stream);
fread(&LengthModelName, sizeof(uint32), 1, stream);
fread(&OffsetName, sizeof(uint32), 1, stream);
fread(&ModelFlags, sizeof(uint32), 1, stream);
fread(&CountGlobalSequences, sizeof(uint32), 1, stream);
fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream);
fread(&CountAnimations, sizeof(uint32), 1, stream);
fread(&OffsetAnimations, sizeof(uint32), 1, stream);
fread(&CountAnimationLookup, sizeof(uint32), 1, stream);
fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream);
fread(&CountBones, sizeof(uint32), 1, stream);
fread(&OffsetBones, sizeof(uint32), 1, stream);
fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream);
fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream);
fread(&CountVertices, sizeof(uint32), 1, stream);
fread(&OffsetVertices, sizeof(uint32), 1, stream);
fread(&CountViews, sizeof(uint32), 1, stream);
fread(&CountColors, sizeof(uint32), 1, stream);
fread(&OffsetColors, sizeof(uint32), 1, stream);
fread(&CountTextures, sizeof(uint32), 1, stream);
fread(&OffsetTextures, sizeof(uint32), 1, stream);
fread(&CountTransparency, sizeof(uint32), 1, stream);
fread(&OffsetTransparency, sizeof(uint32), 1, stream);
fread(&CountUvAnimation, sizeof(uint32), 1, stream);
fread(&OffsetUvAnimation, sizeof(uint32), 1, stream);
fread(&CountTexReplace, sizeof(uint32), 1, stream);
fread(&OffsetTexReplace, sizeof(uint32), 1, stream);
fread(&CountRenderFlags, sizeof(uint32), 1, stream);
fread(&OffsetRenderFlags, sizeof(uint32), 1, stream);
fread(&CountBoneLookup, sizeof(uint32), 1, stream);
fread(&OffsetBoneLookup, sizeof(uint32), 1, stream);
fread(&CountTexLookup, sizeof(uint32), 1, stream);
fread(&OffsetTexLookup, sizeof(uint32), 1, stream);
fread(&CountTexUnits, sizeof(uint32), 1, stream);
fread(&OffsetTexUnits, sizeof(uint32), 1, stream);
fread(&CountTransLookup, sizeof(uint32), 1, stream);
fread(&OffsetTransLookup, sizeof(uint32), 1, stream);
fread(&CountUvAnimLookup, sizeof(uint32), 1, stream);
fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream);
fread(&CountColors, sizeof(uint32), 1, stream);
fread(&OffsetColors, sizeof(uint32), 1, stream);
fread(&CountTextures, sizeof(uint32), 1, stream);
fread(&OffsetTextures, sizeof(uint32), 1, stream);
fread(&CountTransparency, sizeof(uint32), 1, stream);
fread(&OffsetTransparency, sizeof(uint32), 1, stream);
fread(&CountUvAnimation, sizeof(uint32), 1, stream);
fread(&OffsetUvAnimation, sizeof(uint32), 1, stream);
fread(&CountTexReplace, sizeof(uint32), 1, stream);
fread(&OffsetTexReplace, sizeof(uint32), 1, stream);
VertexBox[0] = Vector3::Read(stream);
VertexBox[1] = Vector3::Read(stream);
fread(&VertexRadius, sizeof(float), 1, stream);
BoundingBox[0] = Vector3::Read(stream);
BoundingBox[1] = Vector3::Read(stream);
fread(&BoundingRadius, sizeof(float), 1, stream);
fread(&CountBoundingTriangles, sizeof(uint32), 1, stream);
fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream);
fread(&CountBoundingVertices, sizeof(uint32), 1, stream);
fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream);
fread(&CountBoundingNormals, sizeof(uint32), 1, stream);
fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream);
}
void Read(FILE* stream);
};
class WorldModelHeader
@@ -280,23 +173,7 @@ public:
Vector3 BoundingBox[2];
uint32 LiquidTypeRelated;
static WorldModelHeader Read(FILE* stream)
{
WorldModelHeader ret;
fread(&ret.CountMaterials, sizeof(uint32), 1, stream);
fread(&ret.CountGroups, sizeof(uint32), 1, stream);
fread(&ret.CountPortals, sizeof(uint32), 1, stream);
fread(&ret.CountLights, sizeof(uint32), 1, stream);
fread(&ret.CountModels, sizeof(uint32), 1, stream);
fread(&ret.CountDoodads, sizeof(uint32), 1, stream);
fread(&ret.CountSets, sizeof(uint32), 1, stream);
fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream);
fread(&ret.WmoId, sizeof(uint32), 1, stream);
ret.BoundingBox[0] = Vector3::Read(stream);
ret.BoundingBox[1] = Vector3::Read(stream);
fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream);
return ret;
}
static WorldModelHeader Read(FILE* stream);
};
class DoodadInstance
@@ -313,19 +190,7 @@ public:
float Scale;
uint32 LightColor;
static DoodadInstance Read(FILE* stream)
{
DoodadInstance ret;
fread(&ret.FileOffset, sizeof(uint32), 1, stream);
ret.Position = Vector3::Read(stream);
fread(&ret.QuatW, sizeof(float), 1, stream);
fread(&ret.QuatX, sizeof(float), 1, stream);
fread(&ret.QuatY, sizeof(float), 1, stream);
fread(&ret.QuatZ, sizeof(float), 1, stream);
fread(&ret.Scale, sizeof(float), 1, stream);
fread(&ret.LightColor, sizeof(uint32), 1, stream);
return ret;
}
static DoodadInstance Read(FILE* stream);
};
class DoodadSet
@@ -337,18 +202,7 @@ public:
uint32 CountInstances;
uint32 UnknownZero;
static DoodadSet Read(FILE* stream)
{
DoodadSet ret;
char name[21];
fread(&name, sizeof(char), 20, stream);
name[20] = '\0';
ret.Name = name;
fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream);
fread(&ret.CountInstances, sizeof(uint32), 1, stream);
fread(&ret.UnknownZero, sizeof(uint32), 1, stream);
return ret;
}
static DoodadSet Read(FILE* stream);
};
class LiquidHeader
@@ -362,17 +216,7 @@ public:
Vector3 BaseLocation;
uint16 MaterialId;
static LiquidHeader Read(FILE* stream)
{
LiquidHeader ret;
fread(&ret.CountXVertices, sizeof(uint32), 1, stream);
fread(&ret.CountYVertices, sizeof(uint32), 1, stream);
fread(&ret.Width, sizeof(uint32), 1, stream);
fread(&ret.Height, sizeof(uint32), 1, stream);
ret.BaseLocation = Vector3::Read(stream);
fread(&ret.MaterialId, sizeof(uint16), 1, stream);
return ret;
}
static LiquidHeader Read(FILE* stream);
};
class LiquidData
@@ -387,41 +231,7 @@ public:
return RenderFlags[x][y] != 0x0F;
}
static LiquidData Read(FILE* stream, LiquidHeader header)
{
LiquidData ret;
ret.HeightMap = new float*[header.CountXVertices];
for (uint32 i = 0; i < header.CountXVertices; ++i)
ret.HeightMap[i] = new float[header.CountYVertices];
ret.RenderFlags = new uint8*[header.Width];
for (uint32 i = 0; i < header.Width; ++i)
ret.RenderFlags[i] = new uint8[header.Height];
for (uint32 y = 0; y < header.CountYVertices; y++)
{
for (uint32 x = 0; x < header.CountXVertices; x++)
{
uint32 discard;
fread(&discard, sizeof(uint32), 1, stream);
float tmp;
fread(&tmp, sizeof(float), 1, stream);
ret.HeightMap[x][y] = tmp;
}
}
for (uint32 y = 0; y < header.Height; y++)
{
for (uint32 x = 0; x < header.Width; x++)
{
uint8 tmp;
fread(&tmp, sizeof(uint8), 1, stream);
ret.RenderFlags[x][y] = tmp;
}
}
return ret;
}
static LiquidData Read(FILE* stream, LiquidHeader& header);
};
class H2ORenderMask
@@ -435,12 +245,7 @@ public:
return (Mask[y] >> x & 1) != 0;
}
static H2ORenderMask Read(FILE* stream)
{
H2ORenderMask ret;
fread(&ret.Mask, sizeof(uint8), 8, stream);
return ret;
}
static H2ORenderMask Read(FILE* stream);
};
class MCNKLiquidData
@@ -452,17 +257,7 @@ public:
float** Heights;
H2ORenderMask Mask;
bool IsWater(int x, int y, float height)
{
if (!Heights)
return false;
if (!Mask.ShouldRender(x, y))
return false;
float diff = Heights[x][y] - height;
if (diff > Constants::MaxStandableHeight)
return true;
return false;
}
bool IsWater(int x, int y, float height);
};
class H2OHeader
@@ -473,14 +268,7 @@ public:
uint32 LayerCount;
uint32 OffsetRender;
static H2OHeader Read(FILE* stream)
{
H2OHeader ret;
fread(&ret.OffsetInformation, sizeof(uint32), 1, stream);
fread(&ret.LayerCount, sizeof(uint32), 1, stream);
fread(&ret.OffsetRender, sizeof(uint32), 1, stream);
return ret;
}
static H2OHeader Read(FILE* stream);
};
class H2OInformation
@@ -498,21 +286,7 @@ public:
uint32 OffsetMask2;
uint32 OffsetHeightmap;
static H2OInformation Read(FILE* stream)
{
H2OInformation ret;
fread(&ret.LiquidType, sizeof(uint16), 1, stream);
fread(&ret.Flags, sizeof(uint16), 1, stream);
fread(&ret.HeightLevel1, sizeof(float), 1, stream);
fread(&ret.HeightLevel2, sizeof(float), 1, stream);
fread(&ret.OffsetX, sizeof(uint8), 1, stream);
fread(&ret.OffsetY, sizeof(uint8), 1, stream);
fread(&ret.Width, sizeof(uint8), 1, stream);
fread(&ret.Height, sizeof(uint8), 1, stream);
fread(&ret.OffsetMask2, sizeof(uint32), 1, stream);
fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream);
return ret;
}
static H2OInformation Read(FILE* stream);
};
// Dummy class to act as an interface.