Tools/MeshExtractor: Fixed Doodads and WMOs in the terrain.

Cleaned up a little.
This commit is contained in:
Sebastian Valle committed 2013-09-29 19:47:52 -05:00
1 parent 279183737c
commit 371dd07037
14 files changed
+67 -149

No files matched your search

+1 -1
View File
@@ -7,7 +7,7 @@ ADT::ADT( std::string file, int x, int y ) : ObjectData(NULL), Data(NULL), HasOb
_DoodadHandler(NULL), _WorldModelHandler(NULL), _LiquidHandler(NULL), X(x), Y(y)
{
Data = new ChunkedData(file);
ObjectData = new ChunkedData(/*Utils::Replace(file, ".adt", "_obj0.adt")*/file);
ObjectData = new ChunkedData(file);
if (ObjectData->Stream)
HasObjectData = true;
else
+3 -2
View File
@@ -15,7 +15,7 @@ class GenericCache
public:
GenericCache() {}
static const uint32 FlushLimit = 1000;
static const uint32 FlushLimit = 300; // We can't get too close to filling up all the memory, and we have to be wary of the maximum number of open streams.
void Insert(K key, T* val)
{
@@ -55,7 +55,8 @@ public:
void Clear()
{
ModelCache.Clear();
WorldModelCache.Clear();
}
};
@@ -114,7 +114,7 @@ void ContinentBuilder::Build(bool debug)
for (uint32 i = 0; i < NumberOfThreads; ++i)
Threads.push_back(new BuilderThread(this, debug, params));
printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads);
//for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr)
for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr)
{
bool next = false;
while (!next)
@@ -123,7 +123,7 @@ void ContinentBuilder::Build(bool debug)
{
if ((*_th)->Free)
{
(*_th)->SetData(29/*itr->X*/, 40/*itr->Y*/, MapId, Continent);
(*_th)->SetData(itr->X, itr->Y, MapId, Continent);
(*_th)->activate();
next = true;
break;
+3 -18
View File
@@ -4,10 +4,9 @@
#include "Model.h"
#include "G3D/Matrix4.h"
DoodadHandler::DoodadHandler( ADT* adt ) : ObjectDataHandler(adt), _definitions(NULL), _paths(NULL)
DoodadHandler::DoodadHandler( ADT* adt ) :
ObjectDataHandler(adt), _definitions(NULL), _paths(NULL)
{
/*if (!adt->HasObjectData)
return;*/
Chunk* mddf = adt->ObjectData->GetChunkByName("MDDF");
if (mddf)
ReadDoodadDefinitions(mddf);
@@ -92,26 +91,12 @@ void DoodadHandler::ReadDoodadPaths( Chunk* id, Chunk* data )
}
}
Vector3 TransformDoodadVertex(const DoodadDefinition& def, Vector3& vec)
{
// Rotate our Doodad vertex
G3D::Matrix4 rot = G3D::Matrix3::fromEulerAnglesXZY(Utils::ToRadians(-def.Rotation.z), Utils::ToRadians(def.Rotation.x), Utils::ToRadians(-def.Rotation.y + 180));
Vector3 ret = Utils::VectorTransform(vec, rot);
// Convert the rotated Doodad vector to our current coordinate system
ret = Vector3(ret.x, ret.z, -ret.y);
// And finally translate it to our origin
return ret + Vector3(Constants::MaxXY - def.Position.z, Constants::MaxXY - def.Position.x, def.Position.y);
}
void DoodadHandler::InsertModelGeometry(const DoodadDefinition& def, Model* model)
{
G3D::Matrix4 transformation = Utils::GetTransformation(def);
uint32 vertOffset = Vertices.size();
for (std::vector<Vector3>::iterator itr = model->Vertices.begin(); itr != model->Vertices.end(); ++itr)
Vertices.push_back(TransformDoodadVertex(def, *itr));
Vertices.push_back(Utils::TransformDoodadVertex(def, *itr)); // Vertices have to be converted based on the information from the DoodadDefinition struct
for (std::vector<Triangle<uint16> >::iterator itr = model->Triangles.begin(); itr != model->Triangles.end(); ++itr)
Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_DOODAD, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset));
+1 -2
View File
@@ -111,8 +111,7 @@ void MPQFile::close()
FILE* MPQFile::GetFileStream()
{
FILE* file = NULL;
tmpfile_s(&file);
FILE* file = tmpfile();
if (!file)
{
printf("Could not create temporary file. Please run as Administrator or root\n");
+2 -1
View File
@@ -10,6 +10,8 @@
#include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h"
#include <stdio.h>
#include <set>
MPQManager* MPQHandler;
@@ -340,7 +342,6 @@ void LoadTile(dtNavMesh*& navMesh, const char* tile)
int main(int argc, char* argv[])
{
system("pause");
_setmaxstdio(2048);
uint32 threads = 4, extractFlags = 0;
std::set<uint32> mapIds;
+14 -14
View File
@@ -15,9 +15,9 @@ Model::Model( std::string path ) : IsCollidable(false), IsBad(false)
Header.OffsetBoundingTriangles > 0 && Header.BoundingRadius > 0.0f)
{
IsCollidable = true;
ReadVertices(Stream);
ReadBoundingNormals(Stream);
ReadBoundingTriangles(Stream);
ReadVertices();
ReadBoundingNormals();
ReadBoundingTriangles();
}
}
@@ -27,41 +27,41 @@ Model::~Model()
fclose(Stream);
}
void Model::ReadVertices( FILE* stream )
void Model::ReadVertices()
{
fseek(stream, Header.OffsetBoundingVertices, SEEK_SET);
fseek(Stream, Header.OffsetBoundingVertices, SEEK_SET);
Vertices.reserve(Header.CountBoundingVertices);
for (uint32 i = 0; i < Header.CountBoundingVertices; ++i)
{
Vertices.push_back(Vector3::Read(stream));
Vertices.push_back(Vector3::Read(Stream));
if (Constants::ToWoWCoords)
Vertices[i] = Utils::ToWoWCoords(Vertices[i]);
}
}
void Model::ReadBoundingTriangles( FILE* stream )
void Model::ReadBoundingTriangles()
{
fseek(stream, Header.OffsetBoundingTriangles, SEEK_SET);
fseek(Stream, Header.OffsetBoundingTriangles, SEEK_SET);
Triangles.reserve(Header.CountBoundingTriangles / 3);
for (uint32 i = 0; i < Header.CountBoundingTriangles / 3; i++)
{
Triangle<uint16> tri;
tri.Type = Constants::TRIANGLE_TYPE_DOODAD;
int count = 0;
count += fread(&tri.V0, sizeof(uint16), 1, stream);
count += fread(&tri.V1, sizeof(uint16), 1, stream);
count += fread(&tri.V2, sizeof(uint16), 1, stream);
count += fread(&tri.V0, sizeof(uint16), 1, Stream);
count += fread(&tri.V1, sizeof(uint16), 1, Stream);
count += fread(&tri.V2, sizeof(uint16), 1, Stream);
if (count != 3)
printf("Model::ReadBoundingTriangles: Error reading data, expected 3, read %d\n", count);
Triangles.push_back(tri);
}
}
void Model::ReadBoundingNormals( FILE* stream )
void Model::ReadBoundingNormals()
{
fseek(stream, Header.OffsetBoundingNormals, SEEK_SET);
fseek(Stream, Header.OffsetBoundingNormals, SEEK_SET);
Normals.reserve(Header.CountBoundingNormals);
for (uint32 i = 0; i < Header.CountBoundingNormals; i++)
Normals.push_back(Vector3::Read(stream));
Normals.push_back(Vector3::Read(Stream));
}
+3 -3
View File
@@ -9,9 +9,9 @@ public:
Model(std::string path);
~Model();
void ReadVertices(FILE* stream);
void ReadBoundingTriangles(FILE* stream);
void ReadBoundingNormals(FILE* stream);
void ReadVertices();
void ReadBoundingTriangles();
void ReadBoundingNormals();
ModelHeader Header;
std::vector<Vector3> Vertices;
std::vector<Vector3> Normals;
@@ -5,7 +5,5 @@
void ObjectDataHandler::ProcessMapChunk( MapChunk* chunk )
{
/*if (!Source->HasObjectData)
return;*/
ProcessInternal(chunk);
}
+19 -63
View File
@@ -86,56 +86,27 @@ std::string Utils::FixModelPath(const std::string& path )
return Utils::GetPathBase(path) + ".M2";
}
G3D::Matrix4 Utils::GetTransformation(const IDefinition& def)
Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec)
{
G3D::Matrix4 translation;
if (def.Position.x == 0.0f && def.Position.y == 0.0f && def.Position.z == 0.0f)
translation = G3D::Matrix4::identity();
else
translation = G3D::Matrix4::translation(-(def.Position.z - Constants::MaxXY),
-(def.Position.x - Constants::MaxXY), def.Position.y);
// Sources of information:
/// http://www.pxr.dk/wowdev/wiki/index.php?title=ADT/v18&oldid=3715
//G3D::Matrix4 rotation = RotationX(ToRadians(def.Rotation.z)) * RotationY(ToRadians(def.Rotation.x)) * RotationZ(ToRadians(def.Rotation.y + 180));
G3D::Matrix4 rotation = G3D::Matrix4::identity().rollDegrees(def.Rotation.z).pitchDegrees(def.Rotation.x).yawDegrees(def.Rotation.y + 180);
if (def.Scale() < 1.0f || def.Scale() > 1.0f)
return G3D::Matrix4::scale(def.Scale()) * rotation * translation;
return rotation * translation;
// This function applies to both external doodads and WMOs
// Rotate our Doodad vertex
G3D::Matrix4 rot = G3D::Matrix3::fromEulerAnglesXYZ(Utils::ToRadians(def.Rotation.z), Utils::ToRadians(-def.Rotation.x), Utils::ToRadians(def.Rotation.y + 180));
Vector3 ret = Utils::VectorTransform(vec, rot);
// And finally scale and translate it to our origin
return (ret * def.Scale()) + Vector3(Constants::MaxXY - def.Position.z, Constants::MaxXY - def.Position.x, def.Position.y);
}
G3D::Matrix4 Utils::RotationY( float angle )
Vector3 Utils::TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec )
{
float _cos = cos(angle);
float _sin = sin(angle);
G3D::Matrix4 ret = G3D::Matrix4::identity();
ret[0][0] = _cos;
ret[3][0] = -_sin;
ret[0][3] = _sin;
ret[2][2] = _cos;
return ret;
}
G3D::Quat quat = G3D::Quat(-inst.QuatY, inst.QuatZ, -inst.QuatX, inst.QuatW);
G3D::Matrix4 Utils::RotationZ( float angle )
{
float _cos = cos(angle);
float _sin = sin(angle);
G3D::Matrix4 ret = G3D::Matrix4::identity();
ret[0][0] = _cos;
ret[1][0] = _sin;
ret[0][1] = -_sin;
ret[1][1] = _cos;
return ret;
}
G3D::Matrix4 Utils::RotationX(float angle)
{
float _cos = cos(angle);
float _sin = sin(angle);
G3D::Matrix4 ret = G3D::Matrix4::identity();
ret[1][1] = _cos;
ret[2][1] = _sin;
ret[1][2] = -_sin;
ret[2][2] = _cos;
return ret;
Vector3 ret = Utils::VectorTransform(vec, G3D::Matrix4(quat.toRotationMatrix()));
return (ret * (inst.Scale / 1024.0f)) + Vector3(Constants::MaxXY - inst.Position.z, Constants::MaxXY - inst.Position.x, inst.Position.y);
}
float Utils::ToRadians( float degrees )
@@ -143,13 +114,10 @@ float Utils::ToRadians( float degrees )
return Constants::PI * degrees / 180.0f;
}
Vector3 Utils::VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix )
Vector3 Utils::VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix, bool normal )
{
G3D::Vector3 ret(vec.x, vec.y, vec.z);
ret = matrix.homoMul(ret, 1);
/*ret.x = vec.x * matrix[0][0] + vec.y * matrix[1][0] + vec.z * matrix[2][0] + matrix[3][0];
ret.y = vec.x * matrix[0][1] + vec.y * matrix[1][1] + vec.z * matrix[2][1] + matrix[3][1];
ret.z = vec.x * matrix[0][2] + vec.y * matrix[1][2] + vec.z * matrix[2][2] + matrix[3][2];*/
ret = matrix.homoMul(ret, normal ? 0 : 1);
return Vector3(ret.x, ret.y, ret.z);
}
@@ -169,11 +137,11 @@ Vector3 Vector3::Read( FILE* file )
return ret;
}
Vector3 Utils::GetLiquidVert(const G3D::Matrix4& transformation, Vector3 basePosition, float height, int /*x*/, int /*y*/)
Vector3 Utils::GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int /*x*/, int /*y*/)
{
if (Utils::Distance(height, 0.0f) > 0.5f)
basePosition.z = 0.0f;
return Utils::VectorTransform(basePosition + Vector3(basePosition.x * Constants::UnitSize, basePosition.y * Constants::UnitSize, height), transformation);
return Utils::TransformDoodadVertex(def, basePosition + Vector3(basePosition.x * Constants::UnitSize, basePosition.y * Constants::UnitSize, height));
}
float Utils::Distance( float x, float y )
@@ -192,18 +160,6 @@ std::string Utils::Replace( std::string str, const std::string& oldStr, const st
return str;
}
G3D::Matrix4 Utils::GetWmoDoodadTransformation(const DoodadInstance& inst, const WorldModelDefinition& root )
{
G3D::Matrix4 rootTransformation = Utils::GetTransformation(root);
G3D::Matrix4 translation = G3D::Matrix4::translation(inst.Position.x, inst.Position.y, inst.Position.z);
G3D::Matrix4 scale = G3D::Matrix4::scale(inst.Scale);
G3D::Matrix4 rotation = Utils::RotationY(Constants::PI);
G3D::Quat quat(-inst.QuatY, inst.QuatZ, -inst.QuatX, inst.QuatW);
G3D::Matrix4 quatRotation = quat.toRotationMatrix();
return scale * rotation * quatRotation ** translation * rootTransformation;
}
void Utils::SaveToDisk( FILE* stream, const std::string& path )
{
FILE* disk = fopen(path.c_str(), "wb");
+5 -7
View File
@@ -13,6 +13,7 @@
#include <ace/Stack_Trace.h>
struct WorldModelDefinition;
class DoodadDefinition;
class DoodadInstance;
#define ASSERT(assertion) { if (!(assertion)) { ACE_Stack_Trace st; fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__, __FUNCTION__, #assertion, st.c_str()); *((volatile int*)NULL) = 0; } }
@@ -356,7 +357,6 @@ public:
static Vector3 ToRecast(const Vector3& val );
static std::string GetAdtPath(const std::string& world, int x, int y);
static std::string FixModelPath(const std::string& path);
static G3D::Matrix4 GetTransformation(const IDefinition& def);
/// They say its better to declare template functions in the header files.
template <typename T>
static std::string ToString(T val)
@@ -365,13 +365,9 @@ public:
ss << val;
return ss.str();
}
static G3D::Matrix4 RotationX(float angle);
static G3D::Matrix4 RotationY(float angle);
static G3D::Matrix4 RotationZ(float angle);
static float ToRadians(float degrees);
static Vector3 VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix);
static std::string GetPathBase(const std::string& path);
static Vector3 GetLiquidVert(const G3D::Matrix4& transformation, Vector3 basePosition, float height, int x, int y);
static Vector3 GetLiquidVert(const IDefinition& def, 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)
@@ -382,11 +378,13 @@ public:
return true;
}
static std::string Replace( std::string str, const std::string& oldStr, const std::string& newStr );
static G3D::Matrix4 GetWmoDoodadTransformation(const DoodadInstance& inst, const WorldModelDefinition& root );
static void CreateDir( const std::string& Path );
static void SaveToDisk(FILE* stream, const std::string& path);
static Vector3 ToWoWCoords(const Vector3& vec );
static std::string GetExtension( std::string path );
static char* GetPlainName(const char* FileName);
static Vector3 TransformDoodadVertex(const IDefinition& def, Vector3& vec);
static Vector3 VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix, bool normal = false );
static Vector3 TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec );
};
#endif
+7 -34
View File
@@ -31,8 +31,6 @@ WorldModelDefinition WorldModelDefinition::Read( FILE* file )
WorldModelHandler::WorldModelHandler( ADT* adt ) : ObjectDataHandler(adt), _definitions(NULL), _paths(NULL)
{
/*if (!adt->HasObjectData)
return;*/
ReadModelPaths();
ReadDefinitions();
}
@@ -81,41 +79,17 @@ void WorldModelHandler::ProcessInternal( MapChunk* mcnk )
fseek(stream, mcnk->Source->Offset, SEEK_SET);
}
Vector3 TransformDoodadVertex(const IDefinition& def, Vector3& vec)
{
// Rotate our Doodad vertex
G3D::Matrix4 rot = G3D::Matrix3::fromEulerAnglesXZY(Utils::ToRadians(-def.Rotation.z), Utils::ToRadians(def.Rotation.x), Utils::ToRadians(-def.Rotation.y + 180));
Vector3 ret = Utils::VectorTransform(vec, rot);
// Convert the rotated Doodad vector to our current coordinate system
ret = Vector3(ret.x, ret.z, -ret.y);
// And finally translate it to our origin
return ret + Vector3(Constants::MaxXY - def.Position.z, Constants::MaxXY - def.Position.x, def.Position.y);
}
Vector3 TransformDoodadToWMO(Vector3& vec, const DoodadInstance& inst, const WorldModelRoot& rootDef)
{
Vector3 translation = Vector3(inst.Position.x, inst.Position.z, -inst.Position.y);
G3D::Quat quat = G3D::Quat(inst.QuatX, inst.QuatZ, -inst.QuatY, inst.QuatW);
G3D::Matrix3 rotM;
quat.toRotationMatrix(rotM);
return (Utils::VectorTransform(vec, G3D::Matrix4(rotM)) + translation) * (1.0f / inst.Scale);
}
void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, WorldModelDefinition& def, WorldModelRoot* root )
{
G3D::Matrix4 transformation = Utils::GetTransformation(def);
for (std::vector<WorldModelGroup>::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group)
{
uint32 vertOffset = verts.size();
for (std::vector<Vector3>::iterator itr2 = group->Vertices.begin(); itr2 != group->Vertices.end(); ++itr2)
verts.push_back(TransformDoodadVertex(def, *itr2)/*Utils::VectorTransform(*itr2, transformation)*/);
verts.push_back(Utils::TransformDoodadVertex(def, *itr2)); // Transform the vertex to world space
for (uint32 i = 0; i < group->Triangles.size(); ++i)
{
// only include collidable tris
// only include colliding tris
if ((group->TriangleFlags[i] & 0x04) != 0 && group->TriangleMaterials[i] != 0xFF)
continue;
Triangle<uint16> tri = group->Triangles[i];
@@ -146,10 +120,9 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
if (!model->IsCollidable)
continue;
G3D::Matrix4 doodadTransformation = Utils::GetWmoDoodadTransformation(*instance, def);
int vertOffset = verts.size();
for (std::vector<Vector3>::iterator itr2 = model->Vertices.begin(); itr2 != model->Vertices.end(); ++itr2)
verts.push_back(TransformDoodadToWMO(*itr2, *instance, *root)/*TransformDoodadVertex(instance, *itr2)*//*Utils::VectorTransform(*itr2, doodadTransformation)*/);
verts.push_back(Utils::TransformDoodadVertex(def, Utils::TransformWmoDoodad(*instance, def, *itr2)));
for (std::vector<Triangle<uint16> >::iterator itr2 = model->Triangles.begin(); itr2 != model->Triangles.end(); ++itr2)
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WMO, itr2->V0 + vertOffset, itr2->V1 + vertOffset, itr2->V2 + vertOffset));
}
@@ -171,13 +144,13 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
continue;
uint32 vertOffset = verts.size();
verts.push_back(Utils::GetLiquidVert(transformation, liquidHeader.BaseLocation,
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x][y], x, y));
verts.push_back(Utils::GetLiquidVert(transformation, liquidHeader.BaseLocation,
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x + 1][y], x + 1, y));
verts.push_back(Utils::GetLiquidVert(transformation, liquidHeader.BaseLocation,
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x][y + 1], x, y + 1));
verts.push_back(Utils::GetLiquidVert(transformation, liquidHeader.BaseLocation,
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x + 1][y + 1], x + 1, y + 1));
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset + 2, vertOffset + 1));
@@ -12,6 +12,12 @@ WorldModelRoot::WorldModelRoot( std::string path )
ReadDoodadSets();
}
WorldModelRoot::~WorldModelRoot()
{
if (Data)
delete Data;
}
void WorldModelRoot::ReadGroups()
{
std::string pathBase = Utils::GetPathBase(Path);
@@ -11,6 +11,7 @@ class WorldModelRoot
{
public:
WorldModelRoot(std::string path);
~WorldModelRoot();
std::string Path;
ChunkedData* Data;
WorldModelHeader Header;