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;
};
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,
const ANCSDNA& ancs,
const HECL::ProjectPath& outPath,
@ -52,11 +52,11 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
pakRouter.lookupAndReadDNA(info.cskr, cskr);
typename ANCSDNA::CINFType cinf;
pakRouter.lookupAndReadDNA(info.cinf, cinf);
using RIGPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
RIGPair rigPair(&cskr, &cinf);
using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
RigPair rigPair(&cskr, &cinf);
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.saveBlend();
@ -136,6 +136,8 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
{
os.format("act = bpy.data.actions.new('%s')\n"
"act.use_fake_user = True\n", id.second.first.c_str());
if (id.second.second.toString() == std::string("6DD5CB1DC42BFBB3"))
printf("");
anim.sendANIMToBlender(os, cinf);
}

View File

@ -18,12 +18,19 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
bitsPerKeyFrame += 1;
case Channel::TRANSLATION:
case Channel::SCALE:
{
bitsPerKeyFrame += chan.q[0];
bitsPerKeyFrame += chan.q[1];
bitsPerKeyFrame += chan.q[2];
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;
}
}
@ -43,6 +50,7 @@ static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div)
(quat.v4.vec[0] < 0) ? true : false
};
}
static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 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[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[2] * retval.v4.vec[2] +
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;
}
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)
{
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});
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;
}
}
@ -182,6 +213,24 @@ BitstreamReader::read(const atUint8* data,
kit->push_back({p[0] / (float)rotDiv, p[1] / (float)rotDiv, p[2] / (float)rotDiv});
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;
}
++kit;
@ -252,9 +301,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
++it)
{
const Value* current = &*it;
maxTransDiff = MAX(maxTransDiff, current->v3.vec[0] - last->v3.vec[0]);
maxTransDiff = 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[0] - last->v3.vec[0]);
maxTransDiff = std::max(maxTransDiff, current->v3.vec[1] - last->v3.vec[1]);
maxTransDiff = std::max(maxTransDiff, current->v3.vec[2] - last->v3.vec[2]);
last = current;
}
break;
@ -313,9 +362,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
++it)
{
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
chan.q[0] = MAX(chan.q[0], 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[2] = MAX(chan.q[2], ceilf(log2f(qrCur.v[2] - qrLast.v[2])));
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(qrCur.v[0] - qrLast.v[0]))));
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(qrCur.v[1] - qrLast.v[1]))));
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(qrCur.v[2] - qrLast.v[2]))));
qrLast = qrCur;
}
break;
@ -332,9 +381,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
atInt16(it->v3.vec[1] / transMultOut),
atInt16(it->v3.vec[2] / transMultOut)};
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0])));
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1])));
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2])));
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
last = cur;
}
break;
@ -351,9 +400,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
atInt16(it->v3.vec[1] * rotDivOut),
atInt16(it->v3.vec[2] * rotDivOut)};
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0])));
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1])));
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2])));
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
last = cur;
}
break;

View File

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

View File

@ -33,18 +33,42 @@ struct Header : BigDNA
Align<32> align;
};
struct SurfaceHeader : BigDNA
struct SurfaceHeader_1_2 : BigDNA
{
DECL_DNA
Value<atVec3f> centroid;
Value<atUint32> matIdx;
Value<atInt16> qDiv;
Value<atUint16> dlSize;
Seek<8, Athena::Current> seek;
Value<atUint32> unk1;
Value<atUint32> unk2;
Value<atUint32> aabbSz;
Value<atVec3f> reflectionNormal;
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
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
@ -274,43 +298,98 @@ public:
{
atUint16 val;
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]);
out.texMtxIdx[0] = MAX(out.texMtxIdx[0], val);
out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val));
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]);
out.texMtxIdx[2] = MAX(out.texMtxIdx[2], val);
out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val));
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]);
out.texMtxIdx[4] = MAX(out.texMtxIdx[4], val);
out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val));
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]);
out.texMtxIdx[6] = MAX(out.texMtxIdx[6], val);
out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val));
val = readVal(m_va.pos);
out.pos = MAX(out.pos, val);
out.pos = std::max(out.pos, val);
val = readVal(m_va.norm);
out.norm = MAX(out.norm, val);
out.norm = std::max(out.norm, val);
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);
out.color[1] = MAX(out.color[1], val);
out.color[1] = std::max(out.color[1], val);
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]);
out.uvs[1] = MAX(out.uvs[1], val);
out.uvs[1] = std::max(out.uvs[1], val);
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]);
out.uvs[3] = MAX(out.uvs[3], val);
out.uvs[3] = std::max(out.uvs[3], val);
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]);
out.uvs[5] = MAX(out.uvs[5], val);
out.uvs[5] = std::max(out.uvs[5], val);
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;
@ -322,12 +401,12 @@ void InitGeomBlenderContext(HECL::BlenderConnection::PyOutStream& os,
void FinishBlenderMesh(HECL::BlenderConnection::PyOutStream& os,
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,
Athena::io::IStreamReader& reader,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const RIGPAIR& rp,
const RigPair& rp,
bool shortNormals,
bool shortUVs,
std::vector<VertexAttributes>& vertAttribs,
@ -357,6 +436,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
atUint32 lastDlSec = secCount;
atUint64 afterHeaderPos = reader.position();
DLReader::DLPrimVert maxIdxs;
std::vector<atInt16> skinIndices;
for (size_t s=0 ; s<lastDlSec ; ++s)
{
atUint64 secStart = reader.position();
@ -376,6 +456,8 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
case 0:
{
/* Positions */
if (SurfaceHeader::UseMatrixSkinning() && rp.first)
skinIndices.assign(secSizes[s] / 12, -1);
break;
}
case 1:
@ -429,6 +511,9 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
/* Do max index pre-read */
atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
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);
}
@ -469,8 +554,13 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
os.format("vert = bm.verts.new((%f,%f,%f))\n",
pos.vec[0], pos.vec[1], pos.vec[2]);
if (rp.first)
{
if (SurfaceHeader::UseMatrixSkinning())
rp.first->weightVertex(os, *rp.second, skinIndices[i]);
else
rp.first->weightVertex(os, *rp.second, i);
}
}
break;
}
case 1:
@ -784,13 +874,13 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
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,
Athena::io::IStreamReader& reader,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
const RIGPAIR& rp)
const RigPair& rp)
{
Header head;
head.read(reader);
@ -824,7 +914,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
"\n";
std::vector<VertexAttributes> vertAttribs;
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RIGPAIR>
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader>
(os, reader, pakRouter, entry, rp, head.flags.shortNormals(),
head.flags.shortUVs(), vertAttribs, -1,
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)
{
cmdlOverride.read(reader);
cskrOverride.read(reader);
cmdlOverlay.read(reader);
cskrOverlay.read(reader);
}
animIdxs.clear();
@ -343,7 +343,7 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
sectionCount = 6;
else if (animIdxs.size())
sectionCount = 5;
else if (cmdlOverride)
else if (cmdlOverlay)
sectionCount = 4;
else if (effects.size())
sectionCount = 3;
@ -394,8 +394,8 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
if (sectionCount > 3)
{
cmdlOverride.write(writer);
cskrOverride.write(writer);
cmdlOverlay.write(writer);
cskrOverlay.write(writer);
}
if (sectionCount > 4)
@ -454,8 +454,8 @@ void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& read
if (sectionCount > 3)
{
reader.enumerate("cmdlOverride", cmdlOverride);
reader.enumerate("cskrOverride", cskrOverride);
reader.enumerate("cmdlOverride", cmdlOverlay);
reader.enumerate("cskrOverride", cskrOverlay);
}
animIdxs.clear();
@ -475,7 +475,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
sectionCount = 6;
else if (animIdxs.size())
sectionCount = 5;
else if (cmdlOverride)
else if (cmdlOverlay)
sectionCount = 4;
else if (effects.size())
sectionCount = 3;
@ -526,8 +526,8 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
if (sectionCount > 3)
{
writer.enumerate("cmdlOverride", cmdlOverride);
writer.enumerate("cskrOverride", cskrOverride);
writer.enumerate("cmdlOverride", cmdlOverlay);
writer.enumerate("cskrOverride", cskrOverlay);
}
if (sectionCount > 4)

View File

@ -141,8 +141,8 @@ struct ANCS : BigYAML
};
std::vector<Effect> effects;
UniqueID32 cmdlOverride;
UniqueID32 cskrOverride;
UniqueID32 cmdlOverlay;
UniqueID32 cskrOverlay;
std::vector<atUint32> animIdxs;
};
@ -401,7 +401,7 @@ struct ANCS : BigYAML
if (force || blendType == HECL::ProjectPath::PT_NONE)
{
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);
}
}

View File

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

View File

@ -40,7 +40,7 @@ struct CMDL
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
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);
return conn.saveBlend();
}

View File

@ -29,6 +29,11 @@ struct CSKR : BigDNA
};
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
{
atUint32 accum = 0;

View File

@ -188,7 +188,11 @@ void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueI
ANCS ancs;
ancs.read(rs);
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
{
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();
mHeader.read(rs);
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,
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
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;
while (zs.avail_out)
{
atUint64 readSz = strm->read(compBuf, MIN(compRem, 0x8000));
atUint64 readSz = strm->read(compBuf, std::min(compRem, atUint32(0x8000)));
compRem -= readSz;
zs.avail_in = readSz;
zs.next_in = compBuf;

View File

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

View File

@ -85,8 +85,8 @@ struct ANCS : BigYAML
};
std::vector<Effect> effects;
UniqueID32 cmdlOverride;
UniqueID32 cskrOverride;
UniqueID32 cmdlOverlay;
UniqueID32 cskrOverley;
std::vector<atUint32> animIdxs;
@ -238,7 +238,7 @@ struct ANCS : BigYAML
if (force || blendType == HECL::ProjectPath::PT_NONE)
{
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);
}
}

View File

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

View File

@ -40,7 +40,7 @@ struct CMDL
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
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);
return conn.saveBlend();
}

View File

@ -4,30 +4,21 @@
#include "BlenderConnection.hpp"
#include "../DNACommon/DNACommon.hpp"
#include "CINF.hpp"
#include "../DNAMP1/CSKR.hpp"
namespace Retro
{
namespace DNAMP2
{
struct CSKR : BigDNA
struct CSKR : DNAMP1::CSKR
{
DECL_DNA
Value<atUint32> skinningRuleCount;
struct SkinningRule : BigDNA
Delete expl;
const atInt16* getMatrixBank(size_t) const
{
DECL_DNA
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;
return nullptr;
}
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.read(rs);
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
{
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();
mHeader.read(drs);
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,
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
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
ANIM2() : IANIM(2) {}
ANIM1() : IANIM(1) {}
struct Header : BigDNA
{
DECL_DNA
Value<atUint32> scratchSize;
Value<atUint8> unk1;
Value<atUint16> unk1;
Value<atUint8> unk2;
Value<float> duration;
Value<float> interval;
Value<atUint32> unk3;
Value<atUint32> unk4;
Value<atUint32> rotDiv;
Value<atUint8> unk4[3];
Value<float> translationMult;
Value<atUint32> unk5;
Value<atUint32> boneChannelCount;
Value<atUint32> unk6;
Value<atUint32> keyBitmapBitCount;
};
struct ChannelDesc : BigDNA
{
Delete expl;
Value<atUint8> id = 0;
Value<atUint16> keyCount1 = 0;
Value<atUint16> initRX = 0;
Value<atUint8> qRX = 0;
Value<atUint16> initRY = 0;
Value<atUint8> qRY = 0;
Value<atUint16> initRZ = 0;
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);
}
}
Value<atUint32> unk7;
Value<float> unk8;
Value<float> unk9;
Value<float> duration;
Value<atUint16> keyCount;
Value<atUint32> blobSize;
Value<atUint8> unk10;
Value<atUint32> floatsSize;
Value<atUint32> flagsSize;
Value<atUint32> initBlockSize;
Value<atUint32> streamSize;
Value<atUint32> unk11;
Value<atUint32> boneCount;
};
};
@ -178,8 +88,8 @@ struct ANIM : BigDNA
m_anim.reset(new struct ANIM0);
m_anim->read(reader);
break;
case 2:
m_anim.reset(new struct ANIM2);
case 1:
m_anim.reset(new struct ANIM1);
m_anim->read(reader);
break;
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;
DECL_YAML
Delete expl;
atUint16 version;
Value<atUint16> version;
std::string name;
struct CharacterInfo : BigYAML
{
DECL_YAML
String<-1> name;
UniqueID64 cmdl;
UniqueID64 cskr;
atUint32 unk1;
atUint32 unk2;
UniqueID64 cmdl2;
UniqueID64 cskr2;
Value<atUint32> overlayCount;
struct Overlay : BigYAML
{
DECL_YAML
DNAFourCC type;
UniqueID64 cmdl;
UniqueID64 cskr;
};
Vector<Overlay, DNA_COUNT(overlayCount)> overlays;
UniqueID64 cinf;
UniqueID64 sand;
using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo;
MP1CharacterInfo::PASDatabase pasDatabase;
struct ParticleResData
struct ParticleResData : BigYAML
{
std::vector<UniqueID64> part;
std::vector<UniqueID64> swhc;
std::vector<UniqueID64> unk;
std::vector<UniqueID64> elsc;
std::vector<UniqueID64> spsc;
std::vector<UniqueID64> unk2;
DECL_YAML
Value<atUint32> partCount;
Vector<UniqueID64, DNA_COUNT(partCount)> part;
Value<atUint32> swhcCount;
Vector<UniqueID64, DNA_COUNT(swhcCount)> swhc;
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;
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
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
{
Delete expl;
@ -160,94 +232,8 @@ struct CHAR : BigYAML
String<-1> name;
MetaAnimFactory metaAnim;
};
std::vector<Animation> 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;
Value<atUint32> animationCount;
Vector<Animation, DNA_COUNT(animationCount)> animations;
struct ActionAABB : BigYAML
{
@ -255,49 +241,44 @@ struct CHAR : BigYAML
UniqueID64 animId;
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
String<-1> name;
Value<atUint32> compCount;
struct EffectComponent : BigYAML
Value<atUint32> hitboxCount;
struct Hitbox : BigYAML
{
DECL_YAML
String<-1> name;
DNAFourCC type;
UniqueID32 id;
Value<atUint32> unkMP2;
Value<float> unk1;
Value<atUint32> unk1;
Value<atUint32> unk2;
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;
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;
Value<atUint32> hitboxSetCount;
Vector<HitboxSet, DNA_COUNT(hitboxSetCount)> hitboxSets;
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID64>>& out) const
{
@ -305,16 +286,16 @@ struct CHAR : BigYAML
out.reserve(1);
out.emplace_back();
DNAANCS::CharacterResInfo<UniqueID64>& chOut = out.back();
chOut.name = name;
chOut.cmdl = cmdl;
chOut.cskr = cskr;
chOut.cinf = cinf;
chOut.name = characterInfo.name;
chOut.cmdl = characterInfo.cmdl;
chOut.cskr = characterInfo.cskr;
chOut.cinf = characterInfo.cinf;
}
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID64>>& out) const
{
out.clear();
for (const AnimationSet::Animation& ai : animationSet.animations)
for (const AnimationInfo::Animation& ai : animationInfo.animations)
ai.metaAnim.m_anim->gatherPrimitives(out);
}
@ -348,7 +329,7 @@ struct CHAR : BigYAML
if (force || blendType == HECL::ProjectPath::PT_NONE)
{
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);
}
}

View File

@ -3,74 +3,16 @@
#include "BlenderConnection.hpp"
#include "../DNACommon/DNACommon.hpp"
#include "../DNAMP2/CINF.hpp"
namespace Retro
{
namespace DNAMP3
{
struct CINF : BigDNA
struct CINF : DNAMP2::CINF
{
DECL_DNA
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;
}
}
}
}
Delete expl;
void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID64& cinfId) const
{
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);
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 << "bpy.ops.object.mode_set(mode='OBJECT')\n";

View File

@ -40,7 +40,7 @@ struct CMDL
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
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);
return conn.saveBlend();
}

View File

@ -4,6 +4,7 @@
#include "hecl/blender/BlenderConnection.hpp"
#include "../DNACommon/DNACommon.hpp"
#include "CINF.hpp"
#include "../DNAMP2/CSKR.hpp"
namespace Retro
{
@ -13,34 +14,42 @@ namespace DNAMP3
struct CSKR : BigDNA
{
DECL_DNA
Value<atUint32> skinningRuleCount;
struct SkinningRule : BigDNA
DNAFourCC magic;
Value<atUint32> version;
DNAMP2::CSKR data;
Value<atUint32> matrixCount;
struct MatrixBindings : BigDNA
{
DECL_DNA
Value<atUint32> weightCount;
struct Weight : BigDNA
{
DECL_DNA
Value<atUint32> boneId;
Value<float> weight;
Value<atInt16> mtxs[10];
};
Vector<Weight, DNA_COUNT(weightCount)> weights;
Value<atUint32> vertCount;
};
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
Vector<MatrixBindings, DNA_COUNT(matrixCount / 10)> mtxBindings;
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;
for (const SkinningRule& rule : skinningRules)
return mtxBindings.at(idx).mtxs;
}
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atInt16 skinIdx) const
{
if (idx < accum + rule.vertCount)
for (const SkinningRule::Weight& weight : rule.weights)
if (skinIdx < 0)
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",
cinf.getBoneIdxFromId(weight.boneId),
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'))
{
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")}};
case SBIG('CMDL'):
return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
#if 0
case SBIG('CHAR'):
return {nullptr, CHAR::Extract, {_S(".yaml"), _S(".blend")}, 2};
#endif
case SBIG('MREA'):
return {nullptr, MREA::Extract, {_S(".blend")}, 2};
return {nullptr, MREA::Extract, {_S(".blend")}, 3};
case SBIG('MLVL'):
return {MLVL::Extract, nullptr, {_S(".yaml")}};
}

View File

@ -83,12 +83,11 @@ void MREA::ReadBabeDeadToBlender_3(HECL::BlenderConnection::PyOutStream& os,
break;
case BabeDeadLight::LightSpot:
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.rotation_mode = 'QUATERNION'\n"
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
"\n", s, l,
light.spotCutoff / 2.f,
light.direction.vec[0], light.direction.vec[1], light.direction.vec[2]);
break;
default: continue;
@ -242,7 +241,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
{
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,
false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], surfaceCounts[m]);
}

View File

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