2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-05 19:55:51 +00:00

Working MP3 skin extraction

This commit is contained in:
Jack Andersen 2015-09-25 17:12:08 -10:00
parent 2c5f406c40
commit 60142602fd
29 changed files with 1080 additions and 460 deletions

View File

@ -20,7 +20,7 @@ struct CharacterResInfo
IDTYPE cinf; IDTYPE cinf;
}; };
template <class PAKRouter, class ANCSDNA, class MaterialSet, atUint32 CMDLVersion> template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
bool ReadANCSToBlender(HECL::BlenderConnection& conn, bool ReadANCSToBlender(HECL::BlenderConnection& conn,
const ANCSDNA& ancs, const ANCSDNA& ancs,
const HECL::ProjectPath& outPath, const HECL::ProjectPath& outPath,
@ -52,11 +52,11 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
pakRouter.lookupAndReadDNA(info.cskr, cskr); pakRouter.lookupAndReadDNA(info.cskr, cskr);
typename ANCSDNA::CINFType cinf; typename ANCSDNA::CINFType cinf;
pakRouter.lookupAndReadDNA(info.cinf, cinf); pakRouter.lookupAndReadDNA(info.cinf, cinf);
using RIGPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>; using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
RIGPair rigPair(&cskr, &cinf); RigPair rigPair(&cskr, &cinf);
PAKEntryReadStream rs = cmdlE->beginReadStream(*node); PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RIGPair, CMDLVersion> DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>
(conn, rs, pakRouter, *cmdlE, dataspec, rigPair); (conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
conn.saveBlend(); conn.saveBlend();
@ -136,6 +136,8 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
{ {
os.format("act = bpy.data.actions.new('%s')\n" os.format("act = bpy.data.actions.new('%s')\n"
"act.use_fake_user = True\n", id.second.first.c_str()); "act.use_fake_user = True\n", id.second.first.c_str());
if (id.second.second.toString() == std::string("6DD5CB1DC42BFBB3"))
printf("");
anim.sendANIMToBlender(os, cinf); anim.sendANIMToBlender(os, cinf);
} }

View File

@ -18,12 +18,19 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
bitsPerKeyFrame += 1; bitsPerKeyFrame += 1;
case Channel::TRANSLATION: case Channel::TRANSLATION:
case Channel::SCALE: case Channel::SCALE:
{
bitsPerKeyFrame += chan.q[0]; bitsPerKeyFrame += chan.q[0];
bitsPerKeyFrame += chan.q[1]; bitsPerKeyFrame += chan.q[1];
bitsPerKeyFrame += chan.q[2]; bitsPerKeyFrame += chan.q[2];
break; break;
} case Channel::KF_HEAD:
bitsPerKeyFrame += 1;
break;
case Channel::ROTATION_MP3:
bitsPerKeyFrame += chan.q[0];
bitsPerKeyFrame += chan.q[1];
bitsPerKeyFrame += chan.q[2];
bitsPerKeyFrame += chan.q[3];
break;
default: break; default: break;
} }
} }
@ -43,6 +50,7 @@ static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div)
(quat.v4.vec[0] < 0) ? true : false (quat.v4.vec[0] < 0) ? true : false
}; };
} }
static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div) static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
{ {
float q = M_PI / 2.0 / div; float q = M_PI / 2.0 / div;
@ -53,7 +61,7 @@ static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
sinf(v.v[1] * q), sinf(v.v[1] * q),
sinf(v.v[2] * q), sinf(v.v[2] * q),
}; };
retval.v4.vec[0] = sqrtf(MAX((1.0 - retval.v4.vec[0] = sqrtf(std::max((1.0 -
(retval.v4.vec[1] * retval.v4.vec[1] + (retval.v4.vec[1] * retval.v4.vec[1] +
retval.v4.vec[2] * retval.v4.vec[2] + retval.v4.vec[2] * retval.v4.vec[2] +
retval.v4.vec[3] * retval.v4.vec[3])), 0.0)); retval.v4.vec[3] * retval.v4.vec[3])), 0.0));
@ -61,6 +69,19 @@ static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
return retval; return retval;
} }
static inline Value DequantizeRotation_3(const QuantizedValue& v, atUint32 div)
{
float q = 1.0 / div;
Value retval =
{
v.v[0] * q,
v.v[1] * q,
v.v[2] * q,
v.v[3] * q
};
return retval;
}
bool BitstreamReader::dequantizeBit(const atUint8* data) bool BitstreamReader::dequantizeBit(const atUint8* data)
{ {
atUint32 byteCur = (m_bitCur / 32) * 4; atUint32 byteCur = (m_bitCur / 32) * 4;
@ -144,6 +165,16 @@ BitstreamReader::read(const atUint8* data,
keys.push_back({chan.i[0] / (float)rotDiv, chan.i[1] / (float)rotDiv, chan.i[2] / (float)rotDiv}); keys.push_back({chan.i[0] / (float)rotDiv, chan.i[1] / (float)rotDiv, chan.i[2] / (float)rotDiv});
break; break;
} }
case Channel::KF_HEAD:
{
break;
}
case Channel::ROTATION_MP3:
{
QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, chan.i[0] != 0};
keys.emplace_back(DequantizeRotation(qr, rotDiv));
break;
}
default: break; default: break;
} }
} }
@ -182,6 +213,24 @@ BitstreamReader::read(const atUint8* data,
kit->push_back({p[0] / (float)rotDiv, p[1] / (float)rotDiv, p[2] / (float)rotDiv}); kit->push_back({p[0] / (float)rotDiv, p[1] / (float)rotDiv, p[2] / (float)rotDiv});
break; break;
} }
case Channel::KF_HEAD:
{
bool aBit = dequantizeBit(data);
break;
}
case Channel::ROTATION_MP3:
{
p[0] += dequantize(data, chan.q[0]);
p[1] += dequantize(data, chan.q[1]);
p[2] += dequantize(data, chan.q[2]);
p[3] += dequantize(data, chan.q[3]);
#if 0
kit->emplace_back(DequantizeRotation_3(p, rotDiv));
#else
kit->emplace_back(DequantizeRotation({p[1], p[2], p[3]}, p[0] < 0));
#endif
break;
}
default: break; default: break;
} }
++kit; ++kit;
@ -252,9 +301,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
++it) ++it)
{ {
const Value* current = &*it; const Value* current = &*it;
maxTransDiff = MAX(maxTransDiff, current->v3.vec[0] - last->v3.vec[0]); maxTransDiff = std::max(maxTransDiff, current->v3.vec[0] - last->v3.vec[0]);
maxTransDiff = MAX(maxTransDiff, current->v3.vec[1] - last->v3.vec[1]); maxTransDiff = std::max(maxTransDiff, current->v3.vec[1] - last->v3.vec[1]);
maxTransDiff = MAX(maxTransDiff, current->v3.vec[2] - last->v3.vec[2]); maxTransDiff = std::max(maxTransDiff, current->v3.vec[2] - last->v3.vec[2]);
last = current; last = current;
} }
break; break;
@ -313,9 +362,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
++it) ++it)
{ {
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut); QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
chan.q[0] = MAX(chan.q[0], ceilf(log2f(qrCur.v[0] - qrLast.v[0]))); chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(qrCur.v[0] - qrLast.v[0]))));
chan.q[1] = MAX(chan.q[1], ceilf(log2f(qrCur.v[1] - qrLast.v[1]))); chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(qrCur.v[1] - qrLast.v[1]))));
chan.q[2] = MAX(chan.q[2], ceilf(log2f(qrCur.v[2] - qrLast.v[2]))); chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(qrCur.v[2] - qrLast.v[2]))));
qrLast = qrCur; qrLast = qrCur;
} }
break; break;
@ -332,9 +381,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut), QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
atInt16(it->v3.vec[1] / transMultOut), atInt16(it->v3.vec[1] / transMultOut),
atInt16(it->v3.vec[2] / transMultOut)}; atInt16(it->v3.vec[2] / transMultOut)};
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0]))); chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1]))); chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2]))); chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
last = cur; last = cur;
} }
break; break;
@ -351,9 +400,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut), QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
atInt16(it->v3.vec[1] * rotDivOut), atInt16(it->v3.vec[1] * rotDivOut),
atInt16(it->v3.vec[2] * rotDivOut)}; atInt16(it->v3.vec[2] * rotDivOut)};
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0]))); chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1]))); chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2]))); chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
last = cur; last = cur;
} }
break; break;

View File

@ -31,7 +31,7 @@ union Value
}; };
struct QuantizedValue struct QuantizedValue
{ {
atInt16 v[3]; atInt16 v[4];
atInt16& operator[] (size_t idx) atInt16& operator[] (size_t idx)
{return v[idx];} {return v[idx];}
const atInt16& operator[] (size_t idx) const const atInt16& operator[] (size_t idx) const
@ -48,10 +48,12 @@ struct Channel
{ {
ROTATION, ROTATION,
TRANSLATION, TRANSLATION,
SCALE SCALE,
KF_HEAD,
ROTATION_MP3
} type; } type;
QuantizedValue i = {}; QuantizedValue i = {};
atUint8 q[3] = {}; atUint8 q[4] = {};
}; };
size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& channels); size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& channels);

View File

@ -33,18 +33,42 @@ struct Header : BigDNA
Align<32> align; Align<32> align;
}; };
struct SurfaceHeader : BigDNA struct SurfaceHeader_1_2 : BigDNA
{ {
DECL_DNA DECL_DNA
Value<atVec3f> centroid; Value<atVec3f> centroid;
Value<atUint32> matIdx; Value<atUint32> matIdx;
Value<atInt16> qDiv; Value<atInt16> qDiv;
Value<atUint16> dlSize; Value<atUint16> dlSize;
Seek<8, Athena::Current> seek; Value<atUint32> unk1;
Value<atUint32> unk2;
Value<atUint32> aabbSz; Value<atUint32> aabbSz;
Value<atVec3f> reflectionNormal; Value<atVec3f> reflectionNormal;
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2; Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
Align<32> align; Align<32> align;
static constexpr bool UseMatrixSkinning() {return false;}
constexpr atInt16 skinMatrixBankIdx() const {return -1;}
};
struct SurfaceHeader_3 : BigDNA
{
DECL_DNA
Value<atVec3f> centroid;
Value<atUint32> matIdx;
Value<atInt16> qDiv;
Value<atUint16> dlSize;
Value<atUint32> unk1;
Value<atUint32> unk2;
Value<atUint32> aabbSz;
Value<atVec3f> reflectionNormal;
Value<atInt16> skinMtxBankIdx;
Value<atUint16> unk3;
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
Align<32> align;
static constexpr bool UseMatrixSkinning() {return true;}
atInt16 skinMatrixBankIdx() const {return skinMtxBankIdx;}
}; };
struct VertexAttributes struct VertexAttributes
@ -274,43 +298,98 @@ public:
{ {
atUint16 val; atUint16 val;
val = readVal(m_va.pnMtxIdx); val = readVal(m_va.pnMtxIdx);
out.pnMtxIdx = MAX(out.pnMtxIdx, val); out.pnMtxIdx = std::max(out.pnMtxIdx, atUint8(val));
val = readVal(m_va.texMtxIdx[0]); val = readVal(m_va.texMtxIdx[0]);
out.texMtxIdx[0] = MAX(out.texMtxIdx[0], val); out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val));
val = readVal(m_va.texMtxIdx[1]); val = readVal(m_va.texMtxIdx[1]);
out.texMtxIdx[1] = MAX(out.texMtxIdx[1], val); out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val));
val = readVal(m_va.texMtxIdx[2]); val = readVal(m_va.texMtxIdx[2]);
out.texMtxIdx[2] = MAX(out.texMtxIdx[2], val); out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val));
val = readVal(m_va.texMtxIdx[3]); val = readVal(m_va.texMtxIdx[3]);
out.texMtxIdx[3] = MAX(out.texMtxIdx[3], val); out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val));
val = readVal(m_va.texMtxIdx[4]); val = readVal(m_va.texMtxIdx[4]);
out.texMtxIdx[4] = MAX(out.texMtxIdx[4], val); out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val));
val = readVal(m_va.texMtxIdx[5]); val = readVal(m_va.texMtxIdx[5]);
out.texMtxIdx[5] = MAX(out.texMtxIdx[5], val); out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val));
val = readVal(m_va.texMtxIdx[6]); val = readVal(m_va.texMtxIdx[6]);
out.texMtxIdx[6] = MAX(out.texMtxIdx[6], val); out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val));
val = readVal(m_va.pos); val = readVal(m_va.pos);
out.pos = MAX(out.pos, val); out.pos = std::max(out.pos, val);
val = readVal(m_va.norm); val = readVal(m_va.norm);
out.norm = MAX(out.norm, val); out.norm = std::max(out.norm, val);
val = readVal(m_va.color0); val = readVal(m_va.color0);
out.color[0] = MAX(out.color[0], val); out.color[0] = std::max(out.color[0], val);
val = readVal(m_va.color1); val = readVal(m_va.color1);
out.color[1] = MAX(out.color[1], val); out.color[1] = std::max(out.color[1], val);
val = readVal(m_va.uvs[0]); val = readVal(m_va.uvs[0]);
out.uvs[0] = MAX(out.uvs[0], val); out.uvs[0] = std::max(out.uvs[0], val);
val = readVal(m_va.uvs[1]); val = readVal(m_va.uvs[1]);
out.uvs[1] = MAX(out.uvs[1], val); out.uvs[1] = std::max(out.uvs[1], val);
val = readVal(m_va.uvs[2]); val = readVal(m_va.uvs[2]);
out.uvs[2] = MAX(out.uvs[2], val); out.uvs[2] = std::max(out.uvs[2], val);
val = readVal(m_va.uvs[3]); val = readVal(m_va.uvs[3]);
out.uvs[3] = MAX(out.uvs[3], val); out.uvs[3] = std::max(out.uvs[3], val);
val = readVal(m_va.uvs[4]); val = readVal(m_va.uvs[4]);
out.uvs[4] = MAX(out.uvs[4], val); out.uvs[4] = std::max(out.uvs[4], val);
val = readVal(m_va.uvs[5]); val = readVal(m_va.uvs[5]);
out.uvs[5] = MAX(out.uvs[5], val); out.uvs[5] = std::max(out.uvs[5], val);
val = readVal(m_va.uvs[6]); val = readVal(m_va.uvs[6]);
out.uvs[6] = MAX(out.uvs[6], val); out.uvs[6] = std::max(out.uvs[6], val);
}
}
m_cur = bakCur;
}
void preReadMaxIdxs(DLPrimVert& out, std::vector<atInt16>& skinOut,
const atInt16 bankIn[10])
{
atUint8* bakCur = m_cur;
while (*this)
{
readPrimitive();
atUint16 vc = readVertCount();
for (atUint16 v=0 ; v<vc ; ++v)
{
atUint16 val;
atUint8 pnMtxVal = readVal(m_va.pnMtxIdx);
out.pnMtxIdx = std::max(out.pnMtxIdx, pnMtxVal);
val = readVal(m_va.texMtxIdx[0]);
out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val));
val = readVal(m_va.texMtxIdx[1]);
out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val));
val = readVal(m_va.texMtxIdx[2]);
out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val));
val = readVal(m_va.texMtxIdx[3]);
out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val));
val = readVal(m_va.texMtxIdx[4]);
out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val));
val = readVal(m_va.texMtxIdx[5]);
out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val));
val = readVal(m_va.texMtxIdx[6]);
out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val));
atUint16 posVal = readVal(m_va.pos);
out.pos = std::max(out.pos, posVal);
val = readVal(m_va.norm);
out.norm = std::max(out.norm, val);
val = readVal(m_va.color0);
out.color[0] = std::max(out.color[0], val);
val = readVal(m_va.color1);
out.color[1] = std::max(out.color[1], val);
val = readVal(m_va.uvs[0]);
out.uvs[0] = std::max(out.uvs[0], val);
val = readVal(m_va.uvs[1]);
out.uvs[1] = std::max(out.uvs[1], val);
val = readVal(m_va.uvs[2]);
out.uvs[2] = std::max(out.uvs[2], val);
val = readVal(m_va.uvs[3]);
out.uvs[3] = std::max(out.uvs[3], val);
val = readVal(m_va.uvs[4]);
out.uvs[4] = std::max(out.uvs[4], val);
val = readVal(m_va.uvs[5]);
out.uvs[5] = std::max(out.uvs[5], val);
val = readVal(m_va.uvs[6]);
out.uvs[6] = std::max(out.uvs[6], val);
skinOut[posVal] = bankIn[pnMtxVal/3];
} }
} }
m_cur = bakCur; m_cur = bakCur;
@ -322,12 +401,12 @@ void InitGeomBlenderContext(HECL::BlenderConnection::PyOutStream& os,
void FinishBlenderMesh(HECL::BlenderConnection::PyOutStream& os, void FinishBlenderMesh(HECL::BlenderConnection::PyOutStream& os,
unsigned matSetCount, int meshIdx); unsigned matSetCount, int meshIdx);
template <class PAKRouter, class MaterialSet, class RIGPAIR> template <class PAKRouter, class MaterialSet, class RigPair, class SurfaceHeader>
atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os, atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
Athena::io::IStreamReader& reader, Athena::io::IStreamReader& reader,
PAKRouter& pakRouter, PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry, const typename PAKRouter::EntryType& entry,
const RIGPAIR& rp, const RigPair& rp,
bool shortNormals, bool shortNormals,
bool shortUVs, bool shortUVs,
std::vector<VertexAttributes>& vertAttribs, std::vector<VertexAttributes>& vertAttribs,
@ -357,6 +436,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
atUint32 lastDlSec = secCount; atUint32 lastDlSec = secCount;
atUint64 afterHeaderPos = reader.position(); atUint64 afterHeaderPos = reader.position();
DLReader::DLPrimVert maxIdxs; DLReader::DLPrimVert maxIdxs;
std::vector<atInt16> skinIndices;
for (size_t s=0 ; s<lastDlSec ; ++s) for (size_t s=0 ; s<lastDlSec ; ++s)
{ {
atUint64 secStart = reader.position(); atUint64 secStart = reader.position();
@ -376,6 +456,8 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
case 0: case 0:
{ {
/* Positions */ /* Positions */
if (SurfaceHeader::UseMatrixSkinning() && rp.first)
skinIndices.assign(secSizes[s] / 12, -1);
break; break;
} }
case 1: case 1:
@ -429,6 +511,9 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
/* Do max index pre-read */ /* Do max index pre-read */
atUint32 realDlSize = secSizes[s] - (reader.position() - secStart); atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize); DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
if (SurfaceHeader::UseMatrixSkinning() && rp.first)
dl.preReadMaxIdxs(maxIdxs, skinIndices, rp.first->getMatrixBank(sHead.skinMatrixBankIdx()));
else
dl.preReadMaxIdxs(maxIdxs); dl.preReadMaxIdxs(maxIdxs);
} }
@ -469,8 +554,13 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
os.format("vert = bm.verts.new((%f,%f,%f))\n", os.format("vert = bm.verts.new((%f,%f,%f))\n",
pos.vec[0], pos.vec[1], pos.vec[2]); pos.vec[0], pos.vec[1], pos.vec[2]);
if (rp.first) if (rp.first)
{
if (SurfaceHeader::UseMatrixSkinning())
rp.first->weightVertex(os, *rp.second, skinIndices[i]);
else
rp.first->weightVertex(os, *rp.second, i); rp.first->weightVertex(os, *rp.second, i);
} }
}
break; break;
} }
case 1: case 1:
@ -784,13 +874,13 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
return lastDlSec; return lastDlSec;
} }
template <class PAKRouter, class MaterialSet, class RIGPAIR, atUint32 Version> template <class PAKRouter, class MaterialSet, class RigPair, class SurfaceHeader, atUint32 Version>
bool ReadCMDLToBlender(HECL::BlenderConnection& conn, bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
Athena::io::IStreamReader& reader, Athena::io::IStreamReader& reader,
PAKRouter& pakRouter, PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry, const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec, const SpecBase& dataspec,
const RIGPAIR& rp) const RigPair& rp)
{ {
Header head; Header head;
head.read(reader); head.read(reader);
@ -824,7 +914,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
"\n"; "\n";
std::vector<VertexAttributes> vertAttribs; std::vector<VertexAttributes> vertAttribs;
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RIGPAIR> ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader>
(os, reader, pakRouter, entry, rp, head.flags.shortNormals(), (os, reader, pakRouter, entry, rp, head.flags.shortNormals(),
head.flags.shortUVs(), vertAttribs, -1, head.flags.shortUVs(), vertAttribs, -1,
head.secCount, head.matSetCount, head.secSizes.data()); head.secCount, head.matSetCount, head.secSizes.data());

View File

@ -322,8 +322,8 @@ void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader)
if (sectionCount > 3) if (sectionCount > 3)
{ {
cmdlOverride.read(reader); cmdlOverlay.read(reader);
cskrOverride.read(reader); cskrOverlay.read(reader);
} }
animIdxs.clear(); animIdxs.clear();
@ -343,7 +343,7 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
sectionCount = 6; sectionCount = 6;
else if (animIdxs.size()) else if (animIdxs.size())
sectionCount = 5; sectionCount = 5;
else if (cmdlOverride) else if (cmdlOverlay)
sectionCount = 4; sectionCount = 4;
else if (effects.size()) else if (effects.size())
sectionCount = 3; sectionCount = 3;
@ -394,8 +394,8 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
if (sectionCount > 3) if (sectionCount > 3)
{ {
cmdlOverride.write(writer); cmdlOverlay.write(writer);
cskrOverride.write(writer); cskrOverlay.write(writer);
} }
if (sectionCount > 4) if (sectionCount > 4)
@ -454,8 +454,8 @@ void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& read
if (sectionCount > 3) if (sectionCount > 3)
{ {
reader.enumerate("cmdlOverride", cmdlOverride); reader.enumerate("cmdlOverride", cmdlOverlay);
reader.enumerate("cskrOverride", cskrOverride); reader.enumerate("cskrOverride", cskrOverlay);
} }
animIdxs.clear(); animIdxs.clear();
@ -475,7 +475,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
sectionCount = 6; sectionCount = 6;
else if (animIdxs.size()) else if (animIdxs.size())
sectionCount = 5; sectionCount = 5;
else if (cmdlOverride) else if (cmdlOverlay)
sectionCount = 4; sectionCount = 4;
else if (effects.size()) else if (effects.size())
sectionCount = 3; sectionCount = 3;
@ -526,8 +526,8 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
if (sectionCount > 3) if (sectionCount > 3)
{ {
writer.enumerate("cmdlOverride", cmdlOverride); writer.enumerate("cmdlOverride", cmdlOverlay);
writer.enumerate("cskrOverride", cskrOverride); writer.enumerate("cskrOverride", cskrOverlay);
} }
if (sectionCount > 4) if (sectionCount > 4)

View File

@ -141,8 +141,8 @@ struct ANCS : BigYAML
}; };
std::vector<Effect> effects; std::vector<Effect> effects;
UniqueID32 cmdlOverride; UniqueID32 cmdlOverlay;
UniqueID32 cskrOverride; UniqueID32 cskrOverlay;
std::vector<atUint32> animIdxs; std::vector<atUint32> animIdxs;
}; };
@ -401,7 +401,7 @@ struct ANCS : BigYAML
if (force || blendType == HECL::ProjectPath::PT_NONE) if (force || blendType == HECL::ProjectPath::PT_NONE)
{ {
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2> DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1_2, 2>
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); (conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
} }
} }

View File

@ -150,7 +150,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
atUint32 maxId = 0; atUint32 maxId = 0;
for (const std::pair<atUint32, bool>& bone : bones) for (const std::pair<atUint32, bool>& bone : bones)
maxId = MAX(maxId, bone.first); maxId = std::max(maxId, bone.first);
head.boneSlotCount = maxId + 1; head.boneSlotCount = maxId + 1;
head.write(writer); head.write(writer);
@ -239,7 +239,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
bones.reserve(head.boneChannelCount); bones.reserve(head.boneChannelCount);
channels.clear(); channels.clear();
channels.reserve(head.boneChannelCount); channels.reserve(head.boneChannelCount);
size_t keyframeCount = 0; atUint16 keyframeCount = 0;
for (size_t b=0 ; b<head.boneChannelCount ; ++b) for (size_t b=0 ; b<head.boneChannelCount ; ++b)
{ {
ChannelDesc desc; ChannelDesc desc;
@ -258,7 +258,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
chan.i[2] = desc.initRZ; chan.i[2] = desc.initRZ;
chan.q[2] = desc.qRZ; chan.q[2] = desc.qRZ;
} }
keyframeCount = MAX(keyframeCount, desc.keyCount1); keyframeCount = std::max(keyframeCount, desc.keyCount1);
if (desc.keyCount2) if (desc.keyCount2)
{ {

View File

@ -40,7 +40,7 @@ struct CMDL
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath())) if (!conn.createBlend(outPath.getAbsolutePath()))
return false; return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 2> DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_1_2, 2>
(conn, rs, pakRouter, entry, dataSpec, loadRp); (conn, rs, pakRouter, entry, dataSpec, loadRp);
return conn.saveBlend(); return conn.saveBlend();
} }

View File

@ -29,6 +29,11 @@ struct CSKR : BigDNA
}; };
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules; Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
const atInt16* getMatrixBank(size_t) const
{
return nullptr;
}
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
{ {
atUint32 accum = 0; atUint32 accum = 0;

View File

@ -188,7 +188,11 @@ void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueI
ANCS ancs; ANCS ancs;
ancs.read(rs); ancs.read(rs);
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
{
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
if (ci.cmdlOverlay)
addTo[ci.cmdlOverlay] = std::make_pair(ci.cskrOverlay, ci.cinf);
}
} }
} }
} }

View File

@ -156,7 +156,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
secStart = rs.position(); secStart = rs.position();
mHeader.read(rs); mHeader.read(rs);
rs.seek(secStart + head.secSizes[curSec++], Athena::Begin); rs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair> curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_1_2>
(os, rs, pakRouter, entry, dummy, true, (os, rs, pakRouter, entry, dummy, true,
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]); true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
os.format("obj.retro_disable_enviro_visor = %s\n" os.format("obj.retro_disable_enviro_visor = %s\n"

View File

@ -95,7 +95,7 @@ PAK::Entry::getBuffer(const NOD::DiscBase::IPartition::Node& pak, atUint64& szOu
zs.next_out = buf; zs.next_out = buf;
while (zs.avail_out) while (zs.avail_out)
{ {
atUint64 readSz = strm->read(compBuf, MIN(compRem, 0x8000)); atUint64 readSz = strm->read(compBuf, std::min(compRem, atUint32(0x8000)));
compRem -= readSz; compRem -= readSz;
zs.avail_in = readSz; zs.avail_in = readSz;
zs.next_in = compBuf; zs.next_in = compBuf;

View File

@ -57,8 +57,8 @@ void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader)
if (sectionCount > 3) if (sectionCount > 3)
{ {
cmdlOverride.read(reader); cmdlOverlay.read(reader);
cskrOverride.read(reader); cskrOverley.read(reader);
} }
animIdxs.clear(); animIdxs.clear();
@ -89,7 +89,7 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
sectionCount = 6; sectionCount = 6;
else if (animIdxs.size()) else if (animIdxs.size())
sectionCount = 5; sectionCount = 5;
else if (cmdlOverride) else if (cmdlOverlay)
sectionCount = 4; sectionCount = 4;
else if (effects.size()) else if (effects.size())
sectionCount = 3; sectionCount = 3;
@ -143,8 +143,8 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
if (sectionCount > 3) if (sectionCount > 3)
{ {
cmdlOverride.write(writer); cmdlOverlay.write(writer);
cskrOverride.write(writer); cskrOverley.write(writer);
} }
if (sectionCount > 4) if (sectionCount > 4)
@ -213,8 +213,8 @@ void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& read
if (sectionCount > 3) if (sectionCount > 3)
{ {
reader.enumerate("cmdlOverride", cmdlOverride); reader.enumerate("cmdlOverride", cmdlOverlay);
reader.enumerate("cskrOverride", cskrOverride); reader.enumerate("cskrOverride", cskrOverley);
} }
animIdxs.clear(); animIdxs.clear();
@ -245,7 +245,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
sectionCount = 6; sectionCount = 6;
else if (animIdxs.size()) else if (animIdxs.size())
sectionCount = 5; sectionCount = 5;
else if (cmdlOverride) else if (cmdlOverlay)
sectionCount = 4; sectionCount = 4;
else if (effects.size()) else if (effects.size())
sectionCount = 3; sectionCount = 3;
@ -299,8 +299,8 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
if (sectionCount > 3) if (sectionCount > 3)
{ {
writer.enumerate("cmdlOverride", cmdlOverride); writer.enumerate("cmdlOverride", cmdlOverlay);
writer.enumerate("cskrOverride", cskrOverride); writer.enumerate("cskrOverride", cskrOverley);
} }
if (sectionCount > 4) if (sectionCount > 4)

View File

@ -85,8 +85,8 @@ struct ANCS : BigYAML
}; };
std::vector<Effect> effects; std::vector<Effect> effects;
UniqueID32 cmdlOverride; UniqueID32 cmdlOverlay;
UniqueID32 cskrOverride; UniqueID32 cskrOverley;
std::vector<atUint32> animIdxs; std::vector<atUint32> animIdxs;
@ -238,7 +238,7 @@ struct ANCS : BigYAML
if (force || blendType == HECL::ProjectPath::PT_NONE) if (force || blendType == HECL::ProjectPath::PT_NONE)
{ {
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4> DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1_2, 4>
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); (conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
} }
} }

View File

@ -227,7 +227,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
atUint32 maxId = 0; atUint32 maxId = 0;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones) for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
maxId = MAX(maxId, bone.first); maxId = std::max(maxId, bone.first);
head.boneSlotCount = maxId + 1; head.boneSlotCount = maxId + 1;
head.write(writer); head.write(writer);
@ -368,7 +368,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
bones.reserve(head.boneChannelCount); bones.reserve(head.boneChannelCount);
channels.clear(); channels.clear();
channels.reserve(head.boneChannelCount); channels.reserve(head.boneChannelCount);
size_t keyframeCount = 0; atUint16 keyframeCount = 0;
for (size_t b=0 ; b<head.boneChannelCount ; ++b) for (size_t b=0 ; b<head.boneChannelCount ; ++b)
{ {
ChannelDesc desc; ChannelDesc desc;
@ -387,7 +387,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
chan.i[2] = desc.initRZ; chan.i[2] = desc.initRZ;
chan.q[2] = desc.qRZ; chan.q[2] = desc.qRZ;
} }
keyframeCount = MAX(keyframeCount, desc.keyCount1); keyframeCount = std::max(keyframeCount, desc.keyCount1);
if (desc.keyCount2) if (desc.keyCount2)
{ {
@ -401,7 +401,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
chan.i[2] = desc.initTZ; chan.i[2] = desc.initTZ;
chan.q[2] = desc.qTZ; chan.q[2] = desc.qTZ;
} }
keyframeCount = MAX(keyframeCount, desc.keyCount2); keyframeCount = std::max(keyframeCount, desc.keyCount2);
if (desc.keyCount3) if (desc.keyCount3)
{ {
@ -415,7 +415,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
chan.i[2] = desc.initSZ; chan.i[2] = desc.initSZ;
chan.q[2] = desc.qSZ; chan.q[2] = desc.qSZ;
} }
keyframeCount = MAX(keyframeCount, desc.keyCount3); keyframeCount = std::max(keyframeCount, desc.keyCount3);
} }
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels); size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);

View File

@ -40,7 +40,7 @@ struct CMDL
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath())) if (!conn.createBlend(outPath.getAbsolutePath()))
return false; return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 4> DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_1_2, 4>
(conn, rs, pakRouter, entry, dataSpec, loadRp); (conn, rs, pakRouter, entry, dataSpec, loadRp);
return conn.saveBlend(); return conn.saveBlend();
} }

View File

@ -4,30 +4,21 @@
#include "BlenderConnection.hpp" #include "BlenderConnection.hpp"
#include "../DNACommon/DNACommon.hpp" #include "../DNACommon/DNACommon.hpp"
#include "CINF.hpp" #include "CINF.hpp"
#include "../DNAMP1/CSKR.hpp"
namespace Retro namespace Retro
{ {
namespace DNAMP2 namespace DNAMP2
{ {
struct CSKR : BigDNA struct CSKR : DNAMP1::CSKR
{ {
DECL_DNA Delete expl;
Value<atUint32> skinningRuleCount;
struct SkinningRule : BigDNA const atInt16* getMatrixBank(size_t) const
{ {
DECL_DNA return nullptr;
Value<atUint32> weightCount; }
struct Weight : BigDNA
{
DECL_DNA
Value<atUint32> boneId;
Value<float> weight;
};
Vector<Weight, DNA_COUNT(weightCount)> weights;
Value<atUint32> vertCount;
};
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
{ {

View File

@ -193,7 +193,11 @@ void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueI
ANCS ancs; ANCS ancs;
ancs.read(rs); ancs.read(rs);
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
{
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
if (ci.cmdlOverlay)
addTo[ci.cmdlOverlay] = std::make_pair(ci.cskrOverley, ci.cinf);
}
} }
} }
} }

View File

@ -234,7 +234,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
secStart = drs.position(); secStart = drs.position();
mHeader.read(drs); mHeader.read(drs);
drs.seek(secStart + head.secSizes[curSec++], Athena::Begin); drs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair> curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_1_2>
(os, drs, pakRouter, entry, dummy, true, (os, drs, pakRouter, entry, dummy, true,
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]); true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
os.format("obj.retro_disable_enviro_visor = %s\n" os.format("obj.retro_disable_enviro_visor = %s\n"

View File

@ -0,0 +1,483 @@
#include "ANIM.hpp"
#include <float.h>
#include <math.h>
namespace Retro
{
namespace DNAMP3
{
using ANIMOutStream = HECL::BlenderConnection::PyOutStream::ANIMOutStream;
void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
{
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
auto kit = chanKeys.begin() + 1;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
const std::string* bName = cinf.getBoneNameFromId(bone.first);
if (!bName)
continue;
os.format("bone_string = '%s'\n", bName->c_str());
os << "action_group = act.groups.new(bone_string)\n"
"\n";
if (std::get<0>(bone.second))
os << "rotCurves = []\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string))\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string))\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string))\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n"
"\n";
if (std::get<1>(bone.second))
os << "bone_trans_head = (0.0,0.0,0.0)\n"
"if arm_obj.data.bones[bone_string].parent is not None:\n"
" bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
"transCurves = []\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
"\n";
if (std::get<2>(bone.second))
os << "scaleCurves = []\n"
"scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=0, action_group=bone_string))\n"
"scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=1, action_group=bone_string))\n"
"scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=2, action_group=bone_string))\n"
"\n";
os << "crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n"
"crv.keyframe_points.add()\n"
"crv.keyframe_points[-1].co = (0, 0)\n"
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
"\n";
ANIMOutStream ao = os.beginANIMCurve();
if (std::get<0>(bone.second))
{
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
for (int c=0 ; c<4 ; ++c)
{
auto frameit = frames.begin();
ao.changeCurve(ANIMOutStream::CurveRotate, c, rotKeys.size());
for (const DNAANIM::Value& val : rotKeys)
ao.write(*frameit++, val.v4.vec[c]);
}
}
if (std::get<1>(bone.second))
{
const std::vector<DNAANIM::Value>& transKeys = *kit++;
for (int c=0 ; c<3 ; ++c)
{
auto frameit = frames.begin();
ao.changeCurve(ANIMOutStream::CurveTranslate, c, transKeys.size());
for (const DNAANIM::Value& val : transKeys)
ao.write(*frameit++, val.v3.vec[c]);
}
}
if (std::get<2>(bone.second))
{
const std::vector<DNAANIM::Value>& scaleKeys = *kit++;
for (int c=0 ; c<3 ; ++c)
{
auto frameit = frames.begin();
ao.changeCurve(ANIMOutStream::CurveScale, c, scaleKeys.size());
for (const DNAANIM::Value& val : scaleKeys)
ao.write(*frameit++, val.v3.vec[c]);
}
}
}
}
void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
{
Header head;
head.read(reader);
mainInterval = head.interval;
frames.clear();
frames.reserve(head.keyCount);
for (size_t k=0 ; k<head.keyCount ; ++k)
frames.push_back(k);
std::map<atUint8, atUint32> boneMap;
for (size_t b=0 ; b<head.boneSlotCount ; ++b)
{
atUint8 idx = reader.readUByte();
if (idx == 0xff)
continue;
boneMap[idx] = b;
}
atUint32 boneCount = reader.readUint32Big();
bones.clear();
bones.reserve(boneCount);
for (size_t b=0 ; b<boneCount ; ++b)
{
bones.emplace_back(boneMap[b], std::make_tuple(false, false, false));
atUint8 idx = reader.readUByte();
if (idx != 0xff)
std::get<0>(bones.back().second) = true;
}
boneCount = reader.readUint32Big();
for (size_t b=0 ; b<boneCount ; ++b)
{
atUint8 idx = reader.readUByte();
if (idx != 0xff)
std::get<1>(bones.back().second) = true;
}
boneCount = reader.readUint32Big();
for (size_t b=0 ; b<boneCount ; ++b)
{
atUint8 idx = reader.readUByte();
if (idx != 0xff)
std::get<2>(bones.back().second) = true;
}
channels.clear();
chanKeys.clear();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::ROTATION;
chanKeys.emplace_back();
}
if (std::get<1>(bone.second))
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::TRANSLATION;
chanKeys.emplace_back();
}
if (std::get<2>(bone.second))
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::SCALE;
chanKeys.emplace_back();
}
}
reader.readUint32Big();
auto kit = chanKeys.begin();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
++kit;
if (std::get<1>(bone.second))
++kit;
if (std::get<2>(bone.second))
{
std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec3fBig());
}
}
reader.readUint32Big();
kit = chanKeys.begin();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
{
std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec4fBig());
}
if (std::get<1>(bone.second))
++kit;
if (std::get<2>(bone.second))
++kit;
}
reader.readUint32Big();
kit = chanKeys.begin();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
++kit;
if (std::get<1>(bone.second))
{
std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec3fBig());
}
if (std::get<2>(bone.second))
++kit;
}
}
void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
{
Header head;
head.unk0 = 0;
head.unk1 = 0;
head.unk2 = 0;
head.keyCount = frames.size();
head.duration = head.keyCount * mainInterval;
head.interval = mainInterval;
atUint32 maxId = 0;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
maxId = std::max(maxId, bone.first);
head.boneSlotCount = maxId + 1;
head.write(writer);
for (size_t s=0 ; s<head.boneSlotCount ; ++s)
{
size_t boneIdx = 0;
bool found = false;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (s == bone.first)
{
writer.writeUByte(boneIdx);
found = true;
break;
}
++boneIdx;
}
if (!found)
writer.writeUByte(0xff);
}
writer.writeUint32Big(bones.size());
size_t boneIdx = 0;
size_t rotKeyCount = 0;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
{
writer.writeUByte(boneIdx);
++rotKeyCount;
}
else
writer.writeUByte(0xff);
++boneIdx;
}
writer.writeUint32Big(bones.size());
boneIdx = 0;
size_t transKeyCount = 0;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<1>(bone.second))
{
writer.writeUByte(boneIdx);
++transKeyCount;
}
else
writer.writeUByte(0xff);
++boneIdx;
}
writer.writeUint32Big(bones.size());
boneIdx = 0;
size_t scaleKeyCount = 0;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<2>(bone.second))
{
writer.writeUByte(boneIdx);
++scaleKeyCount;
}
else
writer.writeUByte(0xff);
++boneIdx;
}
writer.writeUint32Big(scaleKeyCount * head.keyCount);
auto cit = chanKeys.begin();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
++cit;
if (std::get<1>(bone.second))
++cit;
if (std::get<2>(bone.second))
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec3fBig((*kit++).v3);
}
}
writer.writeUint32Big(rotKeyCount * head.keyCount);
cit = chanKeys.begin();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec4fBig((*kit++).v4);
}
if (std::get<1>(bone.second))
++cit;
if (std::get<2>(bone.second))
++cit;
}
writer.writeUint32Big(transKeyCount * head.keyCount);
cit = chanKeys.begin();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
++cit;
if (std::get<1>(bone.second))
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec3fBig((*kit++).v3);
}
if (std::get<2>(bone.second))
++cit;
}
}
static float ComputeFrames(const std::vector<float>& keyTimes, std::vector<atUint32>& framesOut)
{
if (keyTimes.size() <= 1)
return 0.0;
float mainInterval = FLT_MAX;
float lastTime = keyTimes[0];
for (auto it=keyTimes.begin() + 1 ; it != keyTimes.end() ; ++it)
{
float diff = *it - lastTime;
if (diff < mainInterval)
mainInterval = diff;
lastTime = *it;
}
mainInterval = 1.0 / round(1.0 / mainInterval);
framesOut.clear();
framesOut.reserve(keyTimes.size());
atUint32 frameAccum = 0;
for (float time : keyTimes)
{
while (frameAccum * mainInterval < time)
++frameAccum;
framesOut.push_back(frameAccum);
}
return mainInterval;
}
void ANIM::ANIM1::read(Athena::io::IStreamReader& reader)
{
Header head;
head.read(reader);
std::vector<float> keyTimes;
keyTimes.reserve(head.keyCount);
for (size_t k=0 ; k<head.keyCount ; ++k)
keyTimes.push_back(reader.readFloatBig());
mainInterval = ComputeFrames(keyTimes, frames);
atUint8 boneFlagCount = reader.readUByte();
bones.clear();
bones.reserve(boneFlagCount);
atUint32 boneChannelCount = 0;
for (atUint8 f=0 ; f<boneFlagCount ; ++f)
{
atUint8 flag = reader.readUByte();
bones.emplace_back(f, std::make_tuple(flag & 0x1, flag & 0x2, flag & 0x4));
if (flag & 0x1)
++boneChannelCount;
if (flag & 0x2)
++boneChannelCount;
if (flag & 0x4)
++boneChannelCount;
}
std::vector<atInt16> initBlock;
initBlock.reserve(head.initBlockSize/2);
for (size_t i=0 ; i<head.initBlockSize/2 ; ++i)
initBlock.push_back(reader.readInt16Big());
atUint32 rawChannelCount = reader.readUint32Big();
atUint32 scratchSize1 = reader.readUint32Big();
atUint32 scratchSize2 = reader.readUint32Big();
std::vector<atUint8> chanBitCounts;
chanBitCounts.reserve(rawChannelCount);
for (size_t c=0 ; c<rawChannelCount ; ++c)
chanBitCounts.push_back(reader.readUByte());
channels.clear();
channels.reserve(boneChannelCount + 1);
channels.emplace_back();
channels.back().type = DNAANIM::Channel::KF_HEAD;
auto initsIt = initBlock.begin();
auto bitsIt = chanBitCounts.begin();
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{
if (std::get<0>(bone.second))
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::ROTATION_MP3;
chan.i[0] = *initsIt++;
chan.q[0] = *bitsIt++;
chan.i[1] = *initsIt++;
chan.q[1] = *bitsIt++;
chan.i[2] = *initsIt++;
chan.q[2] = *bitsIt++;
chan.i[3] = *initsIt++;
chan.q[3] = *bitsIt++;
}
if (std::get<1>(bone.second))
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::TRANSLATION;
chan.i[0] = *initsIt++;
chan.q[0] = *bitsIt++;
chan.i[1] = *initsIt++;
chan.q[1] = *bitsIt++;
chan.i[2] = *initsIt++;
chan.q[2] = *bitsIt++;
}
if (std::get<2>(bone.second))
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::SCALE;
chan.i[0] = *initsIt++;
chan.q[0] = *bitsIt++;
chan.i[1] = *initsIt++;
chan.q[1] = *bitsIt++;
chan.i[2] = *initsIt++;
chan.q[2] = *bitsIt++;
}
}
size_t bsSize = DNAANIM::ComputeBitstreamSize(head.keyCount-1, channels);
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
DNAANIM::BitstreamReader bsReader;
chanKeys = bsReader.read(bsData.get(), head.keyCount-1, channels, 32767, head.translationMult);
}
void ANIM::ANIM1::write(Athena::io::IStreamWriter& writer) const
{
}
}
}

View File

@ -48,123 +48,33 @@ struct ANIM : BigDNA
}; };
}; };
struct ANIM2 : IANIM struct ANIM1 : IANIM
{ {
DECL_EXPLICIT_DNA DECL_EXPLICIT_DNA
ANIM2() : IANIM(2) {} ANIM1() : IANIM(1) {}
struct Header : BigDNA struct Header : BigDNA
{ {
DECL_DNA DECL_DNA
Value<atUint32> scratchSize; Value<atUint16> unk1;
Value<atUint8> unk1;
Value<atUint8> unk2; Value<atUint8> unk2;
Value<float> duration;
Value<float> interval;
Value<atUint32> unk3; Value<atUint32> unk3;
Value<atUint32> unk4; Value<atUint8> unk4[3];
Value<atUint32> rotDiv;
Value<float> translationMult; Value<float> translationMult;
Value<atUint32> unk5;
Value<atUint32> boneChannelCount;
Value<atUint32> unk6; Value<atUint32> unk6;
Value<atUint32> keyBitmapBitCount; Value<atUint32> unk7;
}; Value<float> unk8;
Value<float> unk9;
struct ChannelDesc : BigDNA Value<float> duration;
{ Value<atUint16> keyCount;
Delete expl; Value<atUint32> blobSize;
Value<atUint8> id = 0; Value<atUint8> unk10;
Value<atUint16> keyCount1 = 0; Value<atUint32> floatsSize;
Value<atUint16> initRX = 0; Value<atUint32> flagsSize;
Value<atUint8> qRX = 0; Value<atUint32> initBlockSize;
Value<atUint16> initRY = 0; Value<atUint32> streamSize;
Value<atUint8> qRY = 0; Value<atUint32> unk11;
Value<atUint16> initRZ = 0; Value<atUint32> boneCount;
Value<atUint8> qRZ = 0;
Value<atUint16> keyCount2 = 0;
Value<atUint16> initTX = 0;
Value<atUint8> qTX = 0;
Value<atUint16> initTY = 0;
Value<atUint8> qTY = 0;
Value<atUint16> initTZ = 0;
Value<atUint8> qTZ = 0;
Value<atUint16> keyCount3 = 0;
Value<atUint16> initSX = 0;
Value<atUint8> qSX = 0;
Value<atUint16> initSY = 0;
Value<atUint8> qSY = 0;
Value<atUint16> initSZ = 0;
Value<atUint8> qSZ = 0;
void read(Athena::io::IStreamReader& reader)
{
id = reader.readUByte();
keyCount1 = reader.readUint16Big();
if (keyCount1)
{
initRX = reader.readUint16Big();
qRX = reader.readUByte();
initRY = reader.readUint16Big();
qRY = reader.readUByte();
initRZ = reader.readUint16Big();
qRZ = reader.readUByte();
}
keyCount2 = reader.readUint16Big();
if (keyCount2)
{
initTX = reader.readUint16Big();
qTX = reader.readUByte();
initTY = reader.readUint16Big();
qTY = reader.readUByte();
initTZ = reader.readUint16Big();
qTZ = reader.readUByte();
}
keyCount3 = reader.readUint16Big();
if (keyCount3)
{
initSX = reader.readUint16Big();
qSX = reader.readUByte();
initSY = reader.readUint16Big();
qSY = reader.readUByte();
initSZ = reader.readUint16Big();
qSZ = reader.readUByte();
}
}
void write(Athena::io::IStreamWriter& writer) const
{
writer.writeUByte(id);
writer.writeUint16Big(keyCount1);
if (keyCount1)
{
writer.writeUint16Big(initRX);
writer.writeUByte(qRX);
writer.writeUint16Big(initRY);
writer.writeUByte(qRY);
writer.writeUint16Big(initRZ);
writer.writeUByte(qRZ);
}
writer.writeUint16Big(keyCount2);
if (keyCount2)
{
writer.writeUint16Big(initTX);
writer.writeUByte(qTX);
writer.writeUint16Big(initTY);
writer.writeUByte(qTY);
writer.writeUint16Big(initTZ);
writer.writeUByte(qTZ);
}
writer.writeUint16Big(keyCount3);
if (keyCount3)
{
writer.writeUint16Big(initSX);
writer.writeUByte(qSX);
writer.writeUint16Big(initSY);
writer.writeUByte(qSY);
writer.writeUint16Big(initSZ);
writer.writeUByte(qSZ);
}
}
}; };
}; };
@ -178,8 +88,8 @@ struct ANIM : BigDNA
m_anim.reset(new struct ANIM0); m_anim.reset(new struct ANIM0);
m_anim->read(reader); m_anim->read(reader);
break; break;
case 2: case 1:
m_anim.reset(new struct ANIM2); m_anim.reset(new struct ANIM1);
m_anim->read(reader); m_anim->read(reader);
break; break;
default: default:

View File

@ -0,0 +1,144 @@
#include "CHAR.hpp"
namespace Retro
{
namespace DNAMP3
{
void CHAR::AnimationInfo::EVNT::SFXEvent::read(Athena::io::IStreamReader& reader)
{
EventBase::read(reader);
caudId.read(reader);
unk1 = reader.readUint32Big();
unk2 = reader.readUint32Big();
unk3 = reader.readUint32Big();
extraType = reader.readUint32Big();
if (extraType == 1)
extraFloat = reader.readFloatBig();
else if (extraType == 2)
reader.seek(35, Athena::Current);
}
void CHAR::AnimationInfo::EVNT::SFXEvent::write(Athena::io::IStreamWriter& writer) const
{
EventBase::write(writer);
caudId.write(writer);
writer.writeUint32Big(unk1);
writer.writeUint32Big(unk2);
writer.writeUint32Big(unk3);
writer.writeUint32Big(extraType);
if (extraType == 1)
writer.writeFloatBig(extraFloat);
else if (extraType == 2)
writer.seek(35, Athena::Current);
}
void CHAR::AnimationInfo::EVNT::SFXEvent::fromYAML(Athena::io::YAMLDocReader& reader)
{
EventBase::fromYAML(reader);
reader.enumerate("caudId", caudId);
unk1 = reader.readUint32("unk1");
unk2 = reader.readUint32("unk2");
unk3 = reader.readUint32("unk3");
extraType = reader.readUint32("extraType");
if (extraType == 1)
extraFloat = reader.readFloat("extraFloat");
}
void CHAR::AnimationInfo::EVNT::SFXEvent::toYAML(Athena::io::YAMLDocWriter& writer) const
{
EventBase::toYAML(writer);
writer.enumerate("caudId", caudId);
writer.writeUint32("unk1", unk1);
writer.writeUint32("unk2", unk2);
writer.writeUint32("unk3", unk3);
writer.writeUint32("extraType", extraType);
if (extraType == 1)
writer.writeFloat("extraFloat", extraFloat);
}
void CHAR::AnimationInfo::MetaAnimFactory::read(Athena::io::IStreamReader& reader)
{
IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big()));
switch (type)
{
case IMetaAnim::MAPrimitive:
m_anim.reset(new struct MetaAnimPrimitive);
m_anim->read(reader);
break;
case IMetaAnim::MABlend:
m_anim.reset(new struct MetaAnimBlend);
m_anim->read(reader);
break;
case IMetaAnim::MAPhaseBlend:
m_anim.reset(new struct MetaAnimPhaseBlend);
m_anim->read(reader);
break;
case IMetaAnim::MARandom:
m_anim.reset(new struct MetaAnimRandom);
m_anim->read(reader);
break;
case IMetaAnim::MASequence:
m_anim.reset(new struct MetaAnimSequence);
m_anim->read(reader);
break;
default:
m_anim.reset(nullptr);
break;
}
}
void CHAR::AnimationInfo::MetaAnimFactory::write(Athena::io::IStreamWriter& writer) const
{
if (!m_anim)
return;
writer.writeInt32Big(m_anim->m_type);
m_anim->write(writer);
}
void CHAR::AnimationInfo::MetaAnimFactory::fromYAML(Athena::io::YAMLDocReader& reader)
{
std::string type = reader.readString("type");
std::transform(type.begin(), type.end(), type.begin(), tolower);
if (!type.compare("primitive"))
{
m_anim.reset(new struct MetaAnimPrimitive);
m_anim->fromYAML(reader);
}
else if (!type.compare("blend"))
{
m_anim.reset(new struct MetaAnimBlend);
m_anim->fromYAML(reader);
}
else if (!type.compare("phaseblend"))
{
m_anim.reset(new struct MetaAnimPhaseBlend);
m_anim->fromYAML(reader);
}
else if (!type.compare("random"))
{
m_anim.reset(new struct MetaAnimRandom);
m_anim->fromYAML(reader);
}
else if (!type.compare("sequence"))
{
m_anim.reset(new struct MetaAnimSequence);
m_anim->fromYAML(reader);
}
else
{
m_anim.reset(nullptr);
}
}
void CHAR::AnimationInfo::MetaAnimFactory::toYAML(Athena::io::YAMLDocWriter& writer) const
{
if (!m_anim)
return;
writer.writeString("type", m_anim->m_typeStr);
m_anim->toYAML(writer);
}
}
}

View File

@ -23,37 +23,109 @@ struct CHAR : BigYAML
using ANIMType = ANIM; using ANIMType = ANIM;
DECL_YAML DECL_YAML
Delete expl; Value<atUint16> version;
atUint16 version;
std::string name; struct CharacterInfo : BigYAML
{
DECL_YAML
String<-1> name;
UniqueID64 cmdl; UniqueID64 cmdl;
UniqueID64 cskr; UniqueID64 cskr;
atUint32 unk1; Value<atUint32> overlayCount;
atUint32 unk2; struct Overlay : BigYAML
UniqueID64 cmdl2; {
UniqueID64 cskr2; DECL_YAML
DNAFourCC type;
UniqueID64 cmdl;
UniqueID64 cskr;
};
Vector<Overlay, DNA_COUNT(overlayCount)> overlays;
UniqueID64 cinf; UniqueID64 cinf;
UniqueID64 sand; UniqueID64 sand;
using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo; using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo;
MP1CharacterInfo::PASDatabase pasDatabase; MP1CharacterInfo::PASDatabase pasDatabase;
struct ParticleResData struct ParticleResData : BigYAML
{ {
std::vector<UniqueID64> part; DECL_YAML
std::vector<UniqueID64> swhc; Value<atUint32> partCount;
std::vector<UniqueID64> unk; Vector<UniqueID64, DNA_COUNT(partCount)> part;
std::vector<UniqueID64> elsc; Value<atUint32> swhcCount;
std::vector<UniqueID64> spsc; Vector<UniqueID64, DNA_COUNT(swhcCount)> swhc;
std::vector<UniqueID64> unk2; Value<atUint32> unkCount;
Vector<UniqueID64, DNA_COUNT(unkCount)> unk;
Value<atUint32> elscCount;
Vector<UniqueID64, DNA_COUNT(elscCount)> elsc;
Value<atUint32> spscCount;
Vector<UniqueID64, DNA_COUNT(spscCount)> spsc;
Value<atUint32> unk2Count;
Vector<UniqueID64, DNA_COUNT(unk2Count)> unk2;
} partResData; } partResData;
struct AnimationSet : BigYAML } characterInfo;
struct AnimationInfo : BigYAML
{
DECL_YAML
struct EVNT : BigYAML
{
DECL_YAML
Value<atUint32> eventBinding;
String<-1> eventName;
struct EventBase : BigYAML
{
DECL_YAML
String<-1> name1;
Value<atUint16> unk0;
String<-1> name2;
Value<atUint16> type;
Value<atUint32> unk1;
Value<atUint32> unk2;
Value<atUint32> unk3;
Value<atUint32> unk4;
Value<atUint8> unk5;
Value<float> unk6;
Value<atUint32> unk7;
Value<atUint32> unk8;
Value<atUint32> unk9;
Value<atUint32> unk10;
Value<atUint32> unk11;
Value<atUint32> unk12;
Value<atUint32> unk13;
};
struct EffectEvent : EventBase
{
DECL_YAML
DNAFourCC effectType;
UniqueID64 effectId;
Value<float> scale;
Value<atUint32> parentMode;
};
Value<atUint32> effectCount;
Vector<EffectEvent, DNA_COUNT(effectCount)> effectEvents;
struct SFXEvent : EventBase
{ {
DECL_YAML DECL_YAML
Delete expl; Delete expl;
UniqueID64 caudId;
Value<atUint32> unk1;
Value<atUint32> unk2;
Value<atUint32> unk3;
Value<atUint32> extraType;
Value<float> extraFloat;
};
Value<atUint32> sfxCount;
Vector<SFXEvent, DNA_COUNT(sfxCount)> sfxEvents;
};
Value<atUint32> evntCount;
Vector<EVNT, DNA_COUNT(evntCount)> evnts;
struct IMetaAnim : BigYAML struct IMetaAnim : BigYAML
{ {
Delete expl; Delete expl;
@ -160,94 +232,8 @@ struct CHAR : BigYAML
String<-1> name; String<-1> name;
MetaAnimFactory metaAnim; MetaAnimFactory metaAnim;
}; };
std::vector<Animation> animations; Value<atUint32> animationCount;
Vector<Animation, DNA_COUNT(animationCount)> animations;
struct IMetaTrans : BigYAML
{
Delete expl;
enum Type
{
MTMetaAnim = 0,
MTTrans = 1,
MTPhaseTrans = 2,
MTNoTrans = 3,
} m_type;
const char* m_typeStr;
IMetaTrans(Type type, const char* typeStr)
: m_type(type), m_typeStr(typeStr) {}
};
struct MetaTransFactory : BigYAML
{
DECL_YAML
Delete expl;
std::unique_ptr<IMetaTrans> m_trans;
};
struct MetaTransMetaAnim : IMetaTrans
{
MetaTransMetaAnim() : IMetaTrans(MTMetaAnim, "MetaAnim") {}
DECL_YAML
MetaAnimFactory anim;
};
struct MetaTransTrans : IMetaTrans
{
MetaTransTrans() : IMetaTrans(MTTrans, "Trans") {}
DECL_YAML
Value<float> time;
Value<atUint32> unk1;
Value<atUint8> unk2;
Value<atUint8> unk3;
Value<atUint32> unk4;
};
struct MetaTransPhaseTrans : IMetaTrans
{
MetaTransPhaseTrans() : IMetaTrans(MTPhaseTrans, "PhaseTrans") {}
DECL_YAML
Value<float> time;
Value<atUint32> unk1;
Value<atUint8> unk2;
Value<atUint8> unk3;
Value<atUint32> unk4;
};
struct Transition : BigYAML
{
DECL_YAML
Value<atUint32> unk;
Value<atUint32> animIdxA;
Value<atUint32> animIdxB;
MetaTransFactory metaTrans;
};
std::vector<Transition> transitions;
MetaTransFactory defaultTransition;
struct AdditiveAnimationInfo : BigYAML
{
DECL_YAML
Value<atUint32> animIdx;
Value<float> unk1;
Value<float> unk2;
};
std::vector<AdditiveAnimationInfo> additiveAnims;
float floatA = 0.0;
float floatB = 0.0;
struct HalfTransition : BigYAML
{
DECL_YAML
Value<atUint32> animIdx;
MetaTransFactory metaTrans;
};
std::vector<HalfTransition> halfTransitions;
struct AnimationResources : BigYAML
{
DECL_YAML
UniqueID64 animId;
UniqueID64 evntId;
};
std::vector<AnimationResources> animResources;
} animationSet;
struct ActionAABB : BigYAML struct ActionAABB : BigYAML
{ {
@ -255,49 +241,44 @@ struct CHAR : BigYAML
UniqueID64 animId; UniqueID64 animId;
Value<atVec3f> aabb[2]; Value<atVec3f> aabb[2];
}; };
std::vector<ActionAABB> animAABBs; Value<atUint32> animAABBCount;
Vector<ActionAABB, DNA_COUNT(animAABBCount)> animAABBs;
atUint32 unk3 = 0; Value<atUint8> unkByte;
Value<atUint32> additiveMapCount;
Vector<bool, DNA_COUNT(additiveMapCount)> additiveMap;
struct Effect : BigYAML } animationInfo;
struct HitboxSet : BigYAML
{ {
DECL_YAML DECL_YAML
String<-1> name; String<-1> name;
Value<atUint32> compCount; Value<atUint32> hitboxCount;
struct EffectComponent : BigYAML struct Hitbox : BigYAML
{ {
DECL_YAML DECL_YAML
String<-1> name; Value<atUint32> unk1;
DNAFourCC type;
UniqueID32 id;
Value<atUint32> unkMP2;
Value<float> unk1;
Value<atUint32> unk2; Value<atUint32> unk2;
Value<atUint32> unk3; Value<atUint32> unk3;
Value<atUint32> unk4;
Value<atUint32> unk5;
Value<float> unk6;
Value<float> unk7;
Value<float> unk8;
Value<float> unk9;
Value<float> unk10;
Value<float> unk11;
Value<float> unk12;
Value<float> unk13;
String<-1> boneName;
Value<float> unk14;
}; };
Vector<EffectComponent, DNA_COUNT(compCount)> comps; Vector<Hitbox, DNA_COUNT(hitboxCount)> hitboxes;
}; };
std::vector<Effect> effects; Value<atUint32> hitboxSetCount;
Vector<HitboxSet, DNA_COUNT(hitboxSetCount)> hitboxSets;
UniqueID32 cmdlOverride;
UniqueID32 cskrOverride;
std::vector<atUint32> animIdxs;
atUint32 unk4;
atUint8 unk5;
struct Extents : BigYAML
{
DECL_YAML
Value<atUint32> animIdx;
Value<atVec3f> aabb[2];
};
std::vector<Extents> extents;
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID64>>& out) const void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID64>>& out) const
{ {
@ -305,16 +286,16 @@ struct CHAR : BigYAML
out.reserve(1); out.reserve(1);
out.emplace_back(); out.emplace_back();
DNAANCS::CharacterResInfo<UniqueID64>& chOut = out.back(); DNAANCS::CharacterResInfo<UniqueID64>& chOut = out.back();
chOut.name = name; chOut.name = characterInfo.name;
chOut.cmdl = cmdl; chOut.cmdl = characterInfo.cmdl;
chOut.cskr = cskr; chOut.cskr = characterInfo.cskr;
chOut.cinf = cinf; chOut.cinf = characterInfo.cinf;
} }
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID64>>& out) const void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID64>>& out) const
{ {
out.clear(); out.clear();
for (const AnimationSet::Animation& ai : animationSet.animations) for (const AnimationInfo::Animation& ai : animationInfo.animations)
ai.metaAnim.m_anim->gatherPrimitives(out); ai.metaAnim.m_anim->gatherPrimitives(out);
} }
@ -348,7 +329,7 @@ struct CHAR : BigYAML
if (force || blendType == HECL::ProjectPath::PT_NONE) if (force || blendType == HECL::ProjectPath::PT_NONE)
{ {
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, CHAR, MaterialSet, 4> DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, CHAR, MaterialSet, DNACMDL::SurfaceHeader_3, 4>
(conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force); (conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
} }
} }

View File

@ -3,74 +3,16 @@
#include "BlenderConnection.hpp" #include "BlenderConnection.hpp"
#include "../DNACommon/DNACommon.hpp" #include "../DNACommon/DNACommon.hpp"
#include "../DNAMP2/CINF.hpp"
namespace Retro namespace Retro
{ {
namespace DNAMP3 namespace DNAMP3
{ {
struct CINF : BigDNA struct CINF : DNAMP2::CINF
{ {
DECL_DNA Delete expl;
Value<atUint32> boneCount;
struct Bone : BigDNA
{
DECL_DNA
Value<atUint32> id;
Value<atUint32> parentId;
Value<atVec3f> origin;
Value<atUint32> linkedCount;
Vector<atUint32, DNA_COUNT(linkedCount)> linked;
};
Vector<Bone, DNA_COUNT(boneCount)> bones;
Value<atUint32> boneIdCount;
Vector<atUint32, DNA_COUNT(boneIdCount)> boneIds;
Value<atUint32> nameCount;
struct Name : BigDNA
{
DECL_DNA
String<-1> name;
Value<atUint32> boneId;
};
Vector<Name, DNA_COUNT(nameCount)> names;
atUint32 getBoneIdxFromId(atUint32 id) const
{
atUint32 idx = 0;
for (atUint32 bid : boneIds)
{
if (bid == id)
return idx;
++idx;
}
return 0;
}
const std::string* getBoneNameFromId(atUint32 id) const
{
for (const Name& name : names)
if (id == name.boneId)
return &name.name;
return nullptr;
}
void sendVertexGroupsToBlender(HECL::BlenderConnection::PyOutStream& os) const
{
for (atUint32 bid : boneIds)
{
for (const Name& name : names)
{
if (name.boneId == bid)
{
os.format("obj.vertex_groups.new('%s')\n", name.name.c_str());
break;
}
}
}
}
void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID64& cinfId) const void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID64& cinfId) const
{ {
os.format("arm = bpy.data.armatures.new('CINF_%016" PRIX64 "')\n" os.format("arm = bpy.data.armatures.new('CINF_%016" PRIX64 "')\n"
@ -90,7 +32,7 @@ struct CINF : BigDNA
bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id); bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
for (const Bone& bone : bones) for (const Bone& bone : bones)
if (bone.parentId != 2) if (bone.parentId != 97 && bone.parentId != 147)
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId); os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; os << "bpy.ops.object.mode_set(mode='OBJECT')\n";

View File

@ -40,7 +40,7 @@ struct CMDL
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath())) if (!conn.createBlend(outPath.getAbsolutePath()))
return false; return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 5> DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_3, 5>
(conn, rs, pakRouter, entry, dataSpec, loadRp); (conn, rs, pakRouter, entry, dataSpec, loadRp);
return conn.saveBlend(); return conn.saveBlend();
} }

View File

@ -4,6 +4,7 @@
#include "hecl/blender/BlenderConnection.hpp" #include "hecl/blender/BlenderConnection.hpp"
#include "../DNACommon/DNACommon.hpp" #include "../DNACommon/DNACommon.hpp"
#include "CINF.hpp" #include "CINF.hpp"
#include "../DNAMP2/CSKR.hpp"
namespace Retro namespace Retro
{ {
@ -13,34 +14,42 @@ namespace DNAMP3
struct CSKR : BigDNA struct CSKR : BigDNA
{ {
DECL_DNA DECL_DNA
Value<atUint32> skinningRuleCount; DNAFourCC magic;
struct SkinningRule : BigDNA Value<atUint32> version;
DNAMP2::CSKR data;
Value<atUint32> matrixCount;
struct MatrixBindings : BigDNA
{ {
DECL_DNA DECL_DNA
Value<atUint32> weightCount; Value<atInt16> mtxs[10];
struct Weight : BigDNA
{
DECL_DNA
Value<atUint32> boneId;
Value<float> weight;
}; };
Vector<Weight, DNA_COUNT(weightCount)> weights; Vector<MatrixBindings, DNA_COUNT(matrixCount / 10)> mtxBindings;
Value<atUint32> vertCount;
};
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const Value<atUint32> unkCount1;
Vector<atUint8, DNA_COUNT(unkCount1)> unk1;
Value<atUint32> unkCount2;
Vector<atUint8, DNA_COUNT(unkCount2)> unk2;
Value<atUint32> unkCount3;
Vector<atUint8, DNA_COUNT(unkCount3)> unk3;
Value<atUint32> unkCount4;
Vector<atUint8, DNA_COUNT(unkCount4)> unk4;
Value<atUint32> unkCount5;
Vector<atUint8, DNA_COUNT(unkCount5)> unk5;
const atInt16* getMatrixBank(size_t idx) const
{ {
atUint32 accum = 0; return mtxBindings.at(idx).mtxs;
for (const SkinningRule& rule : skinningRules) }
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atInt16 skinIdx) const
{ {
if (idx < accum + rule.vertCount) if (skinIdx < 0)
for (const SkinningRule::Weight& weight : rule.weights) return;
const DNAMP2::CSKR::SkinningRule& rule = data.skinningRules[skinIdx];
for (const DNAMP2::CSKR::SkinningRule::Weight& weight : rule.weights)
os.format("vert[dvert_lay][%u] = %f\n", os.format("vert[dvert_lay][%u] = %f\n",
cinf.getBoneIdxFromId(weight.boneId), cinf.getBoneIdxFromId(weight.boneId),
weight.weight); weight.weight);
accum += rule.vertCount;
}
} }
}; };

View File

@ -203,6 +203,13 @@ void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID64, std::pair<UniqueI
{ {
if (entry.second->type == FOURCC('CHAR')) if (entry.second->type == FOURCC('CHAR'))
{ {
PAKEntryReadStream rs = entry.second->beginReadStream(m_node);
CHAR aChar;
aChar.read(rs);
const CHAR::CharacterInfo& ci = aChar.characterInfo;
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays)
addTo[overlay.cmdl] = std::make_pair(overlay.cskr, ci.cinf);
} }
} }
} }
@ -217,12 +224,10 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
return {TXTR::Extract, nullptr, {_S(".png")}}; return {TXTR::Extract, nullptr, {_S(".png")}};
case SBIG('CMDL'): case SBIG('CMDL'):
return {nullptr, CMDL::Extract, {_S(".blend")}, 1}; return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
#if 0
case SBIG('CHAR'): case SBIG('CHAR'):
return {nullptr, CHAR::Extract, {_S(".yaml"), _S(".blend")}, 2}; return {nullptr, CHAR::Extract, {_S(".yaml"), _S(".blend")}, 2};
#endif
case SBIG('MREA'): case SBIG('MREA'):
return {nullptr, MREA::Extract, {_S(".blend")}, 2}; return {nullptr, MREA::Extract, {_S(".blend")}, 3};
case SBIG('MLVL'): case SBIG('MLVL'):
return {MLVL::Extract, nullptr, {_S(".yaml")}}; return {MLVL::Extract, nullptr, {_S(".yaml")}};
} }

View File

@ -83,12 +83,11 @@ void MREA::ReadBabeDeadToBlender_3(HECL::BlenderConnection::PyOutStream& os,
break; break;
case BabeDeadLight::LightSpot: case BabeDeadLight::LightSpot:
os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n" os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n"
"lamp.spot_size = %f\n" "lamp.spot_size = 1.0\n"
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
"lamp_obj.rotation_mode = 'QUATERNION'\n" "lamp_obj.rotation_mode = 'QUATERNION'\n"
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n" "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
"\n", s, l, "\n", s, l,
light.spotCutoff / 2.f,
light.direction.vec[0], light.direction.vec[1], light.direction.vec[2]); light.direction.vec[0], light.direction.vec[1], light.direction.vec[2]);
break; break;
default: continue; default: continue;
@ -242,7 +241,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
{ {
for (int m=0 ; m<head.meshCount ; ++m) for (int m=0 ; m<head.meshCount ; ++m)
{ {
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair> curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_3>
(os, drs, pakRouter, entry, dummy, true, (os, drs, pakRouter, entry, dummy, true,
false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], surfaceCounts[m]); false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], surfaceCounts[m]);
} }

View File

@ -98,7 +98,7 @@ struct MREA
Value<atUint8> unk8; Value<atUint8> unk8;
Value<atUint32> unk9; Value<atUint32> unk9;
Value<atUint32> unk10; Value<atUint32> unk10;
Value<float> spotCutoff; Value<float> unk11;
Value<atVec4f> unk12; Value<atVec4f> unk12;
Value<atUint32> unk13; Value<atUint32> unk13;
}; };