mirror of https://github.com/AxioDL/metaforce.git
Initial CModel implementation
This commit is contained in:
parent
2e028d9049
commit
6b1c435d0c
|
@ -281,9 +281,9 @@ bool ProjectResourceFactoryBase::SyncCook(const hecl::ProjectPath& working)
|
|||
return m_clientProc.syncCook(working, m_cookSpec.get(), hecl::SharedBlenderToken);
|
||||
}
|
||||
|
||||
CFactoryFnReturn ProjectResourceFactoryBase::SyncMakeObject(const SObjectTag& tag,
|
||||
const hecl::ProjectPath& path,
|
||||
const CVParamTransfer& paramXfer)
|
||||
CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag,
|
||||
const hecl::ProjectPath& path,
|
||||
const CVParamTransfer& paramXfer)
|
||||
{
|
||||
/* Ensure requested resource is on the filesystem */
|
||||
if (path.getPathType() != hecl::ProjectPath::Type::File)
|
||||
|
@ -319,6 +319,13 @@ CFactoryFnReturn ProjectResourceFactoryBase::SyncMakeObject(const SObjectTag& ta
|
|||
}
|
||||
|
||||
/* All good, build resource */
|
||||
if (m_factoryMgr.CanMakeMemory(tag))
|
||||
{
|
||||
u32 length = fr.length();
|
||||
std::unique_ptr<u8[]> memBuf = fr.readUBytes(length);
|
||||
return m_factoryMgr.MakeObjectFromMemory(tag, std::move(memBuf), length, false, paramXfer);
|
||||
}
|
||||
|
||||
return m_factoryMgr.MakeObject(tag, fr, paramXfer);
|
||||
}
|
||||
|
||||
|
@ -419,7 +426,7 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
|
|||
return {};
|
||||
}
|
||||
|
||||
return SyncMakeObject(tag, search->second, paramXfer);
|
||||
return BuildSync(tag, search->second, paramXfer);
|
||||
}
|
||||
|
||||
void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag,
|
||||
|
|
|
@ -82,8 +82,8 @@ protected:
|
|||
|
||||
hecl::ProjectPath GetCookedPath(const hecl::ProjectPath& working, bool pcTarget) const;
|
||||
bool SyncCook(const hecl::ProjectPath& working);
|
||||
CFactoryFnReturn SyncMakeObject(const SObjectTag& tag, const hecl::ProjectPath& path,
|
||||
const CVParamTransfer& paramXfer);
|
||||
CFactoryFnReturn BuildSync(const SObjectTag& tag, const hecl::ProjectPath& path,
|
||||
const CVParamTransfer& paramXfer);
|
||||
|
||||
public:
|
||||
ProjectResourceFactoryBase(hecl::ClientProcess& clientProc) : m_clientProc(clientProc) {}
|
||||
|
|
|
@ -28,6 +28,7 @@ ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& client
|
|||
m_factoryMgr.AddFactory(FOURCC('PART'), urde::FParticleFactory);
|
||||
m_factoryMgr.AddFactory(FOURCC('FRME'), urde::RGuiFrameFactoryInGame);
|
||||
m_factoryMgr.AddFactory(FOURCC('FONT'), urde::FRasterFontFactory);
|
||||
m_factoryMgr.AddFactory(FOURCC('CMDL'), urde::FModelFactory);
|
||||
}
|
||||
|
||||
void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj)
|
||||
|
|
|
@ -14,22 +14,53 @@ CFactoryFnReturn CFactoryMgr::MakeObject(const SObjectTag& tag, urde::CInputStre
|
|||
return search->second(tag, in, paramXfer);
|
||||
}
|
||||
|
||||
CFactoryFnReturn CFactoryMgr::MakeObjectFromMemory(const SObjectTag& tag, void* buf, int size,
|
||||
bool CFactoryMgr::CanMakeMemory(const urde::SObjectTag& tag) const
|
||||
{
|
||||
auto search = m_memFactories.find(tag.type);
|
||||
return search != m_memFactories.cend();
|
||||
}
|
||||
|
||||
CFactoryFnReturn CFactoryMgr::MakeObjectFromMemory(const SObjectTag& tag, std::unique_ptr<u8[]>&& buf, int size,
|
||||
bool compressed, const CVParamTransfer& paramXfer)
|
||||
{
|
||||
auto search = m_factories.find(tag.type);
|
||||
if (search == m_factories.end())
|
||||
return {};
|
||||
std::unique_ptr<u8[]> localBuf = std::move(buf);
|
||||
|
||||
if (compressed)
|
||||
auto search = m_memFactories.find(tag.type);
|
||||
if (search != m_memFactories.cend())
|
||||
{
|
||||
CZipInputStream r(std::make_unique<athena::io::MemoryReader>(buf, size));
|
||||
return search->second(tag, r, paramXfer);
|
||||
if (compressed)
|
||||
{
|
||||
std::unique_ptr<CInputStream> compRead =
|
||||
std::make_unique<athena::io::MemoryReader>(localBuf.get(), size);
|
||||
u32 decompLen = compRead->readUint32Big();
|
||||
CZipInputStream r(std::move(compRead));
|
||||
std::unique_ptr<u8[]> decompBuf = r.readUBytes(decompLen);
|
||||
return search->second(tag, std::move(decompBuf), decompLen, paramXfer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return search->second(tag, std::move(localBuf), size, paramXfer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CMemoryInStream r(buf, size);
|
||||
return search->second(tag, r, paramXfer);
|
||||
auto search = m_factories.find(tag.type);
|
||||
if (search == m_factories.end())
|
||||
return {};
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
std::unique_ptr<CInputStream> compRead =
|
||||
std::make_unique<athena::io::MemoryReader>(localBuf.get(), size);
|
||||
u32 decompLen = compRead->readUint32Big();
|
||||
CZipInputStream r(std::move(compRead));
|
||||
return search->second(tag, r, paramXfer);
|
||||
}
|
||||
else
|
||||
{
|
||||
CMemoryInStream r(localBuf.get(), size);
|
||||
return search->second(tag, r, paramXfer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,18 +15,27 @@ using CFactoryFnReturn = std::unique_ptr<IObj>;
|
|||
using FFactoryFunc = std::function<CFactoryFnReturn(const urde::SObjectTag& tag,
|
||||
urde::CInputStream& in,
|
||||
const urde::CVParamTransfer& vparms)>;
|
||||
using FMemFactoryFunc = std::function<CFactoryFnReturn(const urde::SObjectTag& tag,
|
||||
std::unique_ptr<u8[]>&& in, u32 len,
|
||||
const urde::CVParamTransfer& vparms)>;
|
||||
class CFactoryMgr
|
||||
{
|
||||
std::unordered_map<FourCC, FFactoryFunc> m_factories;
|
||||
std::unordered_map<FourCC, FMemFactoryFunc> m_memFactories;
|
||||
public:
|
||||
CFactoryFnReturn MakeObject(const SObjectTag& tag, urde::CInputStream& in,
|
||||
const CVParamTransfer& paramXfer);
|
||||
CFactoryFnReturn MakeObjectFromMemory(const SObjectTag& tag, void* buf, int size, bool compressed,
|
||||
bool CanMakeMemory(const urde::SObjectTag& tag) const;
|
||||
CFactoryFnReturn MakeObjectFromMemory(const SObjectTag& tag, std::unique_ptr<u8[]>&& buf, int size, bool compressed,
|
||||
const CVParamTransfer& paramXfer);
|
||||
void AddFactory(FourCC key, FFactoryFunc func)
|
||||
{
|
||||
m_factories[key] = func;
|
||||
}
|
||||
void AddFactory(FourCC key, FMemFactoryFunc func)
|
||||
{
|
||||
m_memFactories[key] = func;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,9 +3,14 @@
|
|||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "zeus/CColor.hpp"
|
||||
#include "CFactoryMgr.hpp"
|
||||
#include "CToken.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
class IObjectStore;
|
||||
class CTexture;
|
||||
|
||||
struct CModelFlags
|
||||
{
|
||||
|
@ -20,14 +25,66 @@ struct CModelFlags
|
|||
*/
|
||||
};
|
||||
|
||||
class CBooModel
|
||||
{
|
||||
public:
|
||||
struct CSurface
|
||||
{
|
||||
const u8* m_data;
|
||||
CBooModel* m_parent = nullptr;
|
||||
CSurface* m_next = nullptr;
|
||||
};
|
||||
private:
|
||||
std::vector<CSurface>* x0_surfaces;
|
||||
const u8* x4_matSet;
|
||||
const void* x8_vbo;
|
||||
const void* xc_ibo;
|
||||
std::vector<TLockedToken<CTexture>>* x1c_textures;
|
||||
zeus::CAABox x20_aabb;
|
||||
CSurface* x38_firstUnsortedSurface = nullptr;
|
||||
CSurface* x3c_firstSortedSurface = nullptr;
|
||||
bool x40_24_ : 1;
|
||||
bool x40_25_ : 1;
|
||||
u8 x41_shortNormals;
|
||||
public:
|
||||
CBooModel(std::vector<CSurface>* surfaces, std::vector<TLockedToken<CTexture>>* textures,
|
||||
const u8* matSet, const void* vbo, const void* ibo, const zeus::CAABox& aabb,
|
||||
u8 shortNormals, bool unk);
|
||||
|
||||
static void MakeTexuresFromMats(const u8* dataIn,
|
||||
std::vector<TLockedToken<CTexture>>& toksOut,
|
||||
IObjectStore& store);
|
||||
|
||||
const u8* GetMaterialByIndex(int idx) const;
|
||||
};
|
||||
|
||||
class CModel
|
||||
{
|
||||
public:
|
||||
struct SShader
|
||||
{
|
||||
std::vector<TLockedToken<CTexture>> x0_textures;
|
||||
const u8* x10_data;
|
||||
};
|
||||
private:
|
||||
std::unique_ptr<u8[]> x0_data;
|
||||
u32 x4_dataLen;
|
||||
std::vector<CBooModel::CSurface> x8_surfaces;
|
||||
std::vector<SShader> x18_matSets;
|
||||
std::unique_ptr<CBooModel> x28_modelInst;
|
||||
CModel* x30_next = nullptr;
|
||||
CModel* x34_prev = nullptr;
|
||||
public:
|
||||
CModel(std::unique_ptr<u8[]>&& in, u32 dataLen, IObjectStore* store);
|
||||
void Draw(const CModelFlags& flags) const;
|
||||
void Touch(int) const;
|
||||
bool IsLoaded(int) const;
|
||||
};
|
||||
|
||||
CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag,
|
||||
std::unique_ptr<u8[]>&& in, u32 len,
|
||||
const urde::CVParamTransfer& vparms);
|
||||
|
||||
}
|
||||
|
||||
#endif // __PSHAG_CMODEL_HPP__
|
||||
|
|
|
@ -2,6 +2,120 @@
|
|||
|
||||
namespace urde
|
||||
{
|
||||
static logvisor::Module Log("urde::CModelBoo");
|
||||
|
||||
CBooModel::CBooModel(std::vector<CSurface>* surfaces, std::vector<TLockedToken<CTexture>>* textures,
|
||||
const u8* matSet, const void* vbo, const void* ibo, const zeus::CAABox& aabb,
|
||||
u8 shortNormals, bool unk)
|
||||
: x0_surfaces(surfaces), x4_matSet(matSet), x8_vbo(vbo), xc_ibo(ibo), x1c_textures(textures),
|
||||
x20_aabb(aabb), x40_24_(unk), x40_25_(0), x41_shortNormals(shortNormals)
|
||||
{
|
||||
for (CSurface& surf : *x0_surfaces)
|
||||
surf.m_parent = this;
|
||||
|
||||
for (auto it=x0_surfaces->rbegin() ; it != x0_surfaces->rend() ; ++it)
|
||||
{
|
||||
u32 matId = hecl::SBig(*reinterpret_cast<const u32*>(it->m_data + 0xc));
|
||||
const u8* matData = GetMaterialByIndex(matId);
|
||||
u32 matFlags = hecl::SBig(*reinterpret_cast<const u32*>(matData));
|
||||
if (matFlags & 0x10)
|
||||
{
|
||||
it->m_next = x3c_firstSortedSurface;
|
||||
x3c_firstSortedSurface = &*it;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->m_next = x38_firstUnsortedSurface;
|
||||
x38_firstUnsortedSurface = &*it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBooModel::MakeTexuresFromMats(const u8* dataIn,
|
||||
std::vector<TLockedToken<CTexture>>& toksOut,
|
||||
IObjectStore& store)
|
||||
{
|
||||
u32 texCount = hecl::SBig(*reinterpret_cast<const u32*>(dataIn));
|
||||
dataIn += 4;
|
||||
toksOut.reserve(texCount);
|
||||
for (u32 i=0 ; i<texCount ; ++i)
|
||||
{
|
||||
u32 id = hecl::SBig(*reinterpret_cast<const u32*>(dataIn));
|
||||
dataIn += 4;
|
||||
toksOut.emplace_back(store.GetObj({SBIG('TXTR'), id}));
|
||||
}
|
||||
}
|
||||
|
||||
const u8* CBooModel::GetMaterialByIndex(int idx) const
|
||||
{
|
||||
const u32* matOffs = reinterpret_cast<const u32*>(x4_matSet + (x1c_textures->size() + 1) * 4);
|
||||
u32 matCount = hecl::SBig(*matOffs);
|
||||
++matOffs;
|
||||
|
||||
const u8* materialBase = reinterpret_cast<const u8*>(matOffs + matCount);
|
||||
if (idx == 0)
|
||||
return materialBase;
|
||||
|
||||
u32 offset = hecl::SBig(matOffs[idx-1]);
|
||||
return materialBase + offset;
|
||||
}
|
||||
|
||||
static const u8* MemoryFromPartData(const u8*& dataCur, const s32*& secSizeCur)
|
||||
{
|
||||
const u8* ret;
|
||||
if (*secSizeCur)
|
||||
ret = dataCur;
|
||||
else
|
||||
ret = nullptr;
|
||||
|
||||
dataCur += hecl::SBig(*secSizeCur);
|
||||
++secSizeCur;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CModel::CModel(std::unique_ptr<u8[]>&& in, u32 dataLen, IObjectStore* store)
|
||||
: x0_data(std::move(in)), x4_dataLen(dataLen)
|
||||
{
|
||||
u32 version = hecl::SBig(*reinterpret_cast<u32*>(x0_data.get() + 0x4));
|
||||
u32 flags = hecl::SBig(*reinterpret_cast<u32*>(x0_data.get() + 0x8));
|
||||
if (version != 16)
|
||||
Log.report(logvisor::Fatal, "invalid CMDL for loading with boo");
|
||||
|
||||
u32 secCount = hecl::SBig(*reinterpret_cast<u32*>(x0_data.get() + 0x24));
|
||||
u32 matSetCount = hecl::SBig(*reinterpret_cast<u32*>(x0_data.get() + 0x28));
|
||||
x18_matSets.reserve(matSetCount);
|
||||
const u8* dataCur = x0_data.get() + ROUND_UP_32(0x2c + secCount * 4);
|
||||
const s32* secSizeCur = reinterpret_cast<const s32*>(x0_data.get() + 0x2c);
|
||||
for (u32 i=0 ; i<matSetCount ; ++i)
|
||||
{
|
||||
const u8* sec = MemoryFromPartData(dataCur, secSizeCur);
|
||||
x18_matSets.emplace_back();
|
||||
SShader& shader = x18_matSets.back();
|
||||
shader.x10_data = sec;
|
||||
CBooModel::MakeTexuresFromMats(sec, shader.x0_textures, *store);
|
||||
}
|
||||
|
||||
const u8* vboData = MemoryFromPartData(dataCur, secSizeCur);
|
||||
const u8* iboData = MemoryFromPartData(dataCur, secSizeCur);
|
||||
const u8* surfInfo = MemoryFromPartData(dataCur, secSizeCur);
|
||||
|
||||
u32 surfCount = hecl::SBig(*reinterpret_cast<const u32*>(surfInfo));
|
||||
x8_surfaces.reserve(surfCount);
|
||||
for (u32 i=0 ; i<surfCount ; ++i)
|
||||
{
|
||||
const u8* sec = MemoryFromPartData(dataCur, secSizeCur);
|
||||
x8_surfaces.emplace_back();
|
||||
CBooModel::CSurface& surf = x8_surfaces.back();
|
||||
surf.m_data = sec;
|
||||
}
|
||||
|
||||
const float* aabbPtr = reinterpret_cast<const float*>(x0_data.get() + 0x18);
|
||||
zeus::CAABox aabb(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]),
|
||||
hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5]));
|
||||
x28_modelInst = std::make_unique<CBooModel>(&x8_surfaces, &x18_matSets[0].x0_textures,
|
||||
x18_matSets[0].x10_data, vboData, iboData,
|
||||
aabb, flags & 0x2, true);
|
||||
}
|
||||
|
||||
void CModel::Draw(const CModelFlags& flags) const
|
||||
{
|
||||
|
@ -16,4 +130,12 @@ bool CModel::IsLoaded(int) const
|
|||
return false;
|
||||
}
|
||||
|
||||
CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag,
|
||||
std::unique_ptr<u8[]>&& in, u32 len,
|
||||
const urde::CVParamTransfer& vparms)
|
||||
{
|
||||
IObjectStore* store = static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam();
|
||||
return TToken<CModel>::GetIObjObjectFor(std::make_unique<CModel>(std::move(in), len, store));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue