mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-07-05 19:55:51 +00:00
Working MP3 skin extraction
This commit is contained in:
parent
2c5f406c40
commit
60142602fd
@ -20,7 +20,7 @@ struct CharacterResInfo
|
|||||||
IDTYPE cinf;
|
IDTYPE cinf;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class PAKRouter, class ANCSDNA, class MaterialSet, atUint32 CMDLVersion>
|
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
|
||||||
bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
||||||
const ANCSDNA& ancs,
|
const ANCSDNA& ancs,
|
||||||
const HECL::ProjectPath& outPath,
|
const HECL::ProjectPath& outPath,
|
||||||
@ -52,11 +52,11 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||||||
pakRouter.lookupAndReadDNA(info.cskr, cskr);
|
pakRouter.lookupAndReadDNA(info.cskr, cskr);
|
||||||
typename ANCSDNA::CINFType cinf;
|
typename ANCSDNA::CINFType cinf;
|
||||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||||
using RIGPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||||
RIGPair rigPair(&cskr, &cinf);
|
RigPair rigPair(&cskr, &cinf);
|
||||||
|
|
||||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RIGPair, CMDLVersion>
|
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>
|
||||||
(conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
|
(conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
|
||||||
|
|
||||||
conn.saveBlend();
|
conn.saveBlend();
|
||||||
@ -136,6 +136,8 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||||||
{
|
{
|
||||||
os.format("act = bpy.data.actions.new('%s')\n"
|
os.format("act = bpy.data.actions.new('%s')\n"
|
||||||
"act.use_fake_user = True\n", id.second.first.c_str());
|
"act.use_fake_user = True\n", id.second.first.c_str());
|
||||||
|
if (id.second.second.toString() == std::string("6DD5CB1DC42BFBB3"))
|
||||||
|
printf("");
|
||||||
anim.sendANIMToBlender(os, cinf);
|
anim.sendANIMToBlender(os, cinf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,12 +18,19 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
|
|||||||
bitsPerKeyFrame += 1;
|
bitsPerKeyFrame += 1;
|
||||||
case Channel::TRANSLATION:
|
case Channel::TRANSLATION:
|
||||||
case Channel::SCALE:
|
case Channel::SCALE:
|
||||||
{
|
|
||||||
bitsPerKeyFrame += chan.q[0];
|
bitsPerKeyFrame += chan.q[0];
|
||||||
bitsPerKeyFrame += chan.q[1];
|
bitsPerKeyFrame += chan.q[1];
|
||||||
bitsPerKeyFrame += chan.q[2];
|
bitsPerKeyFrame += chan.q[2];
|
||||||
break;
|
break;
|
||||||
}
|
case Channel::KF_HEAD:
|
||||||
|
bitsPerKeyFrame += 1;
|
||||||
|
break;
|
||||||
|
case Channel::ROTATION_MP3:
|
||||||
|
bitsPerKeyFrame += chan.q[0];
|
||||||
|
bitsPerKeyFrame += chan.q[1];
|
||||||
|
bitsPerKeyFrame += chan.q[2];
|
||||||
|
bitsPerKeyFrame += chan.q[3];
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,6 +50,7 @@ static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div)
|
|||||||
(quat.v4.vec[0] < 0) ? true : false
|
(quat.v4.vec[0] < 0) ? true : false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
|
static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
|
||||||
{
|
{
|
||||||
float q = M_PI / 2.0 / div;
|
float q = M_PI / 2.0 / div;
|
||||||
@ -53,7 +61,7 @@ static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
|
|||||||
sinf(v.v[1] * q),
|
sinf(v.v[1] * q),
|
||||||
sinf(v.v[2] * q),
|
sinf(v.v[2] * q),
|
||||||
};
|
};
|
||||||
retval.v4.vec[0] = sqrtf(MAX((1.0 -
|
retval.v4.vec[0] = sqrtf(std::max((1.0 -
|
||||||
(retval.v4.vec[1] * retval.v4.vec[1] +
|
(retval.v4.vec[1] * retval.v4.vec[1] +
|
||||||
retval.v4.vec[2] * retval.v4.vec[2] +
|
retval.v4.vec[2] * retval.v4.vec[2] +
|
||||||
retval.v4.vec[3] * retval.v4.vec[3])), 0.0));
|
retval.v4.vec[3] * retval.v4.vec[3])), 0.0));
|
||||||
@ -61,6 +69,19 @@ static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline Value DequantizeRotation_3(const QuantizedValue& v, atUint32 div)
|
||||||
|
{
|
||||||
|
float q = 1.0 / div;
|
||||||
|
Value retval =
|
||||||
|
{
|
||||||
|
v.v[0] * q,
|
||||||
|
v.v[1] * q,
|
||||||
|
v.v[2] * q,
|
||||||
|
v.v[3] * q
|
||||||
|
};
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
bool BitstreamReader::dequantizeBit(const atUint8* data)
|
bool BitstreamReader::dequantizeBit(const atUint8* data)
|
||||||
{
|
{
|
||||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||||
@ -144,6 +165,16 @@ BitstreamReader::read(const atUint8* data,
|
|||||||
keys.push_back({chan.i[0] / (float)rotDiv, chan.i[1] / (float)rotDiv, chan.i[2] / (float)rotDiv});
|
keys.push_back({chan.i[0] / (float)rotDiv, chan.i[1] / (float)rotDiv, chan.i[2] / (float)rotDiv});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Channel::KF_HEAD:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Channel::ROTATION_MP3:
|
||||||
|
{
|
||||||
|
QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, chan.i[0] != 0};
|
||||||
|
keys.emplace_back(DequantizeRotation(qr, rotDiv));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,6 +213,24 @@ BitstreamReader::read(const atUint8* data,
|
|||||||
kit->push_back({p[0] / (float)rotDiv, p[1] / (float)rotDiv, p[2] / (float)rotDiv});
|
kit->push_back({p[0] / (float)rotDiv, p[1] / (float)rotDiv, p[2] / (float)rotDiv});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Channel::KF_HEAD:
|
||||||
|
{
|
||||||
|
bool aBit = dequantizeBit(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Channel::ROTATION_MP3:
|
||||||
|
{
|
||||||
|
p[0] += dequantize(data, chan.q[0]);
|
||||||
|
p[1] += dequantize(data, chan.q[1]);
|
||||||
|
p[2] += dequantize(data, chan.q[2]);
|
||||||
|
p[3] += dequantize(data, chan.q[3]);
|
||||||
|
#if 0
|
||||||
|
kit->emplace_back(DequantizeRotation_3(p, rotDiv));
|
||||||
|
#else
|
||||||
|
kit->emplace_back(DequantizeRotation({p[1], p[2], p[3]}, p[0] < 0));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
++kit;
|
++kit;
|
||||||
@ -252,9 +301,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
const Value* current = &*it;
|
const Value* current = &*it;
|
||||||
maxTransDiff = MAX(maxTransDiff, current->v3.vec[0] - last->v3.vec[0]);
|
maxTransDiff = std::max(maxTransDiff, current->v3.vec[0] - last->v3.vec[0]);
|
||||||
maxTransDiff = MAX(maxTransDiff, current->v3.vec[1] - last->v3.vec[1]);
|
maxTransDiff = std::max(maxTransDiff, current->v3.vec[1] - last->v3.vec[1]);
|
||||||
maxTransDiff = MAX(maxTransDiff, current->v3.vec[2] - last->v3.vec[2]);
|
maxTransDiff = std::max(maxTransDiff, current->v3.vec[2] - last->v3.vec[2]);
|
||||||
last = current;
|
last = current;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -313,9 +362,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
|
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
|
||||||
chan.q[0] = MAX(chan.q[0], ceilf(log2f(qrCur.v[0] - qrLast.v[0])));
|
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(qrCur.v[0] - qrLast.v[0]))));
|
||||||
chan.q[1] = MAX(chan.q[1], ceilf(log2f(qrCur.v[1] - qrLast.v[1])));
|
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(qrCur.v[1] - qrLast.v[1]))));
|
||||||
chan.q[2] = MAX(chan.q[2], ceilf(log2f(qrCur.v[2] - qrLast.v[2])));
|
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(qrCur.v[2] - qrLast.v[2]))));
|
||||||
qrLast = qrCur;
|
qrLast = qrCur;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -332,9 +381,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||||||
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
|
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
|
||||||
atInt16(it->v3.vec[1] / transMultOut),
|
atInt16(it->v3.vec[1] / transMultOut),
|
||||||
atInt16(it->v3.vec[2] / transMultOut)};
|
atInt16(it->v3.vec[2] / transMultOut)};
|
||||||
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0])));
|
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
|
||||||
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1])));
|
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
|
||||||
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2])));
|
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
|
||||||
last = cur;
|
last = cur;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -351,9 +400,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||||||
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
|
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
|
||||||
atInt16(it->v3.vec[1] * rotDivOut),
|
atInt16(it->v3.vec[1] * rotDivOut),
|
||||||
atInt16(it->v3.vec[2] * rotDivOut)};
|
atInt16(it->v3.vec[2] * rotDivOut)};
|
||||||
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0])));
|
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
|
||||||
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1])));
|
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
|
||||||
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2])));
|
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
|
||||||
last = cur;
|
last = cur;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -31,7 +31,7 @@ union Value
|
|||||||
};
|
};
|
||||||
struct QuantizedValue
|
struct QuantizedValue
|
||||||
{
|
{
|
||||||
atInt16 v[3];
|
atInt16 v[4];
|
||||||
atInt16& operator[] (size_t idx)
|
atInt16& operator[] (size_t idx)
|
||||||
{return v[idx];}
|
{return v[idx];}
|
||||||
const atInt16& operator[] (size_t idx) const
|
const atInt16& operator[] (size_t idx) const
|
||||||
@ -48,10 +48,12 @@ struct Channel
|
|||||||
{
|
{
|
||||||
ROTATION,
|
ROTATION,
|
||||||
TRANSLATION,
|
TRANSLATION,
|
||||||
SCALE
|
SCALE,
|
||||||
|
KF_HEAD,
|
||||||
|
ROTATION_MP3
|
||||||
} type;
|
} type;
|
||||||
QuantizedValue i = {};
|
QuantizedValue i = {};
|
||||||
atUint8 q[3] = {};
|
atUint8 q[4] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& channels);
|
size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& channels);
|
||||||
|
@ -33,18 +33,42 @@ struct Header : BigDNA
|
|||||||
Align<32> align;
|
Align<32> align;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceHeader : BigDNA
|
struct SurfaceHeader_1_2 : BigDNA
|
||||||
{
|
{
|
||||||
DECL_DNA
|
DECL_DNA
|
||||||
Value<atVec3f> centroid;
|
Value<atVec3f> centroid;
|
||||||
Value<atUint32> matIdx;
|
Value<atUint32> matIdx;
|
||||||
Value<atInt16> qDiv;
|
Value<atInt16> qDiv;
|
||||||
Value<atUint16> dlSize;
|
Value<atUint16> dlSize;
|
||||||
Seek<8, Athena::Current> seek;
|
Value<atUint32> unk1;
|
||||||
|
Value<atUint32> unk2;
|
||||||
Value<atUint32> aabbSz;
|
Value<atUint32> aabbSz;
|
||||||
Value<atVec3f> reflectionNormal;
|
Value<atVec3f> reflectionNormal;
|
||||||
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
|
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
|
||||||
Align<32> align;
|
Align<32> align;
|
||||||
|
|
||||||
|
static constexpr bool UseMatrixSkinning() {return false;}
|
||||||
|
constexpr atInt16 skinMatrixBankIdx() const {return -1;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SurfaceHeader_3 : BigDNA
|
||||||
|
{
|
||||||
|
DECL_DNA
|
||||||
|
Value<atVec3f> centroid;
|
||||||
|
Value<atUint32> matIdx;
|
||||||
|
Value<atInt16> qDiv;
|
||||||
|
Value<atUint16> dlSize;
|
||||||
|
Value<atUint32> unk1;
|
||||||
|
Value<atUint32> unk2;
|
||||||
|
Value<atUint32> aabbSz;
|
||||||
|
Value<atVec3f> reflectionNormal;
|
||||||
|
Value<atInt16> skinMtxBankIdx;
|
||||||
|
Value<atUint16> unk3;
|
||||||
|
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
|
||||||
|
Align<32> align;
|
||||||
|
|
||||||
|
static constexpr bool UseMatrixSkinning() {return true;}
|
||||||
|
atInt16 skinMatrixBankIdx() const {return skinMtxBankIdx;}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VertexAttributes
|
struct VertexAttributes
|
||||||
@ -274,43 +298,98 @@ public:
|
|||||||
{
|
{
|
||||||
atUint16 val;
|
atUint16 val;
|
||||||
val = readVal(m_va.pnMtxIdx);
|
val = readVal(m_va.pnMtxIdx);
|
||||||
out.pnMtxIdx = MAX(out.pnMtxIdx, val);
|
out.pnMtxIdx = std::max(out.pnMtxIdx, atUint8(val));
|
||||||
val = readVal(m_va.texMtxIdx[0]);
|
val = readVal(m_va.texMtxIdx[0]);
|
||||||
out.texMtxIdx[0] = MAX(out.texMtxIdx[0], val);
|
out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val));
|
||||||
val = readVal(m_va.texMtxIdx[1]);
|
val = readVal(m_va.texMtxIdx[1]);
|
||||||
out.texMtxIdx[1] = MAX(out.texMtxIdx[1], val);
|
out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val));
|
||||||
val = readVal(m_va.texMtxIdx[2]);
|
val = readVal(m_va.texMtxIdx[2]);
|
||||||
out.texMtxIdx[2] = MAX(out.texMtxIdx[2], val);
|
out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val));
|
||||||
val = readVal(m_va.texMtxIdx[3]);
|
val = readVal(m_va.texMtxIdx[3]);
|
||||||
out.texMtxIdx[3] = MAX(out.texMtxIdx[3], val);
|
out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val));
|
||||||
val = readVal(m_va.texMtxIdx[4]);
|
val = readVal(m_va.texMtxIdx[4]);
|
||||||
out.texMtxIdx[4] = MAX(out.texMtxIdx[4], val);
|
out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val));
|
||||||
val = readVal(m_va.texMtxIdx[5]);
|
val = readVal(m_va.texMtxIdx[5]);
|
||||||
out.texMtxIdx[5] = MAX(out.texMtxIdx[5], val);
|
out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val));
|
||||||
val = readVal(m_va.texMtxIdx[6]);
|
val = readVal(m_va.texMtxIdx[6]);
|
||||||
out.texMtxIdx[6] = MAX(out.texMtxIdx[6], val);
|
out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val));
|
||||||
val = readVal(m_va.pos);
|
val = readVal(m_va.pos);
|
||||||
out.pos = MAX(out.pos, val);
|
out.pos = std::max(out.pos, val);
|
||||||
val = readVal(m_va.norm);
|
val = readVal(m_va.norm);
|
||||||
out.norm = MAX(out.norm, val);
|
out.norm = std::max(out.norm, val);
|
||||||
val = readVal(m_va.color0);
|
val = readVal(m_va.color0);
|
||||||
out.color[0] = MAX(out.color[0], val);
|
out.color[0] = std::max(out.color[0], val);
|
||||||
val = readVal(m_va.color1);
|
val = readVal(m_va.color1);
|
||||||
out.color[1] = MAX(out.color[1], val);
|
out.color[1] = std::max(out.color[1], val);
|
||||||
val = readVal(m_va.uvs[0]);
|
val = readVal(m_va.uvs[0]);
|
||||||
out.uvs[0] = MAX(out.uvs[0], val);
|
out.uvs[0] = std::max(out.uvs[0], val);
|
||||||
val = readVal(m_va.uvs[1]);
|
val = readVal(m_va.uvs[1]);
|
||||||
out.uvs[1] = MAX(out.uvs[1], val);
|
out.uvs[1] = std::max(out.uvs[1], val);
|
||||||
val = readVal(m_va.uvs[2]);
|
val = readVal(m_va.uvs[2]);
|
||||||
out.uvs[2] = MAX(out.uvs[2], val);
|
out.uvs[2] = std::max(out.uvs[2], val);
|
||||||
val = readVal(m_va.uvs[3]);
|
val = readVal(m_va.uvs[3]);
|
||||||
out.uvs[3] = MAX(out.uvs[3], val);
|
out.uvs[3] = std::max(out.uvs[3], val);
|
||||||
val = readVal(m_va.uvs[4]);
|
val = readVal(m_va.uvs[4]);
|
||||||
out.uvs[4] = MAX(out.uvs[4], val);
|
out.uvs[4] = std::max(out.uvs[4], val);
|
||||||
val = readVal(m_va.uvs[5]);
|
val = readVal(m_va.uvs[5]);
|
||||||
out.uvs[5] = MAX(out.uvs[5], val);
|
out.uvs[5] = std::max(out.uvs[5], val);
|
||||||
val = readVal(m_va.uvs[6]);
|
val = readVal(m_va.uvs[6]);
|
||||||
out.uvs[6] = MAX(out.uvs[6], val);
|
out.uvs[6] = std::max(out.uvs[6], val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_cur = bakCur;
|
||||||
|
}
|
||||||
|
void preReadMaxIdxs(DLPrimVert& out, std::vector<atInt16>& skinOut,
|
||||||
|
const atInt16 bankIn[10])
|
||||||
|
{
|
||||||
|
atUint8* bakCur = m_cur;
|
||||||
|
while (*this)
|
||||||
|
{
|
||||||
|
readPrimitive();
|
||||||
|
atUint16 vc = readVertCount();
|
||||||
|
for (atUint16 v=0 ; v<vc ; ++v)
|
||||||
|
{
|
||||||
|
atUint16 val;
|
||||||
|
atUint8 pnMtxVal = readVal(m_va.pnMtxIdx);
|
||||||
|
out.pnMtxIdx = std::max(out.pnMtxIdx, pnMtxVal);
|
||||||
|
val = readVal(m_va.texMtxIdx[0]);
|
||||||
|
out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val));
|
||||||
|
val = readVal(m_va.texMtxIdx[1]);
|
||||||
|
out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val));
|
||||||
|
val = readVal(m_va.texMtxIdx[2]);
|
||||||
|
out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val));
|
||||||
|
val = readVal(m_va.texMtxIdx[3]);
|
||||||
|
out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val));
|
||||||
|
val = readVal(m_va.texMtxIdx[4]);
|
||||||
|
out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val));
|
||||||
|
val = readVal(m_va.texMtxIdx[5]);
|
||||||
|
out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val));
|
||||||
|
val = readVal(m_va.texMtxIdx[6]);
|
||||||
|
out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val));
|
||||||
|
atUint16 posVal = readVal(m_va.pos);
|
||||||
|
out.pos = std::max(out.pos, posVal);
|
||||||
|
val = readVal(m_va.norm);
|
||||||
|
out.norm = std::max(out.norm, val);
|
||||||
|
val = readVal(m_va.color0);
|
||||||
|
out.color[0] = std::max(out.color[0], val);
|
||||||
|
val = readVal(m_va.color1);
|
||||||
|
out.color[1] = std::max(out.color[1], val);
|
||||||
|
val = readVal(m_va.uvs[0]);
|
||||||
|
out.uvs[0] = std::max(out.uvs[0], val);
|
||||||
|
val = readVal(m_va.uvs[1]);
|
||||||
|
out.uvs[1] = std::max(out.uvs[1], val);
|
||||||
|
val = readVal(m_va.uvs[2]);
|
||||||
|
out.uvs[2] = std::max(out.uvs[2], val);
|
||||||
|
val = readVal(m_va.uvs[3]);
|
||||||
|
out.uvs[3] = std::max(out.uvs[3], val);
|
||||||
|
val = readVal(m_va.uvs[4]);
|
||||||
|
out.uvs[4] = std::max(out.uvs[4], val);
|
||||||
|
val = readVal(m_va.uvs[5]);
|
||||||
|
out.uvs[5] = std::max(out.uvs[5], val);
|
||||||
|
val = readVal(m_va.uvs[6]);
|
||||||
|
out.uvs[6] = std::max(out.uvs[6], val);
|
||||||
|
|
||||||
|
skinOut[posVal] = bankIn[pnMtxVal/3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_cur = bakCur;
|
m_cur = bakCur;
|
||||||
@ -322,12 +401,12 @@ void InitGeomBlenderContext(HECL::BlenderConnection::PyOutStream& os,
|
|||||||
void FinishBlenderMesh(HECL::BlenderConnection::PyOutStream& os,
|
void FinishBlenderMesh(HECL::BlenderConnection::PyOutStream& os,
|
||||||
unsigned matSetCount, int meshIdx);
|
unsigned matSetCount, int meshIdx);
|
||||||
|
|
||||||
template <class PAKRouter, class MaterialSet, class RIGPAIR>
|
template <class PAKRouter, class MaterialSet, class RigPair, class SurfaceHeader>
|
||||||
atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
||||||
Athena::io::IStreamReader& reader,
|
Athena::io::IStreamReader& reader,
|
||||||
PAKRouter& pakRouter,
|
PAKRouter& pakRouter,
|
||||||
const typename PAKRouter::EntryType& entry,
|
const typename PAKRouter::EntryType& entry,
|
||||||
const RIGPAIR& rp,
|
const RigPair& rp,
|
||||||
bool shortNormals,
|
bool shortNormals,
|
||||||
bool shortUVs,
|
bool shortUVs,
|
||||||
std::vector<VertexAttributes>& vertAttribs,
|
std::vector<VertexAttributes>& vertAttribs,
|
||||||
@ -357,6 +436,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||||||
atUint32 lastDlSec = secCount;
|
atUint32 lastDlSec = secCount;
|
||||||
atUint64 afterHeaderPos = reader.position();
|
atUint64 afterHeaderPos = reader.position();
|
||||||
DLReader::DLPrimVert maxIdxs;
|
DLReader::DLPrimVert maxIdxs;
|
||||||
|
std::vector<atInt16> skinIndices;
|
||||||
for (size_t s=0 ; s<lastDlSec ; ++s)
|
for (size_t s=0 ; s<lastDlSec ; ++s)
|
||||||
{
|
{
|
||||||
atUint64 secStart = reader.position();
|
atUint64 secStart = reader.position();
|
||||||
@ -376,6 +456,8 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
/* Positions */
|
/* Positions */
|
||||||
|
if (SurfaceHeader::UseMatrixSkinning() && rp.first)
|
||||||
|
skinIndices.assign(secSizes[s] / 12, -1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
@ -429,6 +511,9 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||||||
/* Do max index pre-read */
|
/* Do max index pre-read */
|
||||||
atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
|
atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
|
||||||
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
|
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
|
||||||
|
if (SurfaceHeader::UseMatrixSkinning() && rp.first)
|
||||||
|
dl.preReadMaxIdxs(maxIdxs, skinIndices, rp.first->getMatrixBank(sHead.skinMatrixBankIdx()));
|
||||||
|
else
|
||||||
dl.preReadMaxIdxs(maxIdxs);
|
dl.preReadMaxIdxs(maxIdxs);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -469,8 +554,13 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||||||
os.format("vert = bm.verts.new((%f,%f,%f))\n",
|
os.format("vert = bm.verts.new((%f,%f,%f))\n",
|
||||||
pos.vec[0], pos.vec[1], pos.vec[2]);
|
pos.vec[0], pos.vec[1], pos.vec[2]);
|
||||||
if (rp.first)
|
if (rp.first)
|
||||||
|
{
|
||||||
|
if (SurfaceHeader::UseMatrixSkinning())
|
||||||
|
rp.first->weightVertex(os, *rp.second, skinIndices[i]);
|
||||||
|
else
|
||||||
rp.first->weightVertex(os, *rp.second, i);
|
rp.first->weightVertex(os, *rp.second, i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
@ -784,13 +874,13 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||||||
return lastDlSec;
|
return lastDlSec;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class PAKRouter, class MaterialSet, class RIGPAIR, atUint32 Version>
|
template <class PAKRouter, class MaterialSet, class RigPair, class SurfaceHeader, atUint32 Version>
|
||||||
bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
|
bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
|
||||||
Athena::io::IStreamReader& reader,
|
Athena::io::IStreamReader& reader,
|
||||||
PAKRouter& pakRouter,
|
PAKRouter& pakRouter,
|
||||||
const typename PAKRouter::EntryType& entry,
|
const typename PAKRouter::EntryType& entry,
|
||||||
const SpecBase& dataspec,
|
const SpecBase& dataspec,
|
||||||
const RIGPAIR& rp)
|
const RigPair& rp)
|
||||||
{
|
{
|
||||||
Header head;
|
Header head;
|
||||||
head.read(reader);
|
head.read(reader);
|
||||||
@ -824,7 +914,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
|
|||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
std::vector<VertexAttributes> vertAttribs;
|
std::vector<VertexAttributes> vertAttribs;
|
||||||
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RIGPAIR>
|
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader>
|
||||||
(os, reader, pakRouter, entry, rp, head.flags.shortNormals(),
|
(os, reader, pakRouter, entry, rp, head.flags.shortNormals(),
|
||||||
head.flags.shortUVs(), vertAttribs, -1,
|
head.flags.shortUVs(), vertAttribs, -1,
|
||||||
head.secCount, head.matSetCount, head.secSizes.data());
|
head.secCount, head.matSetCount, head.secSizes.data());
|
||||||
|
@ -322,8 +322,8 @@ void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader)
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
cmdlOverride.read(reader);
|
cmdlOverlay.read(reader);
|
||||||
cskrOverride.read(reader);
|
cskrOverlay.read(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
animIdxs.clear();
|
animIdxs.clear();
|
||||||
@ -343,7 +343,7 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
|
|||||||
sectionCount = 6;
|
sectionCount = 6;
|
||||||
else if (animIdxs.size())
|
else if (animIdxs.size())
|
||||||
sectionCount = 5;
|
sectionCount = 5;
|
||||||
else if (cmdlOverride)
|
else if (cmdlOverlay)
|
||||||
sectionCount = 4;
|
sectionCount = 4;
|
||||||
else if (effects.size())
|
else if (effects.size())
|
||||||
sectionCount = 3;
|
sectionCount = 3;
|
||||||
@ -394,8 +394,8 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
cmdlOverride.write(writer);
|
cmdlOverlay.write(writer);
|
||||||
cskrOverride.write(writer);
|
cskrOverlay.write(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectionCount > 4)
|
if (sectionCount > 4)
|
||||||
@ -454,8 +454,8 @@ void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& read
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
reader.enumerate("cmdlOverride", cmdlOverride);
|
reader.enumerate("cmdlOverride", cmdlOverlay);
|
||||||
reader.enumerate("cskrOverride", cskrOverride);
|
reader.enumerate("cskrOverride", cskrOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
animIdxs.clear();
|
animIdxs.clear();
|
||||||
@ -475,7 +475,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
|
|||||||
sectionCount = 6;
|
sectionCount = 6;
|
||||||
else if (animIdxs.size())
|
else if (animIdxs.size())
|
||||||
sectionCount = 5;
|
sectionCount = 5;
|
||||||
else if (cmdlOverride)
|
else if (cmdlOverlay)
|
||||||
sectionCount = 4;
|
sectionCount = 4;
|
||||||
else if (effects.size())
|
else if (effects.size())
|
||||||
sectionCount = 3;
|
sectionCount = 3;
|
||||||
@ -526,8 +526,8 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
writer.enumerate("cmdlOverride", cmdlOverride);
|
writer.enumerate("cmdlOverride", cmdlOverlay);
|
||||||
writer.enumerate("cskrOverride", cskrOverride);
|
writer.enumerate("cskrOverride", cskrOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectionCount > 4)
|
if (sectionCount > 4)
|
||||||
|
@ -141,8 +141,8 @@ struct ANCS : BigYAML
|
|||||||
};
|
};
|
||||||
std::vector<Effect> effects;
|
std::vector<Effect> effects;
|
||||||
|
|
||||||
UniqueID32 cmdlOverride;
|
UniqueID32 cmdlOverlay;
|
||||||
UniqueID32 cskrOverride;
|
UniqueID32 cskrOverlay;
|
||||||
|
|
||||||
std::vector<atUint32> animIdxs;
|
std::vector<atUint32> animIdxs;
|
||||||
};
|
};
|
||||||
@ -401,7 +401,7 @@ struct ANCS : BigYAML
|
|||||||
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
||||||
{
|
{
|
||||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2>
|
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1_2, 2>
|
||||||
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
|||||||
|
|
||||||
atUint32 maxId = 0;
|
atUint32 maxId = 0;
|
||||||
for (const std::pair<atUint32, bool>& bone : bones)
|
for (const std::pair<atUint32, bool>& bone : bones)
|
||||||
maxId = MAX(maxId, bone.first);
|
maxId = std::max(maxId, bone.first);
|
||||||
head.boneSlotCount = maxId + 1;
|
head.boneSlotCount = maxId + 1;
|
||||||
head.write(writer);
|
head.write(writer);
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||||||
bones.reserve(head.boneChannelCount);
|
bones.reserve(head.boneChannelCount);
|
||||||
channels.clear();
|
channels.clear();
|
||||||
channels.reserve(head.boneChannelCount);
|
channels.reserve(head.boneChannelCount);
|
||||||
size_t keyframeCount = 0;
|
atUint16 keyframeCount = 0;
|
||||||
for (size_t b=0 ; b<head.boneChannelCount ; ++b)
|
for (size_t b=0 ; b<head.boneChannelCount ; ++b)
|
||||||
{
|
{
|
||||||
ChannelDesc desc;
|
ChannelDesc desc;
|
||||||
@ -258,7 +258,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||||||
chan.i[2] = desc.initRZ;
|
chan.i[2] = desc.initRZ;
|
||||||
chan.q[2] = desc.qRZ;
|
chan.q[2] = desc.qRZ;
|
||||||
}
|
}
|
||||||
keyframeCount = MAX(keyframeCount, desc.keyCount1);
|
keyframeCount = std::max(keyframeCount, desc.keyCount1);
|
||||||
|
|
||||||
if (desc.keyCount2)
|
if (desc.keyCount2)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,7 @@ struct CMDL
|
|||||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||||
if (!conn.createBlend(outPath.getAbsolutePath()))
|
if (!conn.createBlend(outPath.getAbsolutePath()))
|
||||||
return false;
|
return false;
|
||||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 2>
|
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_1_2, 2>
|
||||||
(conn, rs, pakRouter, entry, dataSpec, loadRp);
|
(conn, rs, pakRouter, entry, dataSpec, loadRp);
|
||||||
return conn.saveBlend();
|
return conn.saveBlend();
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@ struct CSKR : BigDNA
|
|||||||
};
|
};
|
||||||
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
|
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
|
||||||
|
|
||||||
|
const atInt16* getMatrixBank(size_t) const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
||||||
{
|
{
|
||||||
atUint32 accum = 0;
|
atUint32 accum = 0;
|
||||||
|
@ -188,7 +188,11 @@ void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueI
|
|||||||
ANCS ancs;
|
ANCS ancs;
|
||||||
ancs.read(rs);
|
ancs.read(rs);
|
||||||
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
|
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
|
||||||
|
{
|
||||||
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
|
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
|
||||||
|
if (ci.cmdlOverlay)
|
||||||
|
addTo[ci.cmdlOverlay] = std::make_pair(ci.cskrOverlay, ci.cinf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
|
|||||||
secStart = rs.position();
|
secStart = rs.position();
|
||||||
mHeader.read(rs);
|
mHeader.read(rs);
|
||||||
rs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
|
rs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
|
||||||
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair>
|
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_1_2>
|
||||||
(os, rs, pakRouter, entry, dummy, true,
|
(os, rs, pakRouter, entry, dummy, true,
|
||||||
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
|
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
|
||||||
os.format("obj.retro_disable_enviro_visor = %s\n"
|
os.format("obj.retro_disable_enviro_visor = %s\n"
|
||||||
|
@ -95,7 +95,7 @@ PAK::Entry::getBuffer(const NOD::DiscBase::IPartition::Node& pak, atUint64& szOu
|
|||||||
zs.next_out = buf;
|
zs.next_out = buf;
|
||||||
while (zs.avail_out)
|
while (zs.avail_out)
|
||||||
{
|
{
|
||||||
atUint64 readSz = strm->read(compBuf, MIN(compRem, 0x8000));
|
atUint64 readSz = strm->read(compBuf, std::min(compRem, atUint32(0x8000)));
|
||||||
compRem -= readSz;
|
compRem -= readSz;
|
||||||
zs.avail_in = readSz;
|
zs.avail_in = readSz;
|
||||||
zs.next_in = compBuf;
|
zs.next_in = compBuf;
|
||||||
|
@ -57,8 +57,8 @@ void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader)
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
cmdlOverride.read(reader);
|
cmdlOverlay.read(reader);
|
||||||
cskrOverride.read(reader);
|
cskrOverley.read(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
animIdxs.clear();
|
animIdxs.clear();
|
||||||
@ -89,7 +89,7 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
|
|||||||
sectionCount = 6;
|
sectionCount = 6;
|
||||||
else if (animIdxs.size())
|
else if (animIdxs.size())
|
||||||
sectionCount = 5;
|
sectionCount = 5;
|
||||||
else if (cmdlOverride)
|
else if (cmdlOverlay)
|
||||||
sectionCount = 4;
|
sectionCount = 4;
|
||||||
else if (effects.size())
|
else if (effects.size())
|
||||||
sectionCount = 3;
|
sectionCount = 3;
|
||||||
@ -143,8 +143,8 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
cmdlOverride.write(writer);
|
cmdlOverlay.write(writer);
|
||||||
cskrOverride.write(writer);
|
cskrOverley.write(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectionCount > 4)
|
if (sectionCount > 4)
|
||||||
@ -213,8 +213,8 @@ void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& read
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
reader.enumerate("cmdlOverride", cmdlOverride);
|
reader.enumerate("cmdlOverride", cmdlOverlay);
|
||||||
reader.enumerate("cskrOverride", cskrOverride);
|
reader.enumerate("cskrOverride", cskrOverley);
|
||||||
}
|
}
|
||||||
|
|
||||||
animIdxs.clear();
|
animIdxs.clear();
|
||||||
@ -245,7 +245,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
|
|||||||
sectionCount = 6;
|
sectionCount = 6;
|
||||||
else if (animIdxs.size())
|
else if (animIdxs.size())
|
||||||
sectionCount = 5;
|
sectionCount = 5;
|
||||||
else if (cmdlOverride)
|
else if (cmdlOverlay)
|
||||||
sectionCount = 4;
|
sectionCount = 4;
|
||||||
else if (effects.size())
|
else if (effects.size())
|
||||||
sectionCount = 3;
|
sectionCount = 3;
|
||||||
@ -299,8 +299,8 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
|
|||||||
|
|
||||||
if (sectionCount > 3)
|
if (sectionCount > 3)
|
||||||
{
|
{
|
||||||
writer.enumerate("cmdlOverride", cmdlOverride);
|
writer.enumerate("cmdlOverride", cmdlOverlay);
|
||||||
writer.enumerate("cskrOverride", cskrOverride);
|
writer.enumerate("cskrOverride", cskrOverley);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectionCount > 4)
|
if (sectionCount > 4)
|
||||||
|
@ -85,8 +85,8 @@ struct ANCS : BigYAML
|
|||||||
};
|
};
|
||||||
std::vector<Effect> effects;
|
std::vector<Effect> effects;
|
||||||
|
|
||||||
UniqueID32 cmdlOverride;
|
UniqueID32 cmdlOverlay;
|
||||||
UniqueID32 cskrOverride;
|
UniqueID32 cskrOverley;
|
||||||
|
|
||||||
std::vector<atUint32> animIdxs;
|
std::vector<atUint32> animIdxs;
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ struct ANCS : BigYAML
|
|||||||
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
||||||
{
|
{
|
||||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4>
|
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1_2, 4>
|
||||||
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
|||||||
|
|
||||||
atUint32 maxId = 0;
|
atUint32 maxId = 0;
|
||||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||||
maxId = MAX(maxId, bone.first);
|
maxId = std::max(maxId, bone.first);
|
||||||
head.boneSlotCount = maxId + 1;
|
head.boneSlotCount = maxId + 1;
|
||||||
head.write(writer);
|
head.write(writer);
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||||||
bones.reserve(head.boneChannelCount);
|
bones.reserve(head.boneChannelCount);
|
||||||
channels.clear();
|
channels.clear();
|
||||||
channels.reserve(head.boneChannelCount);
|
channels.reserve(head.boneChannelCount);
|
||||||
size_t keyframeCount = 0;
|
atUint16 keyframeCount = 0;
|
||||||
for (size_t b=0 ; b<head.boneChannelCount ; ++b)
|
for (size_t b=0 ; b<head.boneChannelCount ; ++b)
|
||||||
{
|
{
|
||||||
ChannelDesc desc;
|
ChannelDesc desc;
|
||||||
@ -387,7 +387,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||||||
chan.i[2] = desc.initRZ;
|
chan.i[2] = desc.initRZ;
|
||||||
chan.q[2] = desc.qRZ;
|
chan.q[2] = desc.qRZ;
|
||||||
}
|
}
|
||||||
keyframeCount = MAX(keyframeCount, desc.keyCount1);
|
keyframeCount = std::max(keyframeCount, desc.keyCount1);
|
||||||
|
|
||||||
if (desc.keyCount2)
|
if (desc.keyCount2)
|
||||||
{
|
{
|
||||||
@ -401,7 +401,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||||||
chan.i[2] = desc.initTZ;
|
chan.i[2] = desc.initTZ;
|
||||||
chan.q[2] = desc.qTZ;
|
chan.q[2] = desc.qTZ;
|
||||||
}
|
}
|
||||||
keyframeCount = MAX(keyframeCount, desc.keyCount2);
|
keyframeCount = std::max(keyframeCount, desc.keyCount2);
|
||||||
|
|
||||||
if (desc.keyCount3)
|
if (desc.keyCount3)
|
||||||
{
|
{
|
||||||
@ -415,7 +415,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||||||
chan.i[2] = desc.initSZ;
|
chan.i[2] = desc.initSZ;
|
||||||
chan.q[2] = desc.qSZ;
|
chan.q[2] = desc.qSZ;
|
||||||
}
|
}
|
||||||
keyframeCount = MAX(keyframeCount, desc.keyCount3);
|
keyframeCount = std::max(keyframeCount, desc.keyCount3);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
|
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
|
||||||
|
@ -40,7 +40,7 @@ struct CMDL
|
|||||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||||
if (!conn.createBlend(outPath.getAbsolutePath()))
|
if (!conn.createBlend(outPath.getAbsolutePath()))
|
||||||
return false;
|
return false;
|
||||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 4>
|
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_1_2, 4>
|
||||||
(conn, rs, pakRouter, entry, dataSpec, loadRp);
|
(conn, rs, pakRouter, entry, dataSpec, loadRp);
|
||||||
return conn.saveBlend();
|
return conn.saveBlend();
|
||||||
}
|
}
|
||||||
|
@ -4,30 +4,21 @@
|
|||||||
#include "BlenderConnection.hpp"
|
#include "BlenderConnection.hpp"
|
||||||
#include "../DNACommon/DNACommon.hpp"
|
#include "../DNACommon/DNACommon.hpp"
|
||||||
#include "CINF.hpp"
|
#include "CINF.hpp"
|
||||||
|
#include "../DNAMP1/CSKR.hpp"
|
||||||
|
|
||||||
namespace Retro
|
namespace Retro
|
||||||
{
|
{
|
||||||
namespace DNAMP2
|
namespace DNAMP2
|
||||||
{
|
{
|
||||||
|
|
||||||
struct CSKR : BigDNA
|
struct CSKR : DNAMP1::CSKR
|
||||||
{
|
{
|
||||||
DECL_DNA
|
Delete expl;
|
||||||
Value<atUint32> skinningRuleCount;
|
|
||||||
struct SkinningRule : BigDNA
|
const atInt16* getMatrixBank(size_t) const
|
||||||
{
|
{
|
||||||
DECL_DNA
|
return nullptr;
|
||||||
Value<atUint32> weightCount;
|
}
|
||||||
struct Weight : BigDNA
|
|
||||||
{
|
|
||||||
DECL_DNA
|
|
||||||
Value<atUint32> boneId;
|
|
||||||
Value<float> weight;
|
|
||||||
};
|
|
||||||
Vector<Weight, DNA_COUNT(weightCount)> weights;
|
|
||||||
Value<atUint32> vertCount;
|
|
||||||
};
|
|
||||||
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
|
|
||||||
|
|
||||||
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
||||||
{
|
{
|
||||||
|
@ -193,7 +193,11 @@ void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueI
|
|||||||
ANCS ancs;
|
ANCS ancs;
|
||||||
ancs.read(rs);
|
ancs.read(rs);
|
||||||
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
|
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
|
||||||
|
{
|
||||||
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
|
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
|
||||||
|
if (ci.cmdlOverlay)
|
||||||
|
addTo[ci.cmdlOverlay] = std::make_pair(ci.cskrOverley, ci.cinf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
|
|||||||
secStart = drs.position();
|
secStart = drs.position();
|
||||||
mHeader.read(drs);
|
mHeader.read(drs);
|
||||||
drs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
|
drs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
|
||||||
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair>
|
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_1_2>
|
||||||
(os, drs, pakRouter, entry, dummy, true,
|
(os, drs, pakRouter, entry, dummy, true,
|
||||||
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
|
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
|
||||||
os.format("obj.retro_disable_enviro_visor = %s\n"
|
os.format("obj.retro_disable_enviro_visor = %s\n"
|
||||||
|
@ -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
|
DECL_EXPLICIT_DNA
|
||||||
ANIM2() : IANIM(2) {}
|
ANIM1() : IANIM(1) {}
|
||||||
|
|
||||||
struct Header : BigDNA
|
struct Header : BigDNA
|
||||||
{
|
{
|
||||||
DECL_DNA
|
DECL_DNA
|
||||||
Value<atUint32> scratchSize;
|
Value<atUint16> unk1;
|
||||||
Value<atUint8> unk1;
|
|
||||||
Value<atUint8> unk2;
|
Value<atUint8> unk2;
|
||||||
Value<float> duration;
|
|
||||||
Value<float> interval;
|
|
||||||
Value<atUint32> unk3;
|
Value<atUint32> unk3;
|
||||||
Value<atUint32> unk4;
|
Value<atUint8> unk4[3];
|
||||||
Value<atUint32> rotDiv;
|
|
||||||
Value<float> translationMult;
|
Value<float> translationMult;
|
||||||
Value<atUint32> unk5;
|
|
||||||
Value<atUint32> boneChannelCount;
|
|
||||||
Value<atUint32> unk6;
|
Value<atUint32> unk6;
|
||||||
Value<atUint32> keyBitmapBitCount;
|
Value<atUint32> unk7;
|
||||||
};
|
Value<float> unk8;
|
||||||
|
Value<float> unk9;
|
||||||
struct ChannelDesc : BigDNA
|
Value<float> duration;
|
||||||
{
|
Value<atUint16> keyCount;
|
||||||
Delete expl;
|
Value<atUint32> blobSize;
|
||||||
Value<atUint8> id = 0;
|
Value<atUint8> unk10;
|
||||||
Value<atUint16> keyCount1 = 0;
|
Value<atUint32> floatsSize;
|
||||||
Value<atUint16> initRX = 0;
|
Value<atUint32> flagsSize;
|
||||||
Value<atUint8> qRX = 0;
|
Value<atUint32> initBlockSize;
|
||||||
Value<atUint16> initRY = 0;
|
Value<atUint32> streamSize;
|
||||||
Value<atUint8> qRY = 0;
|
Value<atUint32> unk11;
|
||||||
Value<atUint16> initRZ = 0;
|
Value<atUint32> boneCount;
|
||||||
Value<atUint8> qRZ = 0;
|
|
||||||
Value<atUint16> keyCount2 = 0;
|
|
||||||
Value<atUint16> initTX = 0;
|
|
||||||
Value<atUint8> qTX = 0;
|
|
||||||
Value<atUint16> initTY = 0;
|
|
||||||
Value<atUint8> qTY = 0;
|
|
||||||
Value<atUint16> initTZ = 0;
|
|
||||||
Value<atUint8> qTZ = 0;
|
|
||||||
Value<atUint16> keyCount3 = 0;
|
|
||||||
Value<atUint16> initSX = 0;
|
|
||||||
Value<atUint8> qSX = 0;
|
|
||||||
Value<atUint16> initSY = 0;
|
|
||||||
Value<atUint8> qSY = 0;
|
|
||||||
Value<atUint16> initSZ = 0;
|
|
||||||
Value<atUint8> qSZ = 0;
|
|
||||||
|
|
||||||
void read(Athena::io::IStreamReader& reader)
|
|
||||||
{
|
|
||||||
id = reader.readUByte();
|
|
||||||
keyCount1 = reader.readUint16Big();
|
|
||||||
if (keyCount1)
|
|
||||||
{
|
|
||||||
initRX = reader.readUint16Big();
|
|
||||||
qRX = reader.readUByte();
|
|
||||||
initRY = reader.readUint16Big();
|
|
||||||
qRY = reader.readUByte();
|
|
||||||
initRZ = reader.readUint16Big();
|
|
||||||
qRZ = reader.readUByte();
|
|
||||||
}
|
|
||||||
keyCount2 = reader.readUint16Big();
|
|
||||||
if (keyCount2)
|
|
||||||
{
|
|
||||||
initTX = reader.readUint16Big();
|
|
||||||
qTX = reader.readUByte();
|
|
||||||
initTY = reader.readUint16Big();
|
|
||||||
qTY = reader.readUByte();
|
|
||||||
initTZ = reader.readUint16Big();
|
|
||||||
qTZ = reader.readUByte();
|
|
||||||
}
|
|
||||||
keyCount3 = reader.readUint16Big();
|
|
||||||
if (keyCount3)
|
|
||||||
{
|
|
||||||
initSX = reader.readUint16Big();
|
|
||||||
qSX = reader.readUByte();
|
|
||||||
initSY = reader.readUint16Big();
|
|
||||||
qSY = reader.readUByte();
|
|
||||||
initSZ = reader.readUint16Big();
|
|
||||||
qSZ = reader.readUByte();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void write(Athena::io::IStreamWriter& writer) const
|
|
||||||
{
|
|
||||||
writer.writeUByte(id);
|
|
||||||
writer.writeUint16Big(keyCount1);
|
|
||||||
if (keyCount1)
|
|
||||||
{
|
|
||||||
writer.writeUint16Big(initRX);
|
|
||||||
writer.writeUByte(qRX);
|
|
||||||
writer.writeUint16Big(initRY);
|
|
||||||
writer.writeUByte(qRY);
|
|
||||||
writer.writeUint16Big(initRZ);
|
|
||||||
writer.writeUByte(qRZ);
|
|
||||||
}
|
|
||||||
writer.writeUint16Big(keyCount2);
|
|
||||||
if (keyCount2)
|
|
||||||
{
|
|
||||||
writer.writeUint16Big(initTX);
|
|
||||||
writer.writeUByte(qTX);
|
|
||||||
writer.writeUint16Big(initTY);
|
|
||||||
writer.writeUByte(qTY);
|
|
||||||
writer.writeUint16Big(initTZ);
|
|
||||||
writer.writeUByte(qTZ);
|
|
||||||
}
|
|
||||||
writer.writeUint16Big(keyCount3);
|
|
||||||
if (keyCount3)
|
|
||||||
{
|
|
||||||
writer.writeUint16Big(initSX);
|
|
||||||
writer.writeUByte(qSX);
|
|
||||||
writer.writeUint16Big(initSY);
|
|
||||||
writer.writeUByte(qSY);
|
|
||||||
writer.writeUint16Big(initSZ);
|
|
||||||
writer.writeUByte(qSZ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -178,8 +88,8 @@ struct ANIM : BigDNA
|
|||||||
m_anim.reset(new struct ANIM0);
|
m_anim.reset(new struct ANIM0);
|
||||||
m_anim->read(reader);
|
m_anim->read(reader);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 1:
|
||||||
m_anim.reset(new struct ANIM2);
|
m_anim.reset(new struct ANIM1);
|
||||||
m_anim->read(reader);
|
m_anim->read(reader);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -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;
|
using ANIMType = ANIM;
|
||||||
|
|
||||||
DECL_YAML
|
DECL_YAML
|
||||||
Delete expl;
|
Value<atUint16> version;
|
||||||
atUint16 version;
|
|
||||||
|
|
||||||
std::string name;
|
struct CharacterInfo : BigYAML
|
||||||
|
{
|
||||||
|
DECL_YAML
|
||||||
|
String<-1> name;
|
||||||
UniqueID64 cmdl;
|
UniqueID64 cmdl;
|
||||||
UniqueID64 cskr;
|
UniqueID64 cskr;
|
||||||
atUint32 unk1;
|
Value<atUint32> overlayCount;
|
||||||
atUint32 unk2;
|
struct Overlay : BigYAML
|
||||||
UniqueID64 cmdl2;
|
{
|
||||||
UniqueID64 cskr2;
|
DECL_YAML
|
||||||
|
DNAFourCC type;
|
||||||
|
UniqueID64 cmdl;
|
||||||
|
UniqueID64 cskr;
|
||||||
|
};
|
||||||
|
Vector<Overlay, DNA_COUNT(overlayCount)> overlays;
|
||||||
UniqueID64 cinf;
|
UniqueID64 cinf;
|
||||||
UniqueID64 sand;
|
UniqueID64 sand;
|
||||||
|
|
||||||
using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo;
|
using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo;
|
||||||
MP1CharacterInfo::PASDatabase pasDatabase;
|
MP1CharacterInfo::PASDatabase pasDatabase;
|
||||||
|
|
||||||
struct ParticleResData
|
struct ParticleResData : BigYAML
|
||||||
{
|
{
|
||||||
std::vector<UniqueID64> part;
|
DECL_YAML
|
||||||
std::vector<UniqueID64> swhc;
|
Value<atUint32> partCount;
|
||||||
std::vector<UniqueID64> unk;
|
Vector<UniqueID64, DNA_COUNT(partCount)> part;
|
||||||
std::vector<UniqueID64> elsc;
|
Value<atUint32> swhcCount;
|
||||||
std::vector<UniqueID64> spsc;
|
Vector<UniqueID64, DNA_COUNT(swhcCount)> swhc;
|
||||||
std::vector<UniqueID64> unk2;
|
Value<atUint32> unkCount;
|
||||||
|
Vector<UniqueID64, DNA_COUNT(unkCount)> unk;
|
||||||
|
Value<atUint32> elscCount;
|
||||||
|
Vector<UniqueID64, DNA_COUNT(elscCount)> elsc;
|
||||||
|
Value<atUint32> spscCount;
|
||||||
|
Vector<UniqueID64, DNA_COUNT(spscCount)> spsc;
|
||||||
|
Value<atUint32> unk2Count;
|
||||||
|
Vector<UniqueID64, DNA_COUNT(unk2Count)> unk2;
|
||||||
} partResData;
|
} partResData;
|
||||||
|
|
||||||
struct AnimationSet : BigYAML
|
} characterInfo;
|
||||||
|
|
||||||
|
struct AnimationInfo : BigYAML
|
||||||
|
{
|
||||||
|
DECL_YAML
|
||||||
|
|
||||||
|
struct EVNT : BigYAML
|
||||||
|
{
|
||||||
|
DECL_YAML
|
||||||
|
Value<atUint32> eventBinding;
|
||||||
|
String<-1> eventName;
|
||||||
|
|
||||||
|
struct EventBase : BigYAML
|
||||||
|
{
|
||||||
|
DECL_YAML
|
||||||
|
String<-1> name1;
|
||||||
|
Value<atUint16> unk0;
|
||||||
|
String<-1> name2;
|
||||||
|
Value<atUint16> type;
|
||||||
|
Value<atUint32> unk1;
|
||||||
|
Value<atUint32> unk2;
|
||||||
|
Value<atUint32> unk3;
|
||||||
|
Value<atUint32> unk4;
|
||||||
|
Value<atUint8> unk5;
|
||||||
|
Value<float> unk6;
|
||||||
|
Value<atUint32> unk7;
|
||||||
|
Value<atUint32> unk8;
|
||||||
|
Value<atUint32> unk9;
|
||||||
|
Value<atUint32> unk10;
|
||||||
|
Value<atUint32> unk11;
|
||||||
|
Value<atUint32> unk12;
|
||||||
|
Value<atUint32> unk13;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EffectEvent : EventBase
|
||||||
|
{
|
||||||
|
DECL_YAML
|
||||||
|
DNAFourCC effectType;
|
||||||
|
UniqueID64 effectId;
|
||||||
|
Value<float> scale;
|
||||||
|
Value<atUint32> parentMode;
|
||||||
|
};
|
||||||
|
Value<atUint32> effectCount;
|
||||||
|
Vector<EffectEvent, DNA_COUNT(effectCount)> effectEvents;
|
||||||
|
|
||||||
|
struct SFXEvent : EventBase
|
||||||
{
|
{
|
||||||
DECL_YAML
|
DECL_YAML
|
||||||
Delete expl;
|
Delete expl;
|
||||||
|
|
||||||
|
UniqueID64 caudId;
|
||||||
|
Value<atUint32> unk1;
|
||||||
|
Value<atUint32> unk2;
|
||||||
|
Value<atUint32> unk3;
|
||||||
|
Value<atUint32> extraType;
|
||||||
|
Value<float> extraFloat;
|
||||||
|
};
|
||||||
|
Value<atUint32> sfxCount;
|
||||||
|
Vector<SFXEvent, DNA_COUNT(sfxCount)> sfxEvents;
|
||||||
|
};
|
||||||
|
Value<atUint32> evntCount;
|
||||||
|
Vector<EVNT, DNA_COUNT(evntCount)> evnts;
|
||||||
|
|
||||||
struct IMetaAnim : BigYAML
|
struct IMetaAnim : BigYAML
|
||||||
{
|
{
|
||||||
Delete expl;
|
Delete expl;
|
||||||
@ -160,94 +232,8 @@ struct CHAR : BigYAML
|
|||||||
String<-1> name;
|
String<-1> name;
|
||||||
MetaAnimFactory metaAnim;
|
MetaAnimFactory metaAnim;
|
||||||
};
|
};
|
||||||
std::vector<Animation> animations;
|
Value<atUint32> animationCount;
|
||||||
|
Vector<Animation, DNA_COUNT(animationCount)> animations;
|
||||||
struct IMetaTrans : BigYAML
|
|
||||||
{
|
|
||||||
Delete expl;
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
MTMetaAnim = 0,
|
|
||||||
MTTrans = 1,
|
|
||||||
MTPhaseTrans = 2,
|
|
||||||
MTNoTrans = 3,
|
|
||||||
} m_type;
|
|
||||||
const char* m_typeStr;
|
|
||||||
IMetaTrans(Type type, const char* typeStr)
|
|
||||||
: m_type(type), m_typeStr(typeStr) {}
|
|
||||||
};
|
|
||||||
struct MetaTransFactory : BigYAML
|
|
||||||
{
|
|
||||||
DECL_YAML
|
|
||||||
Delete expl;
|
|
||||||
std::unique_ptr<IMetaTrans> m_trans;
|
|
||||||
};
|
|
||||||
struct MetaTransMetaAnim : IMetaTrans
|
|
||||||
{
|
|
||||||
MetaTransMetaAnim() : IMetaTrans(MTMetaAnim, "MetaAnim") {}
|
|
||||||
DECL_YAML
|
|
||||||
MetaAnimFactory anim;
|
|
||||||
};
|
|
||||||
struct MetaTransTrans : IMetaTrans
|
|
||||||
{
|
|
||||||
MetaTransTrans() : IMetaTrans(MTTrans, "Trans") {}
|
|
||||||
DECL_YAML
|
|
||||||
Value<float> time;
|
|
||||||
Value<atUint32> unk1;
|
|
||||||
Value<atUint8> unk2;
|
|
||||||
Value<atUint8> unk3;
|
|
||||||
Value<atUint32> unk4;
|
|
||||||
};
|
|
||||||
struct MetaTransPhaseTrans : IMetaTrans
|
|
||||||
{
|
|
||||||
MetaTransPhaseTrans() : IMetaTrans(MTPhaseTrans, "PhaseTrans") {}
|
|
||||||
DECL_YAML
|
|
||||||
Value<float> time;
|
|
||||||
Value<atUint32> unk1;
|
|
||||||
Value<atUint8> unk2;
|
|
||||||
Value<atUint8> unk3;
|
|
||||||
Value<atUint32> unk4;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Transition : BigYAML
|
|
||||||
{
|
|
||||||
DECL_YAML
|
|
||||||
Value<atUint32> unk;
|
|
||||||
Value<atUint32> animIdxA;
|
|
||||||
Value<atUint32> animIdxB;
|
|
||||||
MetaTransFactory metaTrans;
|
|
||||||
};
|
|
||||||
std::vector<Transition> transitions;
|
|
||||||
MetaTransFactory defaultTransition;
|
|
||||||
|
|
||||||
struct AdditiveAnimationInfo : BigYAML
|
|
||||||
{
|
|
||||||
DECL_YAML
|
|
||||||
Value<atUint32> animIdx;
|
|
||||||
Value<float> unk1;
|
|
||||||
Value<float> unk2;
|
|
||||||
};
|
|
||||||
std::vector<AdditiveAnimationInfo> additiveAnims;
|
|
||||||
|
|
||||||
float floatA = 0.0;
|
|
||||||
float floatB = 0.0;
|
|
||||||
|
|
||||||
struct HalfTransition : BigYAML
|
|
||||||
{
|
|
||||||
DECL_YAML
|
|
||||||
Value<atUint32> animIdx;
|
|
||||||
MetaTransFactory metaTrans;
|
|
||||||
};
|
|
||||||
std::vector<HalfTransition> halfTransitions;
|
|
||||||
|
|
||||||
struct AnimationResources : BigYAML
|
|
||||||
{
|
|
||||||
DECL_YAML
|
|
||||||
UniqueID64 animId;
|
|
||||||
UniqueID64 evntId;
|
|
||||||
};
|
|
||||||
std::vector<AnimationResources> animResources;
|
|
||||||
} animationSet;
|
|
||||||
|
|
||||||
struct ActionAABB : BigYAML
|
struct ActionAABB : BigYAML
|
||||||
{
|
{
|
||||||
@ -255,49 +241,44 @@ struct CHAR : BigYAML
|
|||||||
UniqueID64 animId;
|
UniqueID64 animId;
|
||||||
Value<atVec3f> aabb[2];
|
Value<atVec3f> aabb[2];
|
||||||
};
|
};
|
||||||
std::vector<ActionAABB> animAABBs;
|
Value<atUint32> animAABBCount;
|
||||||
|
Vector<ActionAABB, DNA_COUNT(animAABBCount)> animAABBs;
|
||||||
|
|
||||||
atUint32 unk3 = 0;
|
Value<atUint8> unkByte;
|
||||||
|
|
||||||
|
Value<atUint32> additiveMapCount;
|
||||||
|
Vector<bool, DNA_COUNT(additiveMapCount)> additiveMap;
|
||||||
|
|
||||||
struct Effect : BigYAML
|
} animationInfo;
|
||||||
|
|
||||||
|
struct HitboxSet : BigYAML
|
||||||
{
|
{
|
||||||
DECL_YAML
|
DECL_YAML
|
||||||
String<-1> name;
|
String<-1> name;
|
||||||
Value<atUint32> compCount;
|
Value<atUint32> hitboxCount;
|
||||||
struct EffectComponent : BigYAML
|
struct Hitbox : BigYAML
|
||||||
{
|
{
|
||||||
DECL_YAML
|
DECL_YAML
|
||||||
String<-1> name;
|
Value<atUint32> unk1;
|
||||||
DNAFourCC type;
|
|
||||||
UniqueID32 id;
|
|
||||||
Value<atUint32> unkMP2;
|
|
||||||
Value<float> unk1;
|
|
||||||
Value<atUint32> unk2;
|
Value<atUint32> unk2;
|
||||||
Value<atUint32> unk3;
|
Value<atUint32> unk3;
|
||||||
|
Value<atUint32> unk4;
|
||||||
|
Value<atUint32> unk5;
|
||||||
|
Value<float> unk6;
|
||||||
|
Value<float> unk7;
|
||||||
|
Value<float> unk8;
|
||||||
|
Value<float> unk9;
|
||||||
|
Value<float> unk10;
|
||||||
|
Value<float> unk11;
|
||||||
|
Value<float> unk12;
|
||||||
|
Value<float> unk13;
|
||||||
|
String<-1> boneName;
|
||||||
|
Value<float> unk14;
|
||||||
};
|
};
|
||||||
Vector<EffectComponent, DNA_COUNT(compCount)> comps;
|
Vector<Hitbox, DNA_COUNT(hitboxCount)> hitboxes;
|
||||||
};
|
};
|
||||||
std::vector<Effect> effects;
|
Value<atUint32> hitboxSetCount;
|
||||||
|
Vector<HitboxSet, DNA_COUNT(hitboxSetCount)> hitboxSets;
|
||||||
UniqueID32 cmdlOverride;
|
|
||||||
UniqueID32 cskrOverride;
|
|
||||||
|
|
||||||
std::vector<atUint32> animIdxs;
|
|
||||||
|
|
||||||
atUint32 unk4;
|
|
||||||
atUint8 unk5;
|
|
||||||
|
|
||||||
struct Extents : BigYAML
|
|
||||||
{
|
|
||||||
DECL_YAML
|
|
||||||
Value<atUint32> animIdx;
|
|
||||||
Value<atVec3f> aabb[2];
|
|
||||||
};
|
|
||||||
std::vector<Extents> extents;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID64>>& out) const
|
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID64>>& out) const
|
||||||
{
|
{
|
||||||
@ -305,16 +286,16 @@ struct CHAR : BigYAML
|
|||||||
out.reserve(1);
|
out.reserve(1);
|
||||||
out.emplace_back();
|
out.emplace_back();
|
||||||
DNAANCS::CharacterResInfo<UniqueID64>& chOut = out.back();
|
DNAANCS::CharacterResInfo<UniqueID64>& chOut = out.back();
|
||||||
chOut.name = name;
|
chOut.name = characterInfo.name;
|
||||||
chOut.cmdl = cmdl;
|
chOut.cmdl = characterInfo.cmdl;
|
||||||
chOut.cskr = cskr;
|
chOut.cskr = characterInfo.cskr;
|
||||||
chOut.cinf = cinf;
|
chOut.cinf = characterInfo.cinf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID64>>& out) const
|
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID64>>& out) const
|
||||||
{
|
{
|
||||||
out.clear();
|
out.clear();
|
||||||
for (const AnimationSet::Animation& ai : animationSet.animations)
|
for (const AnimationInfo::Animation& ai : animationInfo.animations)
|
||||||
ai.metaAnim.m_anim->gatherPrimitives(out);
|
ai.metaAnim.m_anim->gatherPrimitives(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +329,7 @@ struct CHAR : BigYAML
|
|||||||
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
||||||
{
|
{
|
||||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, CHAR, MaterialSet, 4>
|
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, CHAR, MaterialSet, DNACMDL::SurfaceHeader_3, 4>
|
||||||
(conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
(conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,74 +3,16 @@
|
|||||||
|
|
||||||
#include "BlenderConnection.hpp"
|
#include "BlenderConnection.hpp"
|
||||||
#include "../DNACommon/DNACommon.hpp"
|
#include "../DNACommon/DNACommon.hpp"
|
||||||
|
#include "../DNAMP2/CINF.hpp"
|
||||||
|
|
||||||
namespace Retro
|
namespace Retro
|
||||||
{
|
{
|
||||||
namespace DNAMP3
|
namespace DNAMP3
|
||||||
{
|
{
|
||||||
|
|
||||||
struct CINF : BigDNA
|
struct CINF : DNAMP2::CINF
|
||||||
{
|
{
|
||||||
DECL_DNA
|
Delete expl;
|
||||||
Value<atUint32> boneCount;
|
|
||||||
struct Bone : BigDNA
|
|
||||||
{
|
|
||||||
DECL_DNA
|
|
||||||
Value<atUint32> id;
|
|
||||||
Value<atUint32> parentId;
|
|
||||||
Value<atVec3f> origin;
|
|
||||||
Value<atUint32> linkedCount;
|
|
||||||
Vector<atUint32, DNA_COUNT(linkedCount)> linked;
|
|
||||||
};
|
|
||||||
Vector<Bone, DNA_COUNT(boneCount)> bones;
|
|
||||||
|
|
||||||
Value<atUint32> boneIdCount;
|
|
||||||
Vector<atUint32, DNA_COUNT(boneIdCount)> boneIds;
|
|
||||||
|
|
||||||
Value<atUint32> nameCount;
|
|
||||||
struct Name : BigDNA
|
|
||||||
{
|
|
||||||
DECL_DNA
|
|
||||||
String<-1> name;
|
|
||||||
Value<atUint32> boneId;
|
|
||||||
};
|
|
||||||
Vector<Name, DNA_COUNT(nameCount)> names;
|
|
||||||
|
|
||||||
atUint32 getBoneIdxFromId(atUint32 id) const
|
|
||||||
{
|
|
||||||
atUint32 idx = 0;
|
|
||||||
for (atUint32 bid : boneIds)
|
|
||||||
{
|
|
||||||
if (bid == id)
|
|
||||||
return idx;
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string* getBoneNameFromId(atUint32 id) const
|
|
||||||
{
|
|
||||||
for (const Name& name : names)
|
|
||||||
if (id == name.boneId)
|
|
||||||
return &name.name;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendVertexGroupsToBlender(HECL::BlenderConnection::PyOutStream& os) const
|
|
||||||
{
|
|
||||||
for (atUint32 bid : boneIds)
|
|
||||||
{
|
|
||||||
for (const Name& name : names)
|
|
||||||
{
|
|
||||||
if (name.boneId == bid)
|
|
||||||
{
|
|
||||||
os.format("obj.vertex_groups.new('%s')\n", name.name.c_str());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID64& cinfId) const
|
void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID64& cinfId) const
|
||||||
{
|
{
|
||||||
os.format("arm = bpy.data.armatures.new('CINF_%016" PRIX64 "')\n"
|
os.format("arm = bpy.data.armatures.new('CINF_%016" PRIX64 "')\n"
|
||||||
@ -90,7 +32,7 @@ struct CINF : BigDNA
|
|||||||
bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
|
bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
|
||||||
|
|
||||||
for (const Bone& bone : bones)
|
for (const Bone& bone : bones)
|
||||||
if (bone.parentId != 2)
|
if (bone.parentId != 97 && bone.parentId != 147)
|
||||||
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
||||||
|
|
||||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||||
|
@ -40,7 +40,7 @@ struct CMDL
|
|||||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||||
if (!conn.createBlend(outPath.getAbsolutePath()))
|
if (!conn.createBlend(outPath.getAbsolutePath()))
|
||||||
return false;
|
return false;
|
||||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 5>
|
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_3, 5>
|
||||||
(conn, rs, pakRouter, entry, dataSpec, loadRp);
|
(conn, rs, pakRouter, entry, dataSpec, loadRp);
|
||||||
return conn.saveBlend();
|
return conn.saveBlend();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "hecl/blender/BlenderConnection.hpp"
|
#include "hecl/blender/BlenderConnection.hpp"
|
||||||
#include "../DNACommon/DNACommon.hpp"
|
#include "../DNACommon/DNACommon.hpp"
|
||||||
#include "CINF.hpp"
|
#include "CINF.hpp"
|
||||||
|
#include "../DNAMP2/CSKR.hpp"
|
||||||
|
|
||||||
namespace Retro
|
namespace Retro
|
||||||
{
|
{
|
||||||
@ -13,34 +14,42 @@ namespace DNAMP3
|
|||||||
struct CSKR : BigDNA
|
struct CSKR : BigDNA
|
||||||
{
|
{
|
||||||
DECL_DNA
|
DECL_DNA
|
||||||
Value<atUint32> skinningRuleCount;
|
DNAFourCC magic;
|
||||||
struct SkinningRule : BigDNA
|
Value<atUint32> version;
|
||||||
|
DNAMP2::CSKR data;
|
||||||
|
Value<atUint32> matrixCount;
|
||||||
|
struct MatrixBindings : BigDNA
|
||||||
{
|
{
|
||||||
DECL_DNA
|
DECL_DNA
|
||||||
Value<atUint32> weightCount;
|
Value<atInt16> mtxs[10];
|
||||||
struct Weight : BigDNA
|
|
||||||
{
|
|
||||||
DECL_DNA
|
|
||||||
Value<atUint32> boneId;
|
|
||||||
Value<float> weight;
|
|
||||||
};
|
};
|
||||||
Vector<Weight, DNA_COUNT(weightCount)> weights;
|
Vector<MatrixBindings, DNA_COUNT(matrixCount / 10)> mtxBindings;
|
||||||
Value<atUint32> vertCount;
|
|
||||||
};
|
|
||||||
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
|
|
||||||
|
|
||||||
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
Value<atUint32> unkCount1;
|
||||||
|
Vector<atUint8, DNA_COUNT(unkCount1)> unk1;
|
||||||
|
Value<atUint32> unkCount2;
|
||||||
|
Vector<atUint8, DNA_COUNT(unkCount2)> unk2;
|
||||||
|
Value<atUint32> unkCount3;
|
||||||
|
Vector<atUint8, DNA_COUNT(unkCount3)> unk3;
|
||||||
|
Value<atUint32> unkCount4;
|
||||||
|
Vector<atUint8, DNA_COUNT(unkCount4)> unk4;
|
||||||
|
Value<atUint32> unkCount5;
|
||||||
|
Vector<atUint8, DNA_COUNT(unkCount5)> unk5;
|
||||||
|
|
||||||
|
const atInt16* getMatrixBank(size_t idx) const
|
||||||
{
|
{
|
||||||
atUint32 accum = 0;
|
return mtxBindings.at(idx).mtxs;
|
||||||
for (const SkinningRule& rule : skinningRules)
|
}
|
||||||
|
|
||||||
|
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atInt16 skinIdx) const
|
||||||
{
|
{
|
||||||
if (idx < accum + rule.vertCount)
|
if (skinIdx < 0)
|
||||||
for (const SkinningRule::Weight& weight : rule.weights)
|
return;
|
||||||
|
const DNAMP2::CSKR::SkinningRule& rule = data.skinningRules[skinIdx];
|
||||||
|
for (const DNAMP2::CSKR::SkinningRule::Weight& weight : rule.weights)
|
||||||
os.format("vert[dvert_lay][%u] = %f\n",
|
os.format("vert[dvert_lay][%u] = %f\n",
|
||||||
cinf.getBoneIdxFromId(weight.boneId),
|
cinf.getBoneIdxFromId(weight.boneId),
|
||||||
weight.weight);
|
weight.weight);
|
||||||
accum += rule.vertCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -203,6 +203,13 @@ void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID64, std::pair<UniqueI
|
|||||||
{
|
{
|
||||||
if (entry.second->type == FOURCC('CHAR'))
|
if (entry.second->type == FOURCC('CHAR'))
|
||||||
{
|
{
|
||||||
|
PAKEntryReadStream rs = entry.second->beginReadStream(m_node);
|
||||||
|
CHAR aChar;
|
||||||
|
aChar.read(rs);
|
||||||
|
const CHAR::CharacterInfo& ci = aChar.characterInfo;
|
||||||
|
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
|
||||||
|
for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays)
|
||||||
|
addTo[overlay.cmdl] = std::make_pair(overlay.cskr, ci.cinf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,12 +224,10 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
|
|||||||
return {TXTR::Extract, nullptr, {_S(".png")}};
|
return {TXTR::Extract, nullptr, {_S(".png")}};
|
||||||
case SBIG('CMDL'):
|
case SBIG('CMDL'):
|
||||||
return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
|
return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
|
||||||
#if 0
|
|
||||||
case SBIG('CHAR'):
|
case SBIG('CHAR'):
|
||||||
return {nullptr, CHAR::Extract, {_S(".yaml"), _S(".blend")}, 2};
|
return {nullptr, CHAR::Extract, {_S(".yaml"), _S(".blend")}, 2};
|
||||||
#endif
|
|
||||||
case SBIG('MREA'):
|
case SBIG('MREA'):
|
||||||
return {nullptr, MREA::Extract, {_S(".blend")}, 2};
|
return {nullptr, MREA::Extract, {_S(".blend")}, 3};
|
||||||
case SBIG('MLVL'):
|
case SBIG('MLVL'):
|
||||||
return {MLVL::Extract, nullptr, {_S(".yaml")}};
|
return {MLVL::Extract, nullptr, {_S(".yaml")}};
|
||||||
}
|
}
|
||||||
|
@ -83,12 +83,11 @@ void MREA::ReadBabeDeadToBlender_3(HECL::BlenderConnection::PyOutStream& os,
|
|||||||
break;
|
break;
|
||||||
case BabeDeadLight::LightSpot:
|
case BabeDeadLight::LightSpot:
|
||||||
os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n"
|
os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n"
|
||||||
"lamp.spot_size = %f\n"
|
"lamp.spot_size = 1.0\n"
|
||||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||||
"lamp_obj.rotation_mode = 'QUATERNION'\n"
|
"lamp_obj.rotation_mode = 'QUATERNION'\n"
|
||||||
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
|
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
|
||||||
"\n", s, l,
|
"\n", s, l,
|
||||||
light.spotCutoff / 2.f,
|
|
||||||
light.direction.vec[0], light.direction.vec[1], light.direction.vec[2]);
|
light.direction.vec[0], light.direction.vec[1], light.direction.vec[2]);
|
||||||
break;
|
break;
|
||||||
default: continue;
|
default: continue;
|
||||||
@ -242,7 +241,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
|
|||||||
{
|
{
|
||||||
for (int m=0 ; m<head.meshCount ; ++m)
|
for (int m=0 ; m<head.meshCount ; ++m)
|
||||||
{
|
{
|
||||||
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair>
|
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_3>
|
||||||
(os, drs, pakRouter, entry, dummy, true,
|
(os, drs, pakRouter, entry, dummy, true,
|
||||||
false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], surfaceCounts[m]);
|
false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], surfaceCounts[m]);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ struct MREA
|
|||||||
Value<atUint8> unk8;
|
Value<atUint8> unk8;
|
||||||
Value<atUint32> unk9;
|
Value<atUint32> unk9;
|
||||||
Value<atUint32> unk10;
|
Value<atUint32> unk10;
|
||||||
Value<float> spotCutoff;
|
Value<float> unk11;
|
||||||
Value<atVec4f> unk12;
|
Value<atVec4f> unk12;
|
||||||
Value<atUint32> unk13;
|
Value<atUint32> unk13;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user