/*
* Copyright (C)
*
* Copyright (C) 2008-2016 TrinityCore
* Copyright (C) 2005-2009 MaNGOS
*/
#include "DoodadHandler.h"
#include "Chunk.h"
#include "Cache.h"
#include "Model.h"
#include "G3D/Matrix4.h"
DoodadHandler::DoodadHandler( ADT* adt ) :
ObjectDataHandler(adt), _definitions(NULL), _paths(NULL)
{
Chunk* mddf = adt->ObjectData->GetChunkByName("MDDF");
if (mddf)
ReadDoodadDefinitions(mddf);
Chunk* mmid = adt->ObjectData->GetChunkByName("MMID");
Chunk* mmdx = adt->ObjectData->GetChunkByName("MMDX");
if (mmid && mmdx)
ReadDoodadPaths(mmid, mmdx);
}
void DoodadHandler::ProcessInternal( MapChunk* mcnk )
{
if (!IsSane())
return;
uint32 refCount = mcnk->Header.DoodadRefs;
FILE* stream = mcnk->Source->GetStream();
fseek(stream, mcnk->Source->Offset + mcnk->Header.OffsetMCRF, SEEK_SET);
for (uint32 i = 0; i < refCount; i++)
{
int32 index;
int32 count;
if ((count = fread(&index, sizeof(int32), 1, stream)) != 1)
printf("DoodadHandler::ProcessInternal: Failed to read some data expected 1, read %d\n", count);
if (index < 0 || uint32(index) >= _definitions->size())
continue;
DoodadDefinition doodad = (*_definitions)[index];
if (_drawn.find(doodad.UniqueId) != _drawn.end())
continue;
_drawn.insert(doodad.UniqueId);
if (doodad.MmidIndex >= _paths->size())
continue;
std::string path = (*_paths)[doodad.MmidIndex];
Model* model = Cache->ModelCache.Get(path);
if (!model)
{
model = new Model(path);
Cache->ModelCache.Insert(path, model);
}
if (!model->IsCollidable)
continue;
Vertices.reserve(refCount * model->Vertices.size() * 0.2);
Triangles.reserve(refCount * model->Triangles.size() * 0.2);
InsertModelGeometry(doodad, model);
}
// Restore the stream position
fseek(stream, mcnk->Source->Offset, SEEK_SET);
}
void DoodadHandler::ReadDoodadDefinitions( Chunk* chunk )
{
int32 count = chunk->Length / 36;
_definitions = new std::vector;
_definitions->reserve(count);
FILE* stream = chunk->GetStream();
for (int i = 0; i < count; i++)
{
DoodadDefinition def;
def.Read(stream);
_definitions->push_back(def);
}
}
void DoodadHandler::ReadDoodadPaths( Chunk* id, Chunk* data )
{
int paths = id->Length / 4;
_paths = new std::vector();
_paths->reserve(paths);
for (int i = 0; i < paths; i++)
{
FILE* idStream = id->GetStream();
fseek(idStream, i * 4, SEEK_CUR);
uint32 offset;
if (fread(&offset, sizeof(uint32), 1, idStream) != 1)
printf("DoodadHandler::ReadDoodadPaths: Failed to read some data expected 1, read 0\n");
FILE* dataStream = data->GetStream();
fseek(dataStream, offset + data->Offset, SEEK_SET);
_paths->push_back(Utils::ReadString(dataStream));
}
}
void DoodadHandler::InsertModelGeometry(const DoodadDefinition& def, Model* model)
{
uint32 vertOffset = Vertices.size();
for (std::vector::iterator itr = model->Vertices.begin(); itr != model->Vertices.end(); ++itr)
Vertices.push_back(Utils::TransformDoodadVertex(def, *itr)); // Vertices have to be converted based on the information from the DoodadDefinition struct
for (std::vector >::iterator itr = model->Triangles.begin(); itr != model->Triangles.end(); ++itr)
Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_DOODAD, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset));
}
DoodadHandler::~DoodadHandler()
{
delete _definitions;
delete _paths;
}