Tools: Made more updates to the MeshExtractor

This commit is contained in:
Subv
2012-09-28 07:59:22 -05:00
parent 50f833a008
commit ad0cd9f40a
7 changed files with 186 additions and 15 deletions

View File

@@ -4,17 +4,19 @@
#include "MapChunk.h"
#include "DoodadHandler.h"
#include "WorldModelHandler.h"
#include "LiquidHandler.h"
class ADT
{
public:
ADT();
~ADT() { delete[] MapChunks; delete ObjectData; delete Data; }
ADT(std::string file);
~ADT();
void Read();
ChunkedData* ObjectData;
ChunkedData* Data;
// This here is not a pointer, is an array of objects ( made this way to allow the dynamic allocation )
MapChunk* MapChunks;
std::vector<MapChunk*> MapChunks;
MHDR Header;
// Can we dispose of this?
bool HasObjectData;

View File

@@ -1 +1,95 @@
#include "LiquidHandler.h"
#include "LiquidHandler.h"
#include "Utils.h"
LiquidHandler::LiquidHandler( ADT* adt ) : Source(adt)
{
HandleNewLiquid();
}
void LiquidHandler::HandleNewLiquid()
{
Chunk* chunk = Source->Data->GetChunkByName("MH2O");
if (!chunk)
return;
Vertices.reserve(1000);
Triangles.reserve(1000);
FILE* stream = chunk->GetStream();
H2OHeader header[256];
MCNKData.reserve(256);
for (int i = 0; i < 256; i++)
header[i] = H2OHeader::Read(stream);
for (int i = 0; i < 256; i++)
{
H2OHeader h = header[i];
if (h.LayerCount == 0)
continue;
fseek(stream, chunk->Offset + h.OffsetInformation, SEEK_SET);
H2OInformation information = H2OInformation::Read(stream);
float** heights = new float*[9];
for (int i = 0; i < 9; ++i)
heights[i] = new float[9];
H2ORenderMask renderMask;
if (information.LiquidType != 2)
{
fseek(stream, chunk->Offset + h.OffsetRender, SEEK_SET);
renderMask = H2ORenderMask::Read(stream);
if ((Utils::IsAllZero(renderMask.Mask, 8) || (information.Width == 8 && information.Height == 8)) && information.OffsetMask2)
{
fseek(stream, chunk->Offset + information.OffsetMask2, SEEK_SET);
uint32 size = ceil(information.Width * information.Height / 8.0f);
uint8* altMask = new uint8[size];
fread(altMax, sizeof(uint8), size, stream);
for (int mi = 0; mi < size; mi++)
renderMask.Mask[mi + information.OffsetY] |= altMask[mi];
delete[] altMask;
}
fseek(stream, chunk->Offset + information.OffsetHeightmap, SEEK_SET);
for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++)
for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++)
fread(&heights[x][y], sizeof(float), 1, stream);
}
else
{
// Fill with ocean data
for (uint32 i = 0; i < 8; ++i)
renderMask.Mask[i] = 0xFF;
for (uint32 y = 0; y < 9; ++y)
for (uint32 x = 0; x < 9; ++x)
heights[x][y] = information.HeightLevel1;
}
MCNKData.push_back(MCNKLiquidData(heights, renderMask));
for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++)
{
for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++)
{
if (!renderMask.ShouldRender(x, y))
continue;
MapChunk* mapChunk = Source->MapChunks[i];
Vector3 location = mapChunk->Header.Position;
location.y = location.y - (x * Constants::UnitSize);
location.x = location.x - (y * Constants::UnitSize);
location.z = heights[x][y];
uint32 vertOffset = Vertices.size();
Vertices.push_back(location);
Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y, location.z));
Vertices.push_back(new Vector3(location.x, location.y - Constants::UnitSize, location.z));
Vertices.push_back(new Vector3(location.x - Constants::UnitSize, location.y - Constants::UnitSize, location.z));
Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset+2, vertOffset + 1));
Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1));
}
}
}
}

View File

@@ -9,9 +9,12 @@
class LiquidHandler
{
public:
LiquidHandler(ADT* adt);
ADT* Source;
std::vector<Vector3> Vertices;
std::vector<Triangle<uint32> > Triangles;
std::vector<MCNKLiquidData> MCNKData;
private:
void HandleNewLiquid();
};
#endif

View File

@@ -1,7 +1,7 @@
#include "MapChunk.h"
#include "ADT.h"
MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : adt(_adt), Source(chunk), Vertices(NULL)
MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : Adt(_adt), Source(chunk), Vertices(NULL)
{
FILE* stream = chunk->GetStream();
Header.Read(stream);
@@ -26,14 +26,14 @@ void MapChunk::GenerateTriangles()
uint32 center = (17 * y) + 9 + x;
uint8 triangleType = Constants::TRIANGLE_TYPE_TERRAIN;
if (ADT.LiquidHandler && ADT.LiquidHandler.MCNKData)
if (Adt->_LiquidHandler && !Adt->_LiquidHandler->MCNKData.empty())
{
var data = ADT.LiquidHandler.MCNKData[Index];
MCNKLiquidData& data = Adt->_LiquidHandler->MCNKData[Index];
uint32 maxHeight = std::max(
std::max(
std::max(std::max(Vertices[topLeft].z, Vertices[topRight].z), Vertices[bottomLeft].z),
Vertices[bottomRight].z), Vertices[center].z);
if (data && data->IsWater(x, y, maxHeight))
if (data.IsWater(x, y, maxHeight))
triangleType = Constants::TRIANGLE_TYPE_WATER;
}

View File

@@ -15,7 +15,7 @@ public:
void GenerateTriangles();
void GenerateVertices(FILE* stream);
static bool HasHole(uint32 map, int x, int y);
ADT* adt;
ADT* Adt;
Chunk* Source;
MapChunkHeader Header;
Vector3* Vertices;

View File

@@ -161,3 +161,14 @@ float Utils::Distance( float x, float y )
{
return sqrt(x*x + y*y);
}
std::string Utils::Replace( std::string str, const std::string& oldStr, const std::string& newStr )
{
size_t pos = 0;
while((pos = str.find(oldStr, pos)) != std::string::npos)
{
str.replace(pos, oldStr.length(), newStr);
pos += newStr.length();
}
return str;
}

View File

@@ -16,9 +16,9 @@ struct Vector3
float x;
float y;
float z;
Vector3 operator+(Vector3 right, Vector3 left)
Vector3 operator +(Vector3 const& other)
{
return Vector3(right.x+left.x, right.y+left.y, right.z+left.z);
return Vector3(x + other.x, y + other.y, z + other.z);
}
static Vector3 Read(FILE* file);
};
@@ -380,7 +380,7 @@ public:
return RenderFlags[x][y] != 0x0F;
}
public static LiquidData Read(FILE* stream, LiquidHeader header)
static LiquidData Read(FILE* stream, LiquidHeader header)
{
LiquidData ret;
ret.HeightMap = new float*[header.CountXVertices];
@@ -440,14 +440,15 @@ class MCNKLiquidData
{
public:
MCNKLiquidData() {}
MCNKLiquidData(float** heights, H2ORenderMask mask) : Heights(heights), Mask(mask) {}
const float MaxStandableHeight = 1.5f;
float** Heights;
H2ORenderMask* Mask;
H2ORenderMask Mask;
bool IsWater(int x, int y, float height)
{
if (!Heights || !Mask)
if (!Heights)
return false;
if (!Mask->ShouldRender(x, y))
return false;
@@ -458,6 +459,56 @@ public:
}
};
class H2OHeader
{
public:
H2OHeader() {}
uint32 OffsetInformation;
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;
}
};
class H2OInformation
{
public:
H2OInformation() {}
uint16 LiquidType;
uint16 Flags;
float HeightLevel1;
float HeightLevel2;
uint8 OffsetX;
uint8 OffsetY;
uint8 Width;
uint8 Height;
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;
}
};
// Dummy class to act as an interface.
class IDefinition
{
@@ -493,5 +544,15 @@ public:
static std::string GetPathBase(std::string path);
static Vector3 GetLiquidVert(G3D::Matrix4 transformation, Vector3 basePosition, float height, int x, int y);
static float Distance(float x, float y);
template<typename T>
static bool IsAllZero(T* arr, uint32 size)
{
for (uint32 i = 0; i < size; ++i)
if (arr[i])
return false;
return true;
}
static std::string Utils::Replace( std::string str, const std::string& oldStr, const std::string& newStr );
};
#endif