mirror of https://github.com/AxioDL/metaforce.git
AROTBuilder and initial collision mesh cook integration
This commit is contained in:
parent
4519e3abf2
commit
6789cdf064
|
@ -0,0 +1,231 @@
|
|||
#include "AROTBuilder.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
||||
static const uint32_t AROTChildCounts[] = { 0, 2, 2, 4, 2, 4, 4, 8 };
|
||||
|
||||
size_t AROTBuilder::BitmapPool::addIndices(const std::set<int>& indices)
|
||||
{
|
||||
for (size_t i=0 ; i<m_pool.size() ; ++i)
|
||||
if (m_pool[i] == indices)
|
||||
return i;
|
||||
m_pool.push_back(indices);
|
||||
return m_pool.size() - 1;
|
||||
}
|
||||
|
||||
bool AROTBuilder::Node::addChild(const zeus::CAABox& curAabb, const zeus::CAABox& childAabb, int idx)
|
||||
{
|
||||
if (childAabb.intersects(curAabb))
|
||||
{
|
||||
childIndices.insert(idx);
|
||||
if (!curAabb.inside(childAabb))
|
||||
{
|
||||
childNodes.resize(8);
|
||||
zeus::CAABox X[2];
|
||||
curAabb.splitX(X[0], X[1]);
|
||||
bool inX[2] = {};
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
{
|
||||
zeus::CAABox Y[2];
|
||||
X[i].splitY(Y[0], Y[1]);
|
||||
bool inY[2] = {};
|
||||
for (int j=0 ; j<2 ; ++j)
|
||||
{
|
||||
zeus::CAABox Z[2];
|
||||
Y[j].splitZ(Z[0], Z[1]);
|
||||
bool inZ[2] = {};
|
||||
inZ[0] = childNodes[i*4 + j*2].addChild(Z[0], childAabb, idx);
|
||||
inZ[1] = childNodes[i*4 + j*2 + 1].addChild(Z[1], childAabb, idx);
|
||||
if (inZ[0] ^ inZ[1])
|
||||
flags |= 0x4;
|
||||
if (inZ[0] | inZ[1])
|
||||
inY[j] = true;
|
||||
}
|
||||
if (inY[0] ^ inY[1])
|
||||
flags |= 0x2;
|
||||
if (inY[0] | inY[1])
|
||||
inX[i] = true;
|
||||
}
|
||||
if (inX[0] ^ inX[1])
|
||||
flags |= 0x1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff)
|
||||
{
|
||||
if (childIndices.size())
|
||||
{
|
||||
sz += 1;
|
||||
poolIdx = bmpPool.addIndices(childIndices);
|
||||
if (childNodes.size())
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((flags & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((flags & 0x4) != 0) ; ++k)
|
||||
{
|
||||
childNodes[i*4 + j*2 + k].nodeCount(sz, idxRefs, bmpPool, curOff);
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t childCount = AROTChildCounts[flags];
|
||||
nodeOff = curOff;
|
||||
nodeSz += childCount * 2;
|
||||
curOff += nodeSz;
|
||||
idxRefs += childCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::writeIndirectionTable(athena::io::MemoryWriter& w)
|
||||
{
|
||||
if (childIndices.size())
|
||||
{
|
||||
w.writeUint32Big(nodeOff);
|
||||
if (childNodes.size())
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((flags & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((flags & 0x4) != 0) ; ++k)
|
||||
{
|
||||
childNodes[i*4 + j*2 + k].writeIndirectionTable(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx)
|
||||
{
|
||||
if (childIndices.size())
|
||||
{
|
||||
w.writeUint16Big(poolIdx);
|
||||
w.writeUint16Big(flags);
|
||||
if (childNodes.size())
|
||||
{
|
||||
int curIdx = nodeIdx + 1;
|
||||
int childIndices[8];
|
||||
|
||||
for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((flags & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((flags & 0x4) != 0) ; ++k)
|
||||
{
|
||||
int ch = i*4 + j*2 + k;
|
||||
w.writeUint16Big(curIdx);
|
||||
childIndices[ch] = curIdx;
|
||||
childNodes[ch].advanceIndex(curIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((flags & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((flags & 0x4) != 0) ; ++k)
|
||||
{
|
||||
int ch = i*4 + j*2 + k;
|
||||
childNodes[ch].writeNodes(w, childIndices[ch]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::advanceIndex(int& nodeIdx)
|
||||
{
|
||||
if (childIndices.size())
|
||||
{
|
||||
++nodeIdx;
|
||||
if (childNodes.size())
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((flags & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((flags & 0x4) != 0) ; ++k)
|
||||
{
|
||||
childNodes[i*4 + j*2 + k].advanceIndex(nodeIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAABox& fullAabb,
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes)
|
||||
{
|
||||
for (int i=0 ; i<meshAabbs.size() ; ++i)
|
||||
{
|
||||
const zeus::CAABox& aabb = meshAabbs[i];
|
||||
rootNode.addChild(fullAabb, aabb, i);
|
||||
}
|
||||
|
||||
size_t totalNodeCount = 0;
|
||||
size_t idxRefCount = 0;
|
||||
size_t curOff = 0;
|
||||
rootNode.nodeCount(totalNodeCount, idxRefCount, bmpPool, curOff);
|
||||
size_t bmpWordCount = ROUND_UP_32(meshes.size()) / 32;
|
||||
size_t arotSz = 64 + bmpWordCount * bmpPool.m_pool.size() * 4 + totalNodeCount * 8 + idxRefCount * 2;
|
||||
|
||||
secs.emplace_back(arotSz, 0);
|
||||
athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
|
||||
w.writeUint32Big('AROT');
|
||||
w.writeUint32Big(1);
|
||||
w.writeUint32Big(bmpPool.m_pool.size());
|
||||
w.writeUint32Big(meshes.size());
|
||||
w.writeUint32Big(totalNodeCount);
|
||||
w.writeVec3fBig(fullAabb.min);
|
||||
w.writeVec3fBig(fullAabb.max);
|
||||
w.seekAlign32();
|
||||
|
||||
std::vector<uint32_t> bmpWords;
|
||||
bmpWords.reserve(bmpWordCount);
|
||||
for (const std::set<int>& bmp : bmpPool.m_pool)
|
||||
{
|
||||
bmpWords.clear();
|
||||
bmpWords.resize(bmpWordCount);
|
||||
|
||||
auto bmpIt = bmp.cbegin();
|
||||
if (bmpIt != bmp.cend())
|
||||
{
|
||||
int curIdx = 0;
|
||||
for (int w=0 ; w<bmpWordCount ; ++w)
|
||||
{
|
||||
for (int b=0 ; b<32 ; ++b)
|
||||
{
|
||||
if (*bmpIt == curIdx)
|
||||
{
|
||||
bmpWords[w] |= 1 << b;
|
||||
++bmpIt;
|
||||
if (bmpIt == bmp.cend())
|
||||
break;
|
||||
}
|
||||
++curIdx;
|
||||
}
|
||||
if (bmpIt == bmp.cend())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t word : bmpWords)
|
||||
w.writeUint32Big(word);
|
||||
}
|
||||
|
||||
rootNode.writeIndirectionTable(w);
|
||||
rootNode.writeNodes(w, 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _DNACOMMON_AROTBUILDER_HPP_
|
||||
#define _DNACOMMON_AROTBUILDER_HPP_
|
||||
|
||||
#include "DNACommon.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
#include "CMDL.hpp"
|
||||
#include <set>
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
||||
struct AROTBuilder
|
||||
{
|
||||
struct BitmapPool
|
||||
{
|
||||
std::vector<std::set<int>> m_pool;
|
||||
size_t addIndices(const std::set<int>& indices);
|
||||
} bmpPool;
|
||||
|
||||
struct Node
|
||||
{
|
||||
std::vector<Node> childNodes;
|
||||
std::set<int> childIndices;
|
||||
size_t poolIdx = 0;
|
||||
uint8_t flags = 0;
|
||||
|
||||
size_t nodeOff = 0;
|
||||
size_t nodeSz = 4;
|
||||
|
||||
bool addChild(const zeus::CAABox& curAabb, const zeus::CAABox& childAabb, int idx);
|
||||
void nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff);
|
||||
void writeIndirectionTable(athena::io::MemoryWriter& w);
|
||||
void writeNodes(athena::io::MemoryWriter& w, int nodeIdx);
|
||||
void advanceIndex(int& nodeIdx);
|
||||
} rootNode;
|
||||
|
||||
void build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAABox& fullAabb,
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _DNACOMMON_AROTBUILDER_HPP_
|
|
@ -6,6 +6,7 @@
|
|||
#include "../DNAMP2/CSKR.hpp"
|
||||
#include "../DNAMP3/CMDLMaterials.hpp"
|
||||
#include "../DNAMP3/CSKR.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
@ -1525,7 +1526,7 @@ bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& in
|
|||
}
|
||||
}
|
||||
|
||||
hecl::HMDLBuffers bufs = mesh.getHMDLBuffers();
|
||||
hecl::HMDLBuffers bufs = mesh.getHMDLBuffers(false);
|
||||
|
||||
/* Metadata */
|
||||
size_t secSz = bufs.m_meta.binarySize(0);
|
||||
|
@ -1636,14 +1637,14 @@ template bool WriteHMDLCMDL<DNAMP1::HMDLMaterialSet, DNACMDL::SurfaceHeader_2, 2
|
|||
|
||||
template <class MaterialSet, class SurfaceHeader, class MeshHeader>
|
||||
bool WriteMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::ProjectPath& inPath,
|
||||
const std::vector<Mesh>& meshes)
|
||||
const std::vector<Mesh>& meshes, zeus::CAABox& fullAABB, std::vector<zeus::CAABox>& meshAABBs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class MaterialSet, class SurfaceHeader, class MeshHeader>
|
||||
bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::ProjectPath& inPath,
|
||||
const std::vector<Mesh>& meshes)
|
||||
const std::vector<Mesh>& meshes, zeus::CAABox& fullAABB, std::vector<zeus::CAABox>& meshAABBs)
|
||||
{
|
||||
/* Build material set */
|
||||
{
|
||||
|
@ -1690,11 +1691,91 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::P
|
|||
/* Iterate meshes */
|
||||
for (const Mesh& mesh : meshes)
|
||||
{
|
||||
MeshHeader meshHeader = {};
|
||||
meshHeader.visorFlags.setFromBlenderProps(mesh.customProps);
|
||||
memmove(meshHeader.xfMtx, &mesh.sceneXf, 48);
|
||||
memmove(&meshHeader.aabb[0], &mesh.aabbMin, 12);
|
||||
memmove(&meshHeader.aabb[1], &mesh.aabbMax, 12);
|
||||
zeus::CTransform meshXf(mesh.sceneXf.val);
|
||||
meshXf.basis.transpose();
|
||||
|
||||
/* Header */
|
||||
{
|
||||
MeshHeader meshHeader = {};
|
||||
meshHeader.visorFlags.setFromBlenderProps(mesh.customProps);
|
||||
memmove(meshHeader.xfMtx, &mesh.sceneXf, 48);
|
||||
|
||||
zeus::CAABox aabb(zeus::CVector3f(mesh.aabbMin), zeus::CVector3f(mesh.aabbMax));
|
||||
aabb = aabb.getTransformedAABox(meshXf);
|
||||
meshAABBs.push_back(aabb);
|
||||
fullAABB.accumulateBounds(aabb);
|
||||
meshHeader.aabb[0] = aabb.min;
|
||||
meshHeader.aabb[1] = aabb.max;
|
||||
|
||||
secsOut.emplace_back(meshHeader.binarySize(0), 0);
|
||||
athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size());
|
||||
meshHeader.write(w);
|
||||
}
|
||||
|
||||
hecl::HMDLBuffers bufs = mesh.getHMDLBuffers(true);
|
||||
|
||||
std::vector<size_t> surfEndOffs;
|
||||
surfEndOffs.reserve(bufs.m_surfaces.size());
|
||||
size_t endOff = 0;
|
||||
for (const hecl::HMDLBuffers::Surface& surf : bufs.m_surfaces)
|
||||
{
|
||||
endOff += 96;
|
||||
surfEndOffs.push_back(endOff);
|
||||
}
|
||||
|
||||
/* Metadata */
|
||||
{
|
||||
secsOut.emplace_back(bufs.m_meta.binarySize(0), 0);
|
||||
athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size());
|
||||
bufs.m_meta.write(w);
|
||||
}
|
||||
|
||||
/* VBO */
|
||||
{
|
||||
secsOut.emplace_back(bufs.m_vboSz, 0);
|
||||
athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size());
|
||||
w.writeUBytes(bufs.m_vboData.get(), bufs.m_vboSz);
|
||||
}
|
||||
|
||||
/* IBO */
|
||||
{
|
||||
secsOut.emplace_back(bufs.m_iboSz, 0);
|
||||
athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size());
|
||||
w.writeUBytes(bufs.m_iboData.get(), bufs.m_iboSz);
|
||||
}
|
||||
|
||||
/* Surface index */
|
||||
{
|
||||
secsOut.emplace_back((surfEndOffs.size() + 1) * 4, 0);
|
||||
athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size());
|
||||
w.writeUint32Big(surfEndOffs.size());
|
||||
for (size_t off : surfEndOffs)
|
||||
w.writeUint32Big(off);
|
||||
}
|
||||
|
||||
/* Surfaces */
|
||||
for (const hecl::HMDLBuffers::Surface& surf : bufs.m_surfaces)
|
||||
{
|
||||
const Mesh::Surface& osurf = surf.m_origSurf;
|
||||
|
||||
SurfaceHeader header;
|
||||
header.centroid = meshXf * zeus::CVector3f(osurf.centroid);
|
||||
header.matIdx = osurf.materialIdx;
|
||||
header.reflectionNormal = (meshXf.basis * zeus::CVector3f(osurf.reflectionNormal)).normalized();
|
||||
header.idxStart = surf.m_start;
|
||||
header.idxCount = surf.m_count;
|
||||
header.skinMtxBankIdx = osurf.skinBankIdx;
|
||||
|
||||
header.aabbSz = 24;
|
||||
zeus::CAABox aabb(zeus::CVector3f(surf.m_origSurf.aabbMin), zeus::CVector3f(surf.m_origSurf.aabbMax));
|
||||
aabb = aabb.getTransformedAABox(meshXf);
|
||||
header.aabb[0] = aabb.min;
|
||||
header.aabb[1] = aabb.max;
|
||||
|
||||
secsOut.emplace_back(header.binarySize(0), 0);
|
||||
athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size());
|
||||
header.write(w);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1702,7 +1783,7 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::P
|
|||
|
||||
template bool WriteHMDLMREASecs<DNAMP1::HMDLMaterialSet, DNACMDL::SurfaceHeader_2, DNAMP1::MREA::MeshHeader>
|
||||
(std::vector<std::vector<uint8_t>>& secsOut, const hecl::ProjectPath& inPath,
|
||||
const std::vector<Mesh>& meshes);
|
||||
const std::vector<Mesh>& meshes, zeus::CAABox& fullAABB, std::vector<zeus::CAABox>& meshAABBs);
|
||||
|
||||
void SurfaceHeader_1::read(athena::io::IStreamReader& reader)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "BlenderConnection.hpp"
|
||||
#include "GX.hpp"
|
||||
#include "TXTR.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
@ -171,11 +172,11 @@ bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& in
|
|||
|
||||
template <class MaterialSet, class SurfaceHeader, class MeshHeader>
|
||||
bool WriteMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::ProjectPath& inPath,
|
||||
const std::vector<Mesh>& meshes);
|
||||
const std::vector<Mesh>& meshes, zeus::CAABox& fullAABB, std::vector<zeus::CAABox>& meshAABBs);
|
||||
|
||||
template <class MaterialSet, class SurfaceHeader, class MeshHeader>
|
||||
bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::ProjectPath& inPath,
|
||||
const std::vector<Mesh>& meshes);
|
||||
const std::vector<Mesh>& meshes, zeus::CAABox& fullAABB, std::vector<zeus::CAABox>& meshAABBs);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,9 @@ add_library(DNACommon
|
|||
FONT.hpp FONT.cpp
|
||||
DGRP.hpp DGRP.cpp
|
||||
DeafBabe.hpp
|
||||
BabeDead.hpp
|
||||
BabeDead.hpp
|
||||
RigInverter.hpp RigInverter.cpp
|
||||
AROTBuilder.hpp AROTBuilder.cpp
|
||||
Tweaks/ITweakGame.hpp
|
||||
Tweaks/ITweakParticle.hpp
|
||||
Tweaks/ITweakPlayer.hpp
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "DeafBabe.hpp"
|
||||
#include "../DNACommon/BabeDead.hpp"
|
||||
#include "zeus/Math.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
#include "DataSpec/DNACommon/AROTBuilder.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
@ -246,14 +248,16 @@ void MREA::MeshHeader::VisorFlags::setFromBlenderProps(const std::unordered_map<
|
|||
|
||||
bool MREA::Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const std::vector<DNACMDL::Mesh>& meshes)
|
||||
const std::vector<DNACMDL::Mesh>& meshes,
|
||||
const ColMesh& cMesh)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const std::vector<DNACMDL::Mesh>& meshes)
|
||||
const std::vector<DNACMDL::Mesh>& meshes,
|
||||
const ColMesh& cMesh)
|
||||
{
|
||||
/* Discover area layers */
|
||||
hecl::ProjectPath areaDirPath = inPath.getParentPath();
|
||||
|
@ -270,7 +274,7 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||
}
|
||||
}
|
||||
|
||||
size_t secCount = 1 + meshes.size() * 4; /* (materials, 4 fixed model secs) */
|
||||
size_t secCount = 1 + meshes.size() * 5; /* (materials, 5 fixed model secs) */
|
||||
|
||||
/* tally up surfaces */
|
||||
for (const DNACMDL::Mesh& mesh : meshes)
|
||||
|
@ -298,8 +302,8 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||
secs.reserve(secCount + 2);
|
||||
|
||||
/* Header section */
|
||||
secs.emplace_back(head.binarySize(0), 0);
|
||||
{
|
||||
secs.emplace_back(head.binarySize(0), 0);
|
||||
athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
|
||||
head.write(w);
|
||||
int i = w.position();
|
||||
|
@ -312,37 +316,59 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||
secs.emplace_back();
|
||||
std::vector<uint8_t>& sizesSec = secs.back();
|
||||
|
||||
/* Pre-emptively build full AABB and mesh AABBs in world coords */
|
||||
zeus::CAABox fullAabb;
|
||||
std::vector<zeus::CAABox> meshAabbs;
|
||||
meshAabbs.reserve(meshes.size());
|
||||
|
||||
/* Models */
|
||||
if (!DNACMDL::WriteHMDLMREASecs<HMDLMaterialSet, DNACMDL::SurfaceHeader_2, MeshHeader>(secs, inPath, meshes))
|
||||
if (!DNACMDL::WriteHMDLMREASecs<HMDLMaterialSet, DNACMDL::SurfaceHeader_2, MeshHeader>
|
||||
(secs, inPath, meshes, fullAabb, meshAabbs))
|
||||
return false;
|
||||
|
||||
/* AROT */
|
||||
{
|
||||
AROTBuilder builder;
|
||||
builder.build(secs, fullAabb, meshAabbs, meshes);
|
||||
}
|
||||
|
||||
/* SCLY */
|
||||
for (const hecl::ProjectPath& layer : layerScriptPaths)
|
||||
{
|
||||
FILE* yamlFile = hecl::Fopen(layer.getAbsolutePath().c_str(), _S("r"));
|
||||
if (!yamlFile)
|
||||
DNAMP1::SCLY sclyData;
|
||||
sclyData.fourCC = FOURCC('SCLY');
|
||||
sclyData.version = 1;
|
||||
for (const hecl::ProjectPath& layer : layerScriptPaths)
|
||||
{
|
||||
Log.report(logvisor::Fatal, _S("unable to open %s for reading"), layer.getAbsolutePath().c_str());
|
||||
return false;
|
||||
}
|
||||
FILE* yamlFile = hecl::Fopen(layer.getAbsolutePath().c_str(), _S("r"));
|
||||
if (!yamlFile)
|
||||
continue;
|
||||
if (!BigYAML::ValidateFromYAMLFile<DNAMP1::SCLY>(yamlFile))
|
||||
{
|
||||
fclose(yamlFile);
|
||||
continue;
|
||||
}
|
||||
|
||||
athena::io::YAMLDocReader reader;
|
||||
yaml_parser_set_input_file(reader.getParser(), yamlFile);
|
||||
if (!reader.parse())
|
||||
{
|
||||
Log.report(logvisor::Fatal, _S("unable to parse %s"), layer.getAbsolutePath().c_str());
|
||||
athena::io::YAMLDocReader reader;
|
||||
yaml_parser_set_input_file(reader.getParser(), yamlFile);
|
||||
if (!reader.parse())
|
||||
{
|
||||
fclose(yamlFile);
|
||||
continue;
|
||||
}
|
||||
fclose(yamlFile);
|
||||
return false;
|
||||
}
|
||||
fclose(yamlFile);
|
||||
|
||||
std::string classStr = reader.readString("DNAType");
|
||||
if (classStr.empty())
|
||||
return false;
|
||||
sclyData.layers.emplace_back();
|
||||
sclyData.layers.back().read(reader);
|
||||
sclyData.layerSizes.push_back(sclyData.layers.back().binarySize(0));
|
||||
}
|
||||
sclyData.layerCount = sclyData.layers.size();
|
||||
|
||||
secs.emplace_back(sclyData.binarySize(0), 0);
|
||||
athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
|
||||
sclyData.write(w);
|
||||
}
|
||||
|
||||
|
||||
/* Collision */
|
||||
|
||||
|
||||
|
|
|
@ -122,13 +122,17 @@ struct MREA
|
|||
PAKRouter<PAKBridge>& pakRouter,
|
||||
PAK::Entry& entry);
|
||||
|
||||
using ColMesh = hecl::BlenderConnection::DataStream::ColMesh;
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const std::vector<DNACMDL::Mesh>& meshes);
|
||||
const std::vector<DNACMDL::Mesh>& meshes,
|
||||
const ColMesh& cMesh);
|
||||
|
||||
static bool PCCook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const std::vector<DNACMDL::Mesh>& meshes);
|
||||
const std::vector<DNACMDL::Mesh>& meshes,
|
||||
const ColMesh& cMesh);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ struct SpecBase : hecl::Database::IDataSpec
|
|||
/* Cook handlers */
|
||||
using BlendStream = hecl::BlenderConnection::DataStream;
|
||||
using Mesh = BlendStream::Mesh;
|
||||
using ColMesh = BlendStream::ColMesh;
|
||||
using Actor = BlendStream::Actor;
|
||||
|
||||
virtual void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
||||
|
|
|
@ -389,20 +389,31 @@ struct SpecMP1 : SpecBase
|
|||
std::vector<Mesh> meshCompiles;
|
||||
meshCompiles.reserve(meshes.size());
|
||||
|
||||
std::experimental::optional<ColMesh> colMesh;
|
||||
|
||||
for (const std::string& mesh : meshes)
|
||||
{
|
||||
hecl::SystemStringView meshSys(mesh);
|
||||
meshCompiles.push_back(ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1,
|
||||
if (!mesh.compare("CMESH"))
|
||||
{
|
||||
colMesh = ds.compileColMesh(mesh);
|
||||
progress(_S("Collision Mesh"));
|
||||
continue;
|
||||
}
|
||||
meshCompiles.push_back(ds.compileMesh(mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1,
|
||||
[&](int surfCount)
|
||||
{
|
||||
progress(hecl::SysFormat(_S("%s %d"), meshSys.c_str(), surfCount).c_str());
|
||||
}));
|
||||
}
|
||||
|
||||
if (!colMesh)
|
||||
Log.report(logvisor::Fatal, _S("unable to find mesh named 'CMESH' in %s"), in.getAbsolutePath().c_str());
|
||||
|
||||
if (m_pc)
|
||||
DNAMP1::MREA::PCCook(out, in, meshCompiles);
|
||||
DNAMP1::MREA::PCCook(out, in, meshCompiles, *colMesh);
|
||||
else
|
||||
DNAMP1::MREA::Cook(out, in, meshCompiles);
|
||||
DNAMP1::MREA::Cook(out, in, meshCompiles, *colMesh);
|
||||
}
|
||||
|
||||
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit e8905db61ac226492210fbb1ed96bda7c33a7110
|
||||
Subproject commit 6b9594a40c2f286db07b979b6d2e5c6db5c5283a
|
Loading…
Reference in New Issue