* WMO Mesh file loader
* WMOs are not rotated correctly yet * Stuffextract and MapMgr patched to display WMOs * Also some small fixes to pacify GCC
This commit is contained in:
parent
8bef509a21
commit
7c885d2b50
334
src/Client/GUI/CWMOMeshFileLoader.cpp
Normal file
334
src/Client/GUI/CWMOMeshFileLoader.cpp
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include "MemoryDataHolder.h"
|
||||||
|
#include "MemoryInterface.h"
|
||||||
|
#include "CWMOMeshFileLoader.h"
|
||||||
|
#include "SSkinnedMesh.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
inline void flipcc(irr::u8 *fcc)
|
||||||
|
{
|
||||||
|
char t;
|
||||||
|
t=fcc[0];
|
||||||
|
fcc[0]=fcc[3];
|
||||||
|
fcc[3]=t;
|
||||||
|
t=fcc[1];
|
||||||
|
fcc[1]=fcc[2];
|
||||||
|
fcc[2]=t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace irr
|
||||||
|
{
|
||||||
|
namespace scene
|
||||||
|
{
|
||||||
|
|
||||||
|
CWMOMeshFileLoader::CWMOMeshFileLoader(IrrlichtDevice* device, c8* texdir):Device(device), Texdir(texdir)
|
||||||
|
{
|
||||||
|
Mesh = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CWMOMeshFileLoader::~CWMOMeshFileLoader()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CWMOMeshFileLoader::isALoadableFileExtension(const c8* filename)const
|
||||||
|
{
|
||||||
|
return strstr(filename, ".wmo")!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! creates/loads an animated mesh from the file.
|
||||||
|
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||||
|
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||||
|
//! See IUnknown::drop() for more information.
|
||||||
|
IAnimatedMesh* CWMOMeshFileLoader::createMesh(io::IReadFile* file)
|
||||||
|
{
|
||||||
|
if(!file)
|
||||||
|
return 0;
|
||||||
|
MeshFile = file;
|
||||||
|
std::string filename=MeshFile->getFileName();
|
||||||
|
Mesh = new scene::CSkinnedMesh();
|
||||||
|
|
||||||
|
if ( load(true) )//We try loading a root file first!
|
||||||
|
{
|
||||||
|
for(u32 i=0;i<rootHeader.nGroups;i++)//On success, load all group files. This is getting slow as molasses for large files like Stormwind.wmo
|
||||||
|
{
|
||||||
|
char grpfilename[255];
|
||||||
|
sprintf(grpfilename,"%s_%03u.wmo",filename.substr(0,filename.length()-4).c_str(),i);
|
||||||
|
logdebug("%s",grpfilename);
|
||||||
|
MeshFile = io::IrrCreateIReadFileBasic(Device,grpfilename);
|
||||||
|
if(!MeshFile)
|
||||||
|
{
|
||||||
|
logerror("Could not read file %s!",grpfilename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
load(false);
|
||||||
|
}
|
||||||
|
Mesh->recalculateBoundingBox();
|
||||||
|
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(Mesh); //Fix inverted surfaces after the rotation
|
||||||
|
//Does this crash on windows?
|
||||||
|
Device->getSceneManager()->getMeshManipulator()->recalculateNormals(Mesh,true);//just to be sure
|
||||||
|
logdebug("Complete Mesh contains a total of %u submeshes!",Mesh->getMeshBufferCount());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Mesh->drop();
|
||||||
|
Mesh = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mesh;
|
||||||
|
}
|
||||||
|
bool CWMOMeshFileLoader::load(bool _root)
|
||||||
|
{
|
||||||
|
bool isRootFile = _root;
|
||||||
|
u8 _cc[5];
|
||||||
|
u8 *fourcc = &_cc[0];
|
||||||
|
fourcc[4]=0;
|
||||||
|
u32 size;
|
||||||
|
u32 textureOffset;
|
||||||
|
|
||||||
|
logdebug("Trying to open file %s",MeshFile->getFileName());
|
||||||
|
|
||||||
|
while(MeshFile->getPos() < MeshFile->getSize())
|
||||||
|
{
|
||||||
|
printf("position 0x%lX ",MeshFile->getPos());
|
||||||
|
MeshFile->read(fourcc,4);
|
||||||
|
MeshFile->read(&size,4);
|
||||||
|
flipcc(fourcc);
|
||||||
|
printf("Reading Chunk: %s size %u\n", (char*)fourcc,size);
|
||||||
|
|
||||||
|
if(!strcmp((char*)fourcc,"MVER")){
|
||||||
|
logdebug("MVER Chunk: %s",(char*)fourcc);
|
||||||
|
MeshFile->seek(size,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Start root file parsing
|
||||||
|
else if(!strcmp((char*)fourcc,"MOHD")){
|
||||||
|
MeshFile->read(&rootHeader,sizeof(RootHeader));
|
||||||
|
logdebug("Read Root Header: %u Textures, %u Groups, %u Models", rootHeader.nTextures, rootHeader.nGroups, rootHeader.nModels);
|
||||||
|
if(!isRootFile)//We should be reading a group file and found a root header, abort
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MOTX")){
|
||||||
|
textureOffset=MeshFile->getPos();
|
||||||
|
MeshFile->seek(size,true);
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MOMT")){
|
||||||
|
if(WMOMTexDefinition.size()>0)
|
||||||
|
WMOMTexDefinition.clear();
|
||||||
|
|
||||||
|
MOMT_Data tempMOMT;
|
||||||
|
for(u32 i =0;i<(size/sizeof(MOMT_Data));i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempMOMT,sizeof(MOMT_Data));
|
||||||
|
WMOMTexDefinition.push_back(tempMOMT);
|
||||||
|
}
|
||||||
|
logdebug("Read %u/%u TextureDefinitions",WMOMTexDefinition.size(),(size/sizeof(MOMT_Data)));
|
||||||
|
|
||||||
|
u32 tempOffset = MeshFile->getPos();//Save current position for further reading until texture file names are read.
|
||||||
|
|
||||||
|
if(WMOMTextureFiles.size()>0)
|
||||||
|
WMOMTextureFiles.clear();
|
||||||
|
std::string tempTexName;
|
||||||
|
u32 texNameSize;
|
||||||
|
|
||||||
|
for(u32 i =0;i<WMOMTexDefinition.size();i++)
|
||||||
|
{
|
||||||
|
texNameSize = WMOMTexDefinition[i].endNameIndex-WMOMTexDefinition[i].startNameIndex; tempTexName.resize(texNameSize);
|
||||||
|
MeshFile->seek(textureOffset+WMOMTexDefinition[i].startNameIndex);
|
||||||
|
MeshFile->read((void*)tempTexName.c_str(),WMOMTexDefinition[i].endNameIndex-WMOMTexDefinition[i].startNameIndex);
|
||||||
|
logdebug("Texture %u: %s",i,tempTexName.c_str());
|
||||||
|
WMOMTextureFiles.push_back(tempTexName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshFile->seek(tempOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Start Group file parsing
|
||||||
|
else if(!strcmp((char*)fourcc,"MOGP")){
|
||||||
|
logdebug("header okay: %s",(char*)fourcc);
|
||||||
|
MeshFile->seek(68,true);
|
||||||
|
if(isRootFile)//We should be reading a root file and found a Group header, abort
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MOPY")){//Texturing information (1 per triangle);
|
||||||
|
if(WMOMTexData.size()>0)
|
||||||
|
WMOMTexData.clear();
|
||||||
|
submeshes.clear();//Saves last vertex of submes
|
||||||
|
u16 previous_texid=999;//outside u8 space
|
||||||
|
MOPY_Data tempMOPY;
|
||||||
|
for(u32 i =0;i<(size/sizeof(MOPY_Data));i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempMOPY,sizeof(MOPY_Data));
|
||||||
|
if(previous_texid==999)
|
||||||
|
previous_texid=tempMOPY.textureID;//Initialize
|
||||||
|
WMOMTexData.push_back(tempMOPY);
|
||||||
|
if(previous_texid!=tempMOPY.textureID)
|
||||||
|
submeshes.push_back(i);
|
||||||
|
previous_texid=tempMOPY.textureID;
|
||||||
|
}
|
||||||
|
submeshes.push_back(WMOMTexData.size()-1);//last read entry
|
||||||
|
logdebug("Read %u/%u Texture Informations, counted %u submeshes",WMOMTexData.size(),(size/sizeof(MOPY_Data)),submeshes.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MOVI")){//Vertex indices (3 per triangle)
|
||||||
|
if(WMOMIndices.size()>0)
|
||||||
|
WMOMIndices.clear();
|
||||||
|
|
||||||
|
u16 tempWMOIndex;
|
||||||
|
for(u32 i =0;i<(size/sizeof(u16));i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempWMOIndex,sizeof(u16));
|
||||||
|
WMOMIndices.push_back(tempWMOIndex);
|
||||||
|
}
|
||||||
|
logdebug("Read %u/%u Indices",WMOMIndices.size(),(size/sizeof(u16)));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MOVT")){//Vertex coordinates
|
||||||
|
if(WMOMVertices.size()>0)
|
||||||
|
WMOMVertices.clear();
|
||||||
|
|
||||||
|
core::vector3df tempWMOVertex;
|
||||||
|
float tempYZ;
|
||||||
|
for(u32 i =0;i<(size/sizeof(core::vector3df));i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempWMOVertex,sizeof(core::vector3df));
|
||||||
|
tempYZ = tempWMOVertex.Y;
|
||||||
|
tempWMOVertex.Y=tempWMOVertex.Z;
|
||||||
|
tempWMOVertex.Z=tempYZ;
|
||||||
|
WMOMVertices.push_back(tempWMOVertex);
|
||||||
|
}
|
||||||
|
logdebug("Read %u/%u Vertex Coordinates",WMOMVertices.size(),(size/sizeof(core::vector3df)));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MONR")){//Normals
|
||||||
|
if(WMOMNormals.size()>0)
|
||||||
|
WMOMNormals.clear();
|
||||||
|
|
||||||
|
core::vector3df tempWMONormal;
|
||||||
|
float tempYZ;
|
||||||
|
for(u32 i =0;i<(size/sizeof(core::vector3df));i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempWMONormal,sizeof(core::vector3df));
|
||||||
|
tempYZ = tempWMONormal.Y;
|
||||||
|
tempWMONormal.Y=tempWMONormal.Z;
|
||||||
|
tempWMONormal.Z=tempYZ;
|
||||||
|
WMOMNormals.push_back(tempWMONormal);
|
||||||
|
}
|
||||||
|
logdebug("Read %u/%u Normal Coordinates",WMOMNormals.size(),(size/sizeof(core::vector3df)));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MOTV")){//TexCoord
|
||||||
|
if(WMOMTexcoord.size()>0)
|
||||||
|
WMOMTexcoord.clear();
|
||||||
|
|
||||||
|
core::vector2df tempWMOMTexcoord;
|
||||||
|
for(u32 i =0;i<(size/sizeof(core::vector2df));i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempWMOMTexcoord,sizeof(core::vector2df));
|
||||||
|
WMOMTexcoord.push_back(tempWMOMTexcoord);
|
||||||
|
}
|
||||||
|
logdebug("Read %u/%u Texture Coordinates",WMOMTexcoord.size(),(size/sizeof(core::vector2df)));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"MOCV")){//Vertex colors!! Scaaaary!
|
||||||
|
if(WMOMVertexColor.size()>0)
|
||||||
|
WMOMVertexColor.clear();
|
||||||
|
|
||||||
|
WMOColor tempWMOMVertexColor;
|
||||||
|
|
||||||
|
for(u32 i =0;i<(size/sizeof(WMOColor));i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempWMOMVertexColor,sizeof(WMOColor));
|
||||||
|
WMOMVertexColor.push_back(video::SColor(tempWMOMVertexColor.a,tempWMOMVertexColor.r,tempWMOMVertexColor.g,tempWMOMVertexColor.b));
|
||||||
|
}
|
||||||
|
logdebug("Read %u/%u Vertex colors",WMOMVertexColor.size(),(size/sizeof(WMOColor)));
|
||||||
|
|
||||||
|
}
|
||||||
|
//End Group file parsing
|
||||||
|
|
||||||
|
|
||||||
|
else
|
||||||
|
MeshFile->seek(size,true);//Skip Chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isRootFile)//If we just read a group file, add a mesh buffer to the main Mesh
|
||||||
|
{
|
||||||
|
if(WMOVertices.size()>0)
|
||||||
|
WMOVertices.clear();
|
||||||
|
|
||||||
|
for(u32 i=0;i<WMOMVertices.size();i++)
|
||||||
|
{
|
||||||
|
//WMOMVertices, Normals and stuff are not usable like this. Thus we build Vertices in irrlicht format
|
||||||
|
//rotation happens when reading from file, so swapping Y and Z here is no longer necessary
|
||||||
|
WMOVertices.push_back(video::S3DVertex(WMOMVertices[i],WMOMNormals[i], video::SColor(255,100,100,100),WMOMTexcoord[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 lastindex=0;
|
||||||
|
for(u32 i=0;i<submeshes.size();i++)//The mesh has to be split into submeshes because irrlicht only handles 1 texture per meshbuffer (not quite correct but i am to lazy to explain now)
|
||||||
|
{
|
||||||
|
if(WMOMTexData[lastindex].textureID!=255)
|
||||||
|
{
|
||||||
|
scene::SSkinMeshBuffer *MeshBuffer = Mesh->createBuffer();
|
||||||
|
|
||||||
|
//Put the Indices and Vertices of the Submesh into a mesh buffer
|
||||||
|
for(u32 j=lastindex;j<submeshes[i];j++)
|
||||||
|
{
|
||||||
|
if((j*3+2)<WMOMIndices.size()&&WMOMTexData[j].textureID!=255)
|
||||||
|
{
|
||||||
|
MeshBuffer->Indices.push_back(WMOMIndices[j*3]);
|
||||||
|
MeshBuffer->Indices.push_back(WMOMIndices[j*3+1]);
|
||||||
|
MeshBuffer->Indices.push_back(WMOMIndices[j*3+2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logdebug("Inserted %u Indices/n",MeshBuffer->Indices.size());
|
||||||
|
|
||||||
|
for(u32 j=0;j<WMOVertices.size();j++)
|
||||||
|
{
|
||||||
|
MeshBuffer->Vertices_Standard.push_back(WMOVertices[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
logdebug("Inserted %u Vertices/n",MeshBuffer->Vertices_Standard.size());
|
||||||
|
|
||||||
|
std::string TexName=Texdir.c_str();
|
||||||
|
TexName+="/";
|
||||||
|
TexName+=WMOMTextureFiles[WMOMTexData[lastindex].textureID].c_str();
|
||||||
|
while(TexName.find('\\')<TexName.size())//Replace \ by /
|
||||||
|
{
|
||||||
|
TexName.replace(TexName.find('\\'),1,"/");
|
||||||
|
}
|
||||||
|
while(TexName.find(' ')<TexName.size())//Replace space by _
|
||||||
|
{
|
||||||
|
TexName.replace(TexName.find(' '),1,"_");
|
||||||
|
}
|
||||||
|
std::transform(TexName.begin(), TexName.end(), TexName.begin(), tolower);
|
||||||
|
MeshBuffer->getMaterial().setTexture(0,Device->getVideoDriver()->getTexture(TexName.c_str()));
|
||||||
|
if(WMOMTexDefinition[WMOMTexData[lastindex].textureID].blendMode==1)
|
||||||
|
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
MeshBuffer->recalculateBoundingBox();
|
||||||
|
}
|
||||||
|
lastindex=submeshes[i];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WMOMIndices.clear();
|
||||||
|
WMOMVertices.clear();
|
||||||
|
WMOMNormals.clear();
|
||||||
|
WMOMTexcoord.clear();
|
||||||
|
WMOMVertexColor.clear();
|
||||||
|
|
||||||
|
WMOVertices.clear();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
132
src/Client/GUI/CWMOMeshFileLoader.h
Normal file
132
src/Client/GUI/CWMOMeshFileLoader.h
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#include "irrlicht/irrlicht.h"
|
||||||
|
#include "irrlicht/IMeshLoader.h"
|
||||||
|
#include "SSkinnedMesh.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace irr
|
||||||
|
{
|
||||||
|
namespace scene
|
||||||
|
{
|
||||||
|
|
||||||
|
struct RootHeader {
|
||||||
|
/*000h*/ u32 nTextures;
|
||||||
|
/*004h*/ u32 nGroups;
|
||||||
|
/*008h*/ u32 nPortals;
|
||||||
|
/*00Ch*/ u32 nLights;
|
||||||
|
/*010h*/ u32 nModels;
|
||||||
|
/*014h*/ u32 nDoodads;
|
||||||
|
/*018h*/ u32 nSets;
|
||||||
|
/*01Ch*/ u8 colR;
|
||||||
|
/*01Dh*/ u8 colG;
|
||||||
|
/*01Eh*/ u8 colB;
|
||||||
|
/*01Fh*/ u8 colX;
|
||||||
|
/*020h*/ u32 wmoID;
|
||||||
|
/*024h*/ float bb1[3];
|
||||||
|
/*030h*/ float bb2[3];
|
||||||
|
/*03Ch*/ u32 nullish;
|
||||||
|
};
|
||||||
|
struct WMOColor{
|
||||||
|
u8 b,g,r,a;
|
||||||
|
|
||||||
|
};
|
||||||
|
struct MOPY_Data{
|
||||||
|
u8 flags,textureID;
|
||||||
|
|
||||||
|
};
|
||||||
|
struct MOMT_Data{
|
||||||
|
/*000h*/ u32 flags1;
|
||||||
|
/*004h*/ u32 flags2;
|
||||||
|
/*008h*/ u32 blendMode;
|
||||||
|
/*00Ch*/ u32 startNameIndex;
|
||||||
|
/*010h*/ u32 color;
|
||||||
|
/*014h*/ u32 unk1;
|
||||||
|
/*018h*/ u32 endNameIndex;
|
||||||
|
/*01Ch*/ u32 frameSidnColor[3];
|
||||||
|
/*020h*/
|
||||||
|
/*024h*/
|
||||||
|
/*028h*/ u32 envNameIndex;
|
||||||
|
/*02Ch*/ float diffColor[3];
|
||||||
|
/*030h*/
|
||||||
|
/*034h*/
|
||||||
|
/*038h*/ u32 groundType;
|
||||||
|
/*03Ch*/ u32 hMaps;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CWMOMeshFileLoader : public IMeshLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Constructor
|
||||||
|
CWMOMeshFileLoader(IrrlichtDevice* device, c8* texdir);
|
||||||
|
|
||||||
|
//! destructor
|
||||||
|
virtual ~CWMOMeshFileLoader();
|
||||||
|
|
||||||
|
//! returns true if the file maybe is able to be loaded by this class
|
||||||
|
//! based on the file extension (e.g. ".cob")
|
||||||
|
virtual bool isALoadableFileExtension(const c8* fileName)const;
|
||||||
|
|
||||||
|
//! creates/loads an animated mesh from the file.
|
||||||
|
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||||
|
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||||
|
//! See IUnknown::drop() for more information.
|
||||||
|
virtual scene::IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool load(bool _root);
|
||||||
|
|
||||||
|
IrrlichtDevice* Device;
|
||||||
|
core::stringc Texdir;
|
||||||
|
io::IReadFile* MeshFile;
|
||||||
|
|
||||||
|
CSkinnedMesh* Mesh;
|
||||||
|
|
||||||
|
|
||||||
|
//Stuff from root file
|
||||||
|
RootHeader rootHeader;
|
||||||
|
core::array<MOMT_Data> WMOMTexDefinition;
|
||||||
|
core::array<std::string> WMOMTextureFiles;
|
||||||
|
|
||||||
|
|
||||||
|
//Stuff from group file
|
||||||
|
core::array<u16> WMOMIndices;
|
||||||
|
core::array<core::vector3df> WMOMVertices;
|
||||||
|
core::array<core::vector3df> WMOMNormals;
|
||||||
|
core::array<core::vector2df> WMOMTexcoord;
|
||||||
|
core::array<video::SColor> WMOMVertexColor;
|
||||||
|
core::array<MOPY_Data> WMOMTexData;
|
||||||
|
core::array<u16> submeshes;
|
||||||
|
|
||||||
|
core::array<video::S3DVertex> WMOVertices;
|
||||||
|
SSkinMeshBuffer* MeshBuffer;
|
||||||
|
/*
|
||||||
|
ModelHeader header;
|
||||||
|
core::stringc WMOMeshName;
|
||||||
|
SMesh* Mesh;
|
||||||
|
//
|
||||||
|
//Taken from the Model file, thus m2M*
|
||||||
|
core::array<ModelVertex> WMOMVertices;
|
||||||
|
core::array<ModelView> WMOMViews;
|
||||||
|
core::array<u16> WMOMIndices;
|
||||||
|
core::array<u16> WMOMTriangles;
|
||||||
|
core::array<ModelViewSubmesh> WMOMSubmeshes;
|
||||||
|
core::array<u16> WMOMTextureLookup;
|
||||||
|
core::array<TextureDefinition> WMOMTextureDef;
|
||||||
|
core::array<std::string> WMOMTextureFiles;
|
||||||
|
core::array<TextureUnit> WMOMTextureUnit;
|
||||||
|
core::array<RenderFlags> WMOMRenderFlags;
|
||||||
|
core::array<Animation> WMOMAnimations;
|
||||||
|
core::array<Bone> WMOMBones;
|
||||||
|
//Used for the Mesh, thus m2_noM_*
|
||||||
|
core::array<video::S3DVertex> WMOVertices;
|
||||||
|
core::array<u16> WMOIndices;
|
||||||
|
core::array<scene::ISkinnedMesh::SJoint> WMOJoints;
|
||||||
|
*/
|
||||||
|
|
||||||
|
};
|
||||||
|
}//namespace scene
|
||||||
|
}//namespace irr
|
||||||
@ -11,7 +11,8 @@ CM2MeshFileLoader.h MCamera.h SceneGuiStart.cpp SImage.cpp Scene
|
|||||||
CIrrKlangAudioStreamLoaderMP3.cpp CIrrKlangAudioStreamLoaderMP3.h CIrrKlangAudioStreamMP3.cpp CIrrKlangAudioStreamMP3.h\
|
CIrrKlangAudioStreamLoaderMP3.cpp CIrrKlangAudioStreamLoaderMP3.h CIrrKlangAudioStreamMP3.cpp CIrrKlangAudioStreamMP3.h\
|
||||||
ikpMP3.cpp decoder/bits.c decoder/internal.h decoder/mpaudec.c decoder/mpaudec.h decoder/mpaudectab.h decoder/mpegaudio.h\
|
ikpMP3.cpp decoder/bits.c decoder/internal.h decoder/mpaudec.c decoder/mpaudec.h decoder/mpaudectab.h decoder/mpegaudio.h\
|
||||||
irrKlangSceneNode.cpp irrKlangSceneNode.h CBoneSceneNode.cpp CBoneSceneNode.h SSkinnedMesh.cpp SSkinnedMesh.h\
|
irrKlangSceneNode.cpp irrKlangSceneNode.h CBoneSceneNode.cpp CBoneSceneNode.h SSkinnedMesh.cpp SSkinnedMesh.h\
|
||||||
CMDHMemoryReadFile.cpp CMDHMemoryReadFile.h MemoryInterface.cpp MemoryInterface.h
|
CMDHMemoryReadFile.cpp CMDHMemoryReadFile.h MemoryInterface.cpp MemoryInterface.h\
|
||||||
|
CWMOMeshFileLoader.cpp CWMOMeshFileLoader.h
|
||||||
|
|
||||||
|
|
||||||
libgui_a_LIBADD = $(top_builddir)/src/shared/libshared.a $(top_builddir)/src/shared/Auth/libauth.a $(top_builddir)/src/shared/Network/libnetwork.a
|
libgui_a_LIBADD = $(top_builddir)/src/shared/libshared.a $(top_builddir)/src/shared/Auth/libauth.a $(top_builddir)/src/shared/Network/libnetwork.a
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "irrlicht/irrlicht.h"
|
#include "irrlicht/irrlicht.h"
|
||||||
#include "CM2MeshFileLoader.h"
|
#include "CM2MeshFileLoader.h"
|
||||||
|
#include "CWMOMeshFileLoader.h"
|
||||||
#include "CImageLoaderBLP.h"
|
#include "CImageLoaderBLP.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "DrawObject.h"
|
#include "DrawObject.h"
|
||||||
@ -132,6 +133,8 @@ void PseuGUI::_Init(void)
|
|||||||
_driver->addExternalImageLoader(BLPloader);
|
_driver->addExternalImageLoader(BLPloader);
|
||||||
scene::CM2MeshFileLoader* m2loader = new scene::CM2MeshFileLoader(_device, "./data/texture");
|
scene::CM2MeshFileLoader* m2loader = new scene::CM2MeshFileLoader(_device, "./data/texture");
|
||||||
_smgr->addExternalMeshLoader(m2loader);
|
_smgr->addExternalMeshLoader(m2loader);
|
||||||
|
scene::CWMOMeshFileLoader* wmoloader = new scene::CWMOMeshFileLoader(_device, "./data/texture");
|
||||||
|
_smgr->addExternalMeshLoader(wmoloader);
|
||||||
_throttle=0;
|
_throttle=0;
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
|
||||||
|
|||||||
@ -58,6 +58,19 @@ namespace scene
|
|||||||
//! set user axis aligned bounding box
|
//! set user axis aligned bounding box
|
||||||
virtual void setBoundingBox( const core::aabbox3df& box);
|
virtual void setBoundingBox( const core::aabbox3df& box);
|
||||||
|
|
||||||
|
//! recalculates the bounding box
|
||||||
|
void recalculateBoundingBox()
|
||||||
|
{
|
||||||
|
if (LocalBuffers.size())
|
||||||
|
{
|
||||||
|
BoundingBox = LocalBuffers[0]->getBoundingBox();
|
||||||
|
for (u32 i=1; i<LocalBuffers.size(); ++i)
|
||||||
|
BoundingBox.addInternalBox(LocalBuffers[i]->getBoundingBox());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BoundingBox.reset(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
//! sets a flag of all contained materials to a new value
|
//! sets a flag of all contained materials to a new value
|
||||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
|
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
|
||||||
|
|
||||||
|
|||||||
@ -167,6 +167,7 @@ private:
|
|||||||
IGUIStaticText *debugText;
|
IGUIStaticText *debugText;
|
||||||
bool debugmode;
|
bool debugmode;
|
||||||
std::map<uint32,SceneNodeWithGridPos> _doodads;
|
std::map<uint32,SceneNodeWithGridPos> _doodads;
|
||||||
|
std::map<uint32,SceneNodeWithGridPos> _wmos;
|
||||||
std::map<uint32,SceneNodeWithGridPos> _sound_emitters;
|
std::map<uint32,SceneNodeWithGridPos> _sound_emitters;
|
||||||
scene::ISceneNode *sky;
|
scene::ISceneNode *sky;
|
||||||
scene::ISceneNode *selectedNode, *oldSelectedNode, *focusedNode, *oldFocusedNode;
|
scene::ISceneNode *selectedNode, *oldSelectedNode, *focusedNode, *oldFocusedNode;
|
||||||
|
|||||||
@ -659,6 +659,49 @@ void SceneWorld::UpdateTerrain(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// create WorldMapObjects (WMOs)
|
||||||
|
logdebug("Loading %u WMOs for tile (%u, %u)", maptile->GetWMOCount(), tile_real_x, tile_real_y);
|
||||||
|
for(uint32 i = 0; i < maptile->GetWMOCount(); i++)
|
||||||
|
{
|
||||||
|
WorldMapObject *wmo = maptile->GetWMO(i);
|
||||||
|
if(_wmos.find(wmo->uniqueid) == _wmos.end()) // only add wmos that dont exist yet
|
||||||
|
{
|
||||||
|
scene::IAnimatedMesh *mesh = smgr->getMesh(wmo->model.c_str());
|
||||||
|
if(mesh)
|
||||||
|
{
|
||||||
|
scene::IAnimatedMeshSceneNode *wmo_node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||||
|
if(wmo_node)
|
||||||
|
{
|
||||||
|
for(u32 m = 0; m < wmo_node->getMaterialCount(); m++)
|
||||||
|
{
|
||||||
|
wmo_node->getMaterial(m).setFlag(EMF_FOG_ENABLE, true);
|
||||||
|
}
|
||||||
|
wmo_node->setAutomaticCulling(EAC_BOX);
|
||||||
|
// this is causing the framerate to drop to ~1. better leave it disabled for now :/
|
||||||
|
//doodad->addShadowVolumeSceneNode();
|
||||||
|
wmo_node->setPosition(core::vector3df(-wmo->x, wmo->z, -wmo->y));
|
||||||
|
|
||||||
|
// Rotation problems
|
||||||
|
// MapTile.cpp - changed to
|
||||||
|
// d.ox = mddf.c; d.oy = mddf.b; d.oz = mddf.a;
|
||||||
|
// its nonsense to do d.oy = mddf.b-90; and rotation with -d->oy-90 = -(mddf.b-90)-90 = -mddf.b
|
||||||
|
// here:
|
||||||
|
// doodad->setRotation(core::vector3df(-d->ox,0,-d->oz)); // rotated axes looks good
|
||||||
|
// doodad->setRotation(core::vector3df(0,-d->oy,0)); // same here
|
||||||
|
//wmo_node->setRotation(core::vector3df(-wmo->ox,-wmo->oy,-wmo->oz)); // very ugly with some rotations, |ang|>360?
|
||||||
|
|
||||||
|
//wmo_node->setScale(core::vector3df(5,5,5));
|
||||||
|
|
||||||
|
// smgr->addTextSceneNode(this->device->getGUIEnvironment()->getBuiltInFont(), (irr::core::stringw(L"")+(float)d->uniqueid).c_str() , irr::video::SColor(255,255,255,255),doodad, irr::core::vector3df(0,5,0));
|
||||||
|
SceneNodeWithGridPos gp;
|
||||||
|
gp.gx = mapmgr->GetGridX() + tilex - 1;
|
||||||
|
gp.gy = mapmgr->GetGridY() + tiley - 1;
|
||||||
|
gp.scenenode = wmo_node;
|
||||||
|
_wmos[wmo->uniqueid] = gp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// create sound emitters
|
// create sound emitters
|
||||||
logdebug("Loading %u sound emitters for tile (%u, %u)", maptile->GetSoundEmitterCount(), tile_real_x, tile_real_y);
|
logdebug("Loading %u sound emitters for tile (%u, %u)", maptile->GetSoundEmitterCount(), tile_real_x, tile_real_y);
|
||||||
uint32 fieldId[10]; // SCP: file1 - file10 (index 0 not used)
|
uint32 fieldId[10]; // SCP: file1 - file10 (index 0 not used)
|
||||||
|
|||||||
@ -1338,7 +1338,7 @@ void WorldSession::_HandleCastSuccessOpcode(WorldPacket& recvPacket)
|
|||||||
{
|
{
|
||||||
Object *caster = objmgr.GetObj(casterGuid);
|
Object *caster = objmgr.GetObj(casterGuid);
|
||||||
if(caster)
|
if(caster)
|
||||||
logdetail("%s casted spell %u", caster->GetName(), spellId);
|
logdetail("%s casted spell %u", caster->GetName().c_str(), spellId);
|
||||||
else
|
else
|
||||||
logerror("Caster of spell %u (GUID "I64FMT") is unknown object!",spellId,casterGuid);
|
logerror("Caster of spell %u (GUID "I64FMT") is unknown object!",spellId,casterGuid);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,6 +98,24 @@ void MapTile::ImportFromADT(ADTFile *adt)
|
|||||||
_doodads.push_back(d);
|
_doodads.push_back(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy over wmos and do some transformations
|
||||||
|
DEBUG(logdebug("%u wmos", adt->_wmosp.size()));
|
||||||
|
for(uint32 i = 0; i < adt->_wmosp.size(); i++)
|
||||||
|
{
|
||||||
|
WorldMapObject wmo;
|
||||||
|
MODF_chunk& modf = adt->_wmosp[i];
|
||||||
|
wmo.y = -(modf.x - ZEROPOINT);
|
||||||
|
wmo.z = modf.y;
|
||||||
|
wmo.x = -(modf.z - ZEROPOINT);
|
||||||
|
wmo.ox = modf.ox;
|
||||||
|
wmo.oy = modf.oy;
|
||||||
|
wmo.oz = modf.oz;
|
||||||
|
wmo.flags = modf.flags;
|
||||||
|
wmo.uniqueid = modf.uniqueid;
|
||||||
|
wmo.model = std::string("./data/wmo/") + NormalizeFilename(_PathToFileName(adt->_wmos[modf.id]));
|
||||||
|
_wmo_data.push_back(wmo);
|
||||||
|
}
|
||||||
|
|
||||||
// copy sound emitters
|
// copy sound emitters
|
||||||
_soundemm = adt->_soundemm;
|
_soundemm = adt->_soundemm;
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,14 @@ struct Doodad
|
|||||||
std::string model;
|
std::string model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WorldMapObject
|
||||||
|
{
|
||||||
|
uint32 uniqueid;
|
||||||
|
float x,y,z,ox,oy,oz;
|
||||||
|
uint16 flags,doodadset;
|
||||||
|
std::string model;
|
||||||
|
};
|
||||||
|
|
||||||
// generic map tile class. stores the information previously stored in an ADT file
|
// generic map tile class. stores the information previously stored in an ADT file
|
||||||
// in an easier to use form.
|
// in an easier to use form.
|
||||||
class MapTile
|
class MapTile
|
||||||
@ -53,6 +61,8 @@ public:
|
|||||||
inline Doodad *GetDoodad(uint32 i) { return &_doodads[i]; }
|
inline Doodad *GetDoodad(uint32 i) { return &_doodads[i]; }
|
||||||
inline uint32 GetSoundEmitterCount(void) { return _soundemm.size(); }
|
inline uint32 GetSoundEmitterCount(void) { return _soundemm.size(); }
|
||||||
inline MCSE_chunk *GetSoundEmitter(uint32 i) { return &_soundemm[i]; }
|
inline MCSE_chunk *GetSoundEmitter(uint32 i) { return &_soundemm[i]; }
|
||||||
|
inline uint32 GetWMOCount(void) { return _wmo_data.size(); }
|
||||||
|
inline WorldMapObject *GetWMO(uint32 i) { return &_wmo_data[i]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MapChunk _chunks[256]; // 16x16
|
MapChunk _chunks[256]; // 16x16
|
||||||
@ -60,6 +70,7 @@ private:
|
|||||||
std::vector<std::string> _wmos;
|
std::vector<std::string> _wmos;
|
||||||
std::vector<std::string> _models;
|
std::vector<std::string> _models;
|
||||||
std::vector<Doodad> _doodads;
|
std::vector<Doodad> _doodads;
|
||||||
|
std::vector<WorldMapObject> _wmo_data;
|
||||||
std::vector<MCSE_chunk> _soundemm;
|
std::vector<MCSE_chunk> _soundemm;
|
||||||
|
|
||||||
float _xbase,_ybase,_hbase;
|
float _xbase,_ybase,_hbase;
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include "Locale.h"
|
#include "Locale.h"
|
||||||
#include "ProgressBar.h"
|
#include "ProgressBar.h"
|
||||||
#include "../../Client/GUI/CM2MeshFileLoader.h"
|
#include "../../Client/GUI/CM2MeshFileLoader.h"
|
||||||
|
#include "../../Client/GUI/CWMOMeshFileLoader.h"
|
||||||
|
|
||||||
int replaceSpaces (int i) { return i==(int)' ' ? (int)'_' : i; }
|
int replaceSpaces (int i) { return i==(int)' ' ? (int)'_' : i; }
|
||||||
|
|
||||||
@ -21,11 +22,12 @@ std::map<uint32,std::string> mapNames;
|
|||||||
std::set<NameAndAlt> texNames;
|
std::set<NameAndAlt> texNames;
|
||||||
std::set<NameAndAlt> modelNames;
|
std::set<NameAndAlt> modelNames;
|
||||||
std::set<NameAndAlt> wmoNames;
|
std::set<NameAndAlt> wmoNames;
|
||||||
|
std::set<NameAndAlt> wmoGroupNames;
|
||||||
std::set<NameAndAlt> soundFileSet;
|
std::set<NameAndAlt> soundFileSet;
|
||||||
|
|
||||||
|
|
||||||
// default config; SCPs are done always
|
// default config; SCPs are done always
|
||||||
bool doMaps=true, doSounds=false, doTextures=false, doWmos=false, doModels=false, doMd5=true, doAutoclose=false;
|
bool doMaps=true, doSounds=false, doTextures=false, doWmos=false, doWmogroups=false, doModels=false, doMd5=true, doAutoclose=false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ int main(int argc, char *argv[])
|
|||||||
CreateDir("stuffextract/data");
|
CreateDir("stuffextract/data");
|
||||||
ConvertDBC();
|
ConvertDBC();
|
||||||
if(doMaps) ExtractMaps();
|
if(doMaps) ExtractMaps();
|
||||||
if(doTextures || doModels || doWmos) ExtractMapDependencies();
|
if(doTextures || doModels || doWmos || doWmogroups) ExtractMapDependencies();
|
||||||
if(doSounds) ExtractSoundFiles();
|
if(doSounds) ExtractSoundFiles();
|
||||||
//...
|
//...
|
||||||
if (!doAutoclose)
|
if (!doAutoclose)
|
||||||
@ -96,6 +98,7 @@ void ProcessCmdArgs(int argc, char *argv[])
|
|||||||
if (!stricmp(what,"maps")) doMaps = on;
|
if (!stricmp(what,"maps")) doMaps = on;
|
||||||
else if(!stricmp(what,"textures")) doTextures = on;
|
else if(!stricmp(what,"textures")) doTextures = on;
|
||||||
else if(!stricmp(what,"wmos")) doWmos = on;
|
else if(!stricmp(what,"wmos")) doWmos = on;
|
||||||
|
else if(!stricmp(what,"wmogroups")) doWmogroups = on;
|
||||||
else if(!stricmp(what,"models")) doModels = on;
|
else if(!stricmp(what,"models")) doModels = on;
|
||||||
else if(!stricmp(what,"sounds")) doSounds = on;
|
else if(!stricmp(what,"sounds")) doSounds = on;
|
||||||
else if(!stricmp(what,"md5")) doMd5 = on;
|
else if(!stricmp(what,"md5")) doMd5 = on;
|
||||||
@ -125,6 +128,11 @@ void ProcessCmdArgs(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
doWmos = false;
|
doWmos = false;
|
||||||
}
|
}
|
||||||
|
if(!doWmos)
|
||||||
|
{
|
||||||
|
doWmogroups = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(help)
|
if(help)
|
||||||
{
|
{
|
||||||
PrintHelp();
|
PrintHelp();
|
||||||
@ -139,6 +147,7 @@ void PrintConfig(void)
|
|||||||
printf("config: Do maps: %s\n",doMaps?"yes":"no");
|
printf("config: Do maps: %s\n",doMaps?"yes":"no");
|
||||||
printf("config: Do textures: %s\n",doTextures?"yes":"no");
|
printf("config: Do textures: %s\n",doTextures?"yes":"no");
|
||||||
printf("config: Do wmos: %s\n",doWmos?"yes":"no");
|
printf("config: Do wmos: %s\n",doWmos?"yes":"no");
|
||||||
|
printf("config: Do wmogroups: %s\n",doWmogroups?"yes":"no");
|
||||||
printf("config: Do models: %s\n",doModels?"yes":"no");
|
printf("config: Do models: %s\n",doModels?"yes":"no");
|
||||||
printf("config: Do sounds: %s\n",doSounds?"yes":"no");
|
printf("config: Do sounds: %s\n",doSounds?"yes":"no");
|
||||||
printf("config: Calc md5: %s\n",doMd5?"yes":"no");
|
printf("config: Calc md5: %s\n",doMd5?"yes":"no");
|
||||||
@ -153,6 +162,7 @@ void PrintHelp(void)
|
|||||||
printf("maps - map extraction\n");
|
printf("maps - map extraction\n");
|
||||||
printf("textures - extract textures\n");
|
printf("textures - extract textures\n");
|
||||||
printf("wmos - extract map WMOs (requires maps extraction)\n");
|
printf("wmos - extract map WMOs (requires maps extraction)\n");
|
||||||
|
printf("wmogroups - extract map WMO group files (requires maps and wmos extraction)\n");
|
||||||
printf("models - extract models\n");
|
printf("models - extract models\n");
|
||||||
printf("sounds - extract sound files (wav/mp3)\n");
|
printf("sounds - extract sound files (wav/mp3)\n");
|
||||||
printf("md5 - write MD5 checksum lists of extracted files\n");
|
printf("md5 - write MD5 checksum lists of extracted files\n");
|
||||||
@ -515,12 +525,16 @@ bool ConvertDBC(void)
|
|||||||
if(value.size()) // only store if not null
|
if(value.size()) // only store if not null
|
||||||
{
|
{
|
||||||
// TODO: add check for wmo model files ?
|
// TODO: add check for wmo model files ?
|
||||||
if(doModels)
|
if(doModels && stricmp(value.c_str()+value.length()-4,".wmo"))
|
||||||
modelNames.insert(NameAndAlt(value)); // we need to extract model later, store it
|
modelNames.insert(NameAndAlt(value)); // we need to extract model later, store it
|
||||||
|
else
|
||||||
|
wmoNames.insert(NameAndAlt(value)); //this is a WMO
|
||||||
|
//Interestingly, some of the files referenced here have MDL extension - WTF?
|
||||||
std::string fn = _PathToFileName(value);
|
std::string fn = _PathToFileName(value);
|
||||||
if(stricmp(fn.c_str()+fn.length()-4, "mdx"))
|
if(!stricmp(fn.c_str()+fn.length()-3, "mdx") or !stricmp(fn.c_str()+fn.length()-3, "mdl"))
|
||||||
fn = fn.substr(0,fn.length()-3) + "m2";
|
fn = fn.substr(0,fn.length()-3) + "m2";
|
||||||
|
else
|
||||||
|
logdebug("This should be a WMO: %s\n",fn.c_str());
|
||||||
GameObjectDisplayInfoStorage[id].push_back(std::string(GameObjectDisplayInfoFieldNames[field]) + "=" + fn);
|
GameObjectDisplayInfoStorage[id].push_back(std::string(GameObjectDisplayInfoFieldNames[field]) + "=" + fn);
|
||||||
|
|
||||||
std::string texture = value.substr(0,value.length()-3) + "blp";
|
std::string texture = value.substr(0,value.length()-3) + "blp";
|
||||||
@ -709,12 +723,99 @@ void ExtractMapDependencies(void)
|
|||||||
std::string pathmodel = path + "/model";
|
std::string pathmodel = path + "/model";
|
||||||
std::string pathwmo = path + "/wmo";
|
std::string pathwmo = path + "/wmo";
|
||||||
std::string mpqfn,realfn,altfn;
|
std::string mpqfn,realfn,altfn;
|
||||||
MD5FileMap md5Tex, md5Wmo, md5Model;
|
MD5FileMap md5Tex, md5Wmo, md5Wmogroup, md5Model;
|
||||||
CreateDir(pathtex.c_str());
|
CreateDir(pathtex.c_str());
|
||||||
CreateDir(pathmodel.c_str());
|
CreateDir(pathmodel.c_str());
|
||||||
CreateDir(pathwmo.c_str());
|
CreateDir(pathwmo.c_str());
|
||||||
uint32 wmosdone=0,texdone=0,mdone=0;
|
uint32 wmosdone=0,texdone=0,mdone=0;
|
||||||
|
|
||||||
|
if(doWmos)
|
||||||
|
{
|
||||||
|
printf("Extracting WMOS...\n");
|
||||||
|
bar = new barGoLink(wmoNames.size(),true);
|
||||||
|
for(std::set<NameAndAlt>::iterator i = wmoNames.begin(); i != wmoNames.end(); i++)
|
||||||
|
{
|
||||||
|
bar->step();
|
||||||
|
mpqfn = i->name;
|
||||||
|
altfn = i->alt;
|
||||||
|
if(altfn.empty())
|
||||||
|
altfn = mpqfn;
|
||||||
|
if(!mpqwmo.FileExists((char*)mpqfn.c_str()))
|
||||||
|
continue;
|
||||||
|
realfn = pathwmo + "/" + _PathToFileName(altfn);
|
||||||
|
std::fstream fh;
|
||||||
|
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||||
|
if(fh.is_open())
|
||||||
|
{
|
||||||
|
const ByteBuffer& bb = mpqwmo.ExtractFile((char*)mpqfn.c_str());
|
||||||
|
fh.write((const char*)bb.contents(),bb.size());
|
||||||
|
//Extract number of group files, Texture file names and M2s from WMO
|
||||||
|
if(doWmogroups || doTextures || doModels) WMO_Parse_Data(bb,mpqfn.c_str(),doWmogroups,doTextures,doModels);
|
||||||
|
if(doMd5)
|
||||||
|
{
|
||||||
|
MD5Hash h;
|
||||||
|
h.Update((uint8*)bb.contents(), bb.size());
|
||||||
|
h.Finalize();
|
||||||
|
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||||
|
md5Wmo[_PathToFileName(realfn)] = md5ptr;
|
||||||
|
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||||
|
}
|
||||||
|
wmosdone++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("Could not write WMO %s\n",realfn.c_str());
|
||||||
|
fh.close();
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
if(wmoNames.size())
|
||||||
|
OutMD5((char*)pathwmo.c_str(),md5Wmo);
|
||||||
|
delete bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doWmogroups)
|
||||||
|
{
|
||||||
|
printf("Extracting WMO Group Files...\n");
|
||||||
|
bar = new barGoLink(wmoGroupNames.size(),true);
|
||||||
|
for(std::set<NameAndAlt>::iterator i = wmoGroupNames.begin(); i != wmoGroupNames.end(); i++)
|
||||||
|
{
|
||||||
|
bar->step();
|
||||||
|
mpqfn = i->name;
|
||||||
|
altfn = i->alt;
|
||||||
|
if(altfn.empty())
|
||||||
|
altfn = mpqfn;
|
||||||
|
if(!mpqwmo.FileExists((char*)mpqfn.c_str()))
|
||||||
|
continue;
|
||||||
|
realfn = pathwmo + "/" + _PathToFileName(altfn);
|
||||||
|
std::fstream fh;
|
||||||
|
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||||
|
if(fh.is_open())
|
||||||
|
{
|
||||||
|
const ByteBuffer& bb = mpqwmo.ExtractFile((char*)mpqfn.c_str());
|
||||||
|
fh.write((const char*)bb.contents(),bb.size());
|
||||||
|
if(doMd5)
|
||||||
|
{
|
||||||
|
MD5Hash h;
|
||||||
|
h.Update((uint8*)bb.contents(), bb.size());
|
||||||
|
h.Finalize();
|
||||||
|
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||||
|
md5Wmogroup[_PathToFileName(realfn)] = md5ptr;
|
||||||
|
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||||
|
}
|
||||||
|
wmosdone++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("Could not write WMO %s\n",realfn.c_str());
|
||||||
|
fh.close();
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
if(wmoGroupNames.size())
|
||||||
|
OutMD5((char*)pathwmo.c_str(),md5Wmogroup);
|
||||||
|
delete bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(doModels)
|
if(doModels)
|
||||||
{
|
{
|
||||||
printf("Extracting models...\n");
|
printf("Extracting models...\n");
|
||||||
@ -858,46 +959,6 @@ void ExtractMapDependencies(void)
|
|||||||
delete bar;
|
delete bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doWmos)
|
|
||||||
{
|
|
||||||
printf("Extracting WMOS...\n");
|
|
||||||
bar = new barGoLink(wmoNames.size(),true);
|
|
||||||
for(std::set<NameAndAlt>::iterator i = wmoNames.begin(); i != wmoNames.end(); i++)
|
|
||||||
{
|
|
||||||
bar->step();
|
|
||||||
mpqfn = i->name;
|
|
||||||
altfn = i->alt;
|
|
||||||
if(altfn.empty())
|
|
||||||
altfn = mpqfn;
|
|
||||||
if(!mpqwmo.FileExists((char*)mpqfn.c_str()))
|
|
||||||
continue;
|
|
||||||
realfn = pathwmo + "/" + _PathToFileName(altfn);
|
|
||||||
std::fstream fh;
|
|
||||||
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
|
||||||
if(fh.is_open())
|
|
||||||
{
|
|
||||||
const ByteBuffer& bb = mpqwmo.ExtractFile((char*)mpqfn.c_str());
|
|
||||||
fh.write((const char*)bb.contents(),bb.size());
|
|
||||||
if(doMd5)
|
|
||||||
{
|
|
||||||
MD5Hash h;
|
|
||||||
h.Update((uint8*)bb.contents(), bb.size());
|
|
||||||
h.Finalize();
|
|
||||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
|
||||||
md5Wmo[_PathToFileName(realfn)] = md5ptr;
|
|
||||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
|
||||||
}
|
|
||||||
wmosdone++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf("Could not write WMO %s\n",realfn.c_str());
|
|
||||||
fh.close();
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
if(wmoNames.size())
|
|
||||||
OutMD5((char*)pathwmo.c_str(),md5Wmo);
|
|
||||||
delete bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,6 +1012,77 @@ void ExtractSoundFiles(void)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WMO_Parse_Data(ByteBuffer bb, const char* _filename, bool groups, bool textures, bool models)
|
||||||
|
{
|
||||||
|
bb.rpos(20); //Skip MVER chunk and header of MHDR
|
||||||
|
irr::scene::RootHeader header;
|
||||||
|
if (bb.size() < sizeof(header))
|
||||||
|
return;
|
||||||
|
bb.read((uint8*)&header, sizeof(header));
|
||||||
|
if(groups)
|
||||||
|
{
|
||||||
|
std::string filename=_filename;
|
||||||
|
for(uint32 i=0; i<header.nGroups; i++)
|
||||||
|
{
|
||||||
|
char grpfilename[255];
|
||||||
|
sprintf(grpfilename,"%s_%03lu.wmo",filename.substr(0,filename.length()-4).c_str(),i);
|
||||||
|
wmoGroupNames.insert(NameAndAlt(grpfilename));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(models || textures)
|
||||||
|
{
|
||||||
|
uint32 size;
|
||||||
|
uint8 _cc[5];
|
||||||
|
uint8 *fourcc = &_cc[0];
|
||||||
|
fourcc[4]=0;
|
||||||
|
|
||||||
|
while(bb.rpos()<bb.size())
|
||||||
|
{
|
||||||
|
bb.read((uint8*)fourcc,4);
|
||||||
|
bb.read((uint8*)&size,4);
|
||||||
|
if(!strcmp((char*)fourcc,"XTOM") && textures)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
char c;
|
||||||
|
uint32 read=0;
|
||||||
|
while(read<size)
|
||||||
|
{
|
||||||
|
bb.read((uint8*)&c,sizeof(char));
|
||||||
|
if(c=='\x0' && temp.size()>0)
|
||||||
|
{
|
||||||
|
texNames.insert(NameAndAlt(temp));
|
||||||
|
temp.clear();
|
||||||
|
}
|
||||||
|
else if(c!=0)
|
||||||
|
temp += c;
|
||||||
|
read++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!strcmp((char*)fourcc,"NDOM") && models)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
char c;
|
||||||
|
uint32 read=0;
|
||||||
|
while(read<size)
|
||||||
|
{
|
||||||
|
bb.read((uint8*)&c,sizeof(char));
|
||||||
|
if(c=='\x0' && temp.size()>0)
|
||||||
|
{
|
||||||
|
modelNames.insert(NameAndAlt(temp));
|
||||||
|
temp.clear();
|
||||||
|
}
|
||||||
|
else if(c!=0)
|
||||||
|
temp += c;
|
||||||
|
read++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bb.rpos(bb.rpos()+size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
void ADT_ExportStringSetByOffset(const uint8* data, uint32 off, std::set<NameAndAlt>& st,const char* stop)
|
void ADT_ExportStringSetByOffset(const uint8* data, uint32 off, std::set<NameAndAlt>& st,const char* stop)
|
||||||
{
|
{
|
||||||
data += ((uint32*)data)[off]; // seek to correct absolute offset
|
data += ((uint32*)data)[off]; // seek to correct absolute offset
|
||||||
|
|||||||
@ -41,6 +41,8 @@ void ExtractSoundFiles(void);
|
|||||||
|
|
||||||
void FetchTexturesFromModel(ByteBuffer);
|
void FetchTexturesFromModel(ByteBuffer);
|
||||||
|
|
||||||
|
void WMO_Parse_Data(ByteBuffer, const char*, bool, bool, bool);
|
||||||
|
|
||||||
void ADT_ExportStringSetByOffset(const uint8*, uint32, std::set<NameAndAlt>&, const char*);
|
void ADT_ExportStringSetByOffset(const uint8*, uint32, std::set<NameAndAlt>&, const char*);
|
||||||
void ADT_FillTextureData(const uint8*,std::set<NameAndAlt>&);
|
void ADT_FillTextureData(const uint8*,std::set<NameAndAlt>&);
|
||||||
void ADT_FillWMOData(const uint8*,std::set<NameAndAlt>&);
|
void ADT_FillWMOData(const uint8*,std::set<NameAndAlt>&);
|
||||||
|
|||||||
@ -67,9 +67,9 @@ public:
|
|||||||
return reinterpret_cast<char*>(file.stringTable + stringOffset);
|
return reinterpret_cast<char*>(file.stringTable + stringOffset);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {}
|
|
||||||
unsigned char *offset;
|
|
||||||
DBCFile &file;
|
DBCFile &file;
|
||||||
|
unsigned char *offset;
|
||||||
|
Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {}
|
||||||
|
|
||||||
friend class DBCFile;
|
friend class DBCFile;
|
||||||
friend class DBCFile::Iterator;
|
friend class DBCFile::Iterator;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user