📄 modelloadermdx.cpp
字号:
//+-----------------------------------------------------------------------------
//| Included files
//+-----------------------------------------------------------------------------
#include "ModelLoaderMdx.h"
//+-----------------------------------------------------------------------------
//| Global objects
//+-----------------------------------------------------------------------------
MODEL_LOADER_MDX ModelLoaderMdx;
//+-----------------------------------------------------------------------------
//| Constructor
//+-----------------------------------------------------------------------------
MODEL_LOADER_MDX::MODEL_LOADER_MDX()
{
RegisterMdxLoader('VERS', LoadVersion);
RegisterMdxLoader('MODL', LoadModel);
RegisterMdxLoader('SEQS', LoadSequences);
RegisterMdxLoader('GLBS', LoadGlobalSequences);
RegisterMdxLoader('TEXS', LoadTextures);
RegisterMdxLoader('MTLS', LoadMaterials);
RegisterMdxLoader('TXAN', LoadTextureAnimations);
RegisterMdxLoader('GEOS', LoadGeosets);
RegisterMdxLoader('GEOA', LoadGeosetAnimations);
RegisterMdxLoader('BONE', LoadBones);
RegisterMdxLoader('LITE', LoadLights);
RegisterMdxLoader('HELP', LoadHelpers);
RegisterMdxLoader('ATCH', LoadAttachments);
RegisterMdxLoader('PIVT', LoadPivotPoints);
RegisterMdxLoader('PREM', LoadParticleEmitters);
RegisterMdxLoader('PRE2', LoadParticleEmitters2);
RegisterMdxLoader('RIBB', LoadRibbonEmitters);
RegisterMdxLoader('EVTS', LoadEventObjects);
RegisterMdxLoader('CAMS', LoadCameras);
RegisterMdxLoader('CLID', LoadCollisionShapes);
}
//+-----------------------------------------------------------------------------
//| Destructor
//+-----------------------------------------------------------------------------
MODEL_LOADER_MDX::~MODEL_LOADER_MDX()
{
MdxLoaderMap.clear();
}
//+-----------------------------------------------------------------------------
//| Saves a model to a buffer
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::Save(MODEL& Model, CONST std::string& FileName, BUFFER& Buffer)
{
DATA_OUT_STREAM DataStream;
CurrentFileName = FileName;
DataStream.SetFileName(FileName);
Model.GenerateObjectIds();
Model.WrapPivotPoints();
DataStream.WriteDWord(ReverseDWord('MDLX'));
if(!SaveVersion(Model, DataStream)) return FALSE;
if(!SaveModel(Model, DataStream)) return FALSE;
if(!SaveSequences(Model, DataStream)) return FALSE;
if(!SaveGlobalSequences(Model, DataStream)) return FALSE;
if(!SaveMaterials(Model, DataStream)) return FALSE;
if(!SaveTextures(Model, DataStream)) return FALSE;
if(!SaveTextureAnimations(Model, DataStream)) return FALSE;
if(!SaveGeosets(Model, DataStream)) return FALSE;
if(!SaveGeosetAnimations(Model, DataStream)) return FALSE;
if(!SaveBones(Model, DataStream)) return FALSE;
if(!SaveLights(Model, DataStream)) return FALSE;
if(!SaveHelpers(Model, DataStream)) return FALSE;
if(!SaveAttachments(Model, DataStream)) return FALSE;
if(!SavePivotPoints(Model, DataStream)) return FALSE;
if(!SaveParticleEmitters(Model, DataStream)) return FALSE;
if(!SaveParticleEmitters2(Model, DataStream)) return FALSE;
if(!SaveRibbonEmitters(Model, DataStream)) return FALSE;
if(!SaveCameras(Model, DataStream)) return FALSE;
if(!SaveEventObjects(Model, DataStream)) return FALSE;
if(!SaveCollisionShapes(Model, DataStream)) return FALSE;
if(!DataStream.Save(Buffer)) return FALSE;
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Loads a model from a buffer
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::Load(MODEL& Model, CONST std::string& FileName, BUFFER& Buffer)
{
INT Size;
DWORD Group;
DATA_IN_STREAM DataStream;
std::map<DWORD, MDX_LOADER>::iterator i;
CurrentFileName = FileName;
DataStream.SetFileName(FileName);
if(!DataStream.Load(Buffer)) return FALSE;
if(ReverseDWord(DataStream.ReadDWord()) != 'MDLX')
{
Error.SetMessage("The file is not an MDX model!");
return FALSE;
}
while(!DataStream.Eof())
{
Group = ReverseDWord(DataStream.ReadDWord());
Size = static_cast<INT>(DataStream.ReadDWord());
i = MdxLoaderMap.find(Group);
if(i == MdxLoaderMap.end())
{
Error.SetMessage("Unable to load \"" + FileName + "\", unknown group \"" + GroupToString(Group) + "\"!");
return FALSE;
}
if(!(i->second(Model, DataStream, Size))) return FALSE;
}
Model.ConnectNodes();
Model.UnwrapPivotPoints();
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Registers an mdx loader
//+-----------------------------------------------------------------------------
VOID MODEL_LOADER_MDX::RegisterMdxLoader(DWORD Group, MDX_LOADER Loader)
{
MdxLoaderMap.insert(std::make_pair(Group, Loader));
}
//+-----------------------------------------------------------------------------
//| Reverses a DWORD
//+-----------------------------------------------------------------------------
DWORD MODEL_LOADER_MDX::ReverseDWord(DWORD DWord)
{
DWORD NewDWord;
CHAR* Source;
CHAR* Target;
Source = reinterpret_cast<CHAR*>(&DWord);
Target = reinterpret_cast<CHAR*>(&NewDWord);
Target[0] = Source[3];
Target[1] = Source[2];
Target[2] = Source[1];
Target[3] = Source[0];
return NewDWord;
}
//+-----------------------------------------------------------------------------
//| Converts a group to a string
//+-----------------------------------------------------------------------------
std::string MODEL_LOADER_MDX::GroupToString(DWORD Group)
{
CHAR Buffer[5];
CHAR* Pointer;
Pointer = reinterpret_cast<CHAR*>(&Group);
Buffer[0] = Pointer[3];
Buffer[1] = Pointer[2];
Buffer[2] = Pointer[1];
Buffer[3] = Pointer[0];
Buffer[4] = '\0';
return Buffer;
}
//+-----------------------------------------------------------------------------
//| Saves the model version
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveVersion(MODEL& Model, DATA_OUT_STREAM& DataStream)
{
DataStream.WriteDWord(ReverseDWord('VERS'));
DataStream.WriteDWord(4);
DataStream.WriteDWord(Model.Data().Info.Version);
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves the model info
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveModel(MODEL& Model, DATA_OUT_STREAM& DataStream)
{
DataStream.WriteDWord(ReverseDWord('MODL'));
DataStream.WriteDWord(MODEL_NAME_SIZE + 36);
DataStream.WriteString(Model.Data().Info.Name, MODEL_NAME_SIZE);
DataStream.WriteDWord(0); //What is this? (always 0?)
DataStream.WriteFloat(Model.Data().Info.Extent.Radius);
DataStream.WriteFloat(Model.Data().Info.Extent.Min.x);
DataStream.WriteFloat(Model.Data().Info.Extent.Min.y);
DataStream.WriteFloat(Model.Data().Info.Extent.Min.z);
DataStream.WriteFloat(Model.Data().Info.Extent.Max.x);
DataStream.WriteFloat(Model.Data().Info.Extent.Max.y);
DataStream.WriteFloat(Model.Data().Info.Extent.Max.z);
DataStream.WriteDWord(Model.Data().Info.BlendTime);
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves the model sequences
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveSequences(MODEL& Model, DATA_OUT_STREAM& DataStream)
{
INT i;
INT TotalSize = 0;
if(Model.Data().SequenceContainer.GetSize() <= 0) return TRUE;
for(i = 0; i < Model.Data().SequenceContainer.GetTotalSize(); i++)
{
if(Model.Data().SequenceContainer.ValidIndex(i))
{
TotalSize += Model.Data().SequenceContainer[i]->GetSize();
}
}
DataStream.WriteDWord(ReverseDWord('SEQS'));
DataStream.WriteDWord(TotalSize);
for(i = 0; i < Model.Data().SequenceContainer.GetTotalSize(); i++)
{
if(Model.Data().SequenceContainer.ValidIndex(i))
{
if(!SaveSequence(*(Model.Data().SequenceContainer[i]), DataStream)) return FALSE;
}
}
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves a model sequence
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveSequence(MODEL_SEQUENCE& Sequence, DATA_OUT_STREAM& DataStream)
{
DataStream.WriteString(Sequence.Data().Name, MODEL_NAME_SEQUENCE_SIZE);
DataStream.WriteDWord(static_cast<DWORD>(Sequence.Data().Interval.x));
DataStream.WriteDWord(static_cast<DWORD>(Sequence.Data().Interval.y));
DataStream.WriteFloat(Sequence.Data().MoveSpeed);
DataStream.WriteDWord(Sequence.Data().NonLooping ? 1 : 0);
DataStream.WriteFloat(Sequence.Data().Rarity);
DataStream.WriteDWord(0); //What is this?
DataStream.WriteFloat(Sequence.Data().Extent.Radius);
DataStream.WriteFloat(Sequence.Data().Extent.Min.x);
DataStream.WriteFloat(Sequence.Data().Extent.Min.y);
DataStream.WriteFloat(Sequence.Data().Extent.Min.z);
DataStream.WriteFloat(Sequence.Data().Extent.Max.x);
DataStream.WriteFloat(Sequence.Data().Extent.Max.y);
DataStream.WriteFloat(Sequence.Data().Extent.Max.z);
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves the global model sequences
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveGlobalSequences(MODEL& Model, DATA_OUT_STREAM& DataStream)
{
INT i;
INT TotalSize = 0;
if(Model.Data().GlobalSequenceContainer.GetSize() <= 0) return TRUE;
for(i = 0; i < Model.Data().GlobalSequenceContainer.GetTotalSize(); i++)
{
if(Model.Data().GlobalSequenceContainer.ValidIndex(i))
{
TotalSize += Model.Data().GlobalSequenceContainer[i]->GetSize();
}
}
DataStream.WriteDWord(ReverseDWord('GLBS'));
DataStream.WriteDWord(TotalSize);
for(i = 0; i < Model.Data().GlobalSequenceContainer.GetTotalSize(); i++)
{
if(Model.Data().GlobalSequenceContainer.ValidIndex(i))
{
DataStream.WriteDWord(Model.Data().GlobalSequenceContainer[i]->Data().Duration);
}
}
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves the model textures
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveTextures(MODEL& Model, DATA_OUT_STREAM& DataStream)
{
INT i;
INT TotalSize = 0;
if(Model.Data().TextureContainer.GetSize() <= 0) return TRUE;
for(i = 0; i < Model.Data().TextureContainer.GetTotalSize(); i++)
{
if(Model.Data().TextureContainer.ValidIndex(i))
{
TotalSize += Model.Data().TextureContainer[i]->GetSize();
}
}
DataStream.WriteDWord(ReverseDWord('TEXS'));
DataStream.WriteDWord(TotalSize);
for(i = 0; i < Model.Data().TextureContainer.GetTotalSize(); i++)
{
if(Model.Data().TextureContainer.ValidIndex(i))
{
if(!SaveTexture(*(Model.Data().TextureContainer[i]), DataStream)) return FALSE;
}
}
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves a model texture
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveTexture(MODEL_TEXTURE& Texture, DATA_OUT_STREAM& DataStream)
{
DWORD Flags;
DataStream.WriteDWord((Texture.Data().ReplaceableId == INVALID_INDEX) ? 0 : Texture.Data().ReplaceableId);
DataStream.WriteString(Texture.Data().FileName, MODEL_NAME_TEXTURE_SIZE);
DataStream.WriteDWord(0); //What is this? (always 0?)
Flags = 0;
if(Texture.Data().WrapWidth) Flags |= 1;
if(Texture.Data().WrapHeight) Flags |= 2;
DataStream.WriteDWord(Flags);
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves the model materials
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveMaterials(MODEL& Model, DATA_OUT_STREAM& DataStream)
{
INT i;
INT TotalSize = 0;
if(Model.Data().MaterialContainer.GetSize() <= 0) return TRUE;
for(i = 0; i < Model.Data().MaterialContainer.GetTotalSize(); i++)
{
if(Model.Data().MaterialContainer.ValidIndex(i))
{
TotalSize += Model.Data().MaterialContainer[i]->GetSize();
}
}
DataStream.WriteDWord(ReverseDWord('MTLS'));
DataStream.WriteDWord(TotalSize);
for(i = 0; i < Model.Data().MaterialContainer.GetTotalSize(); i++)
{
if(Model.Data().MaterialContainer.ValidIndex(i))
{
if(!SaveMaterial(*(Model.Data().MaterialContainer[i]), DataStream)) return FALSE;
}
}
return TRUE;
}
//+-----------------------------------------------------------------------------
//| Saves a model material
//+-----------------------------------------------------------------------------
BOOL MODEL_LOADER_MDX::SaveMaterial(MODEL_MATERIAL& Material, DATA_OUT_STREAM& DataStream)
{
INT i;
DWORD Flags;
DWORD Temp;
MODEL_MATERIAL_LAYER* Layer;
DataStream.WriteDWord(Material.GetSize());
Flags = 0;
if(Material.Data().ConstantColor) Flags |= 1;
if(Material.Data().SortPrimitivesFarZ) Flags |= 16;
if(Material.Data().FullResolution) Flags |= 32;
DataStream.WriteDWord(Material.Data().PriorityPlane);
DataStream.WriteDWord(Flags);
DataStream.WriteDWord(ReverseDWord('LAYS'));
DataStream.WriteDWord(Material.Data().LayerContainer.GetSize());
for(i = 0; i < Material.Data().LayerContainer.GetTotalSize(); i++)
{
if(Material.Data().LayerContainer.ValidIndex(i))
{
Layer = Material.Data().LayerContainer[i];
DataStream.WriteDWord(Layer->GetSize());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -