mirror of https://github.com/AxioDL/metaforce.git
Working MP3 skin extraction
This commit is contained in:
parent
2c5f406c40
commit
60142602fd
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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")}};
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue