mirror of https://github.com/AxioDL/metaforce.git
MP1 ANIM bug fixes
This commit is contained in:
parent
d0577ae304
commit
5b38596595
|
@ -13,6 +13,7 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
|
||||||
switch (chan.type)
|
switch (chan.type)
|
||||||
{
|
{
|
||||||
case Channel::ROTATION:
|
case Channel::ROTATION:
|
||||||
|
bitsPerKeyFrame += 1;
|
||||||
case Channel::TRANSLATION:
|
case Channel::TRANSLATION:
|
||||||
{
|
{
|
||||||
bitsPerKeyFrame += chan.q[0];
|
bitsPerKeyFrame += chan.q[0];
|
||||||
|
@ -37,11 +38,11 @@ static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div)
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
atInt16(asinf(quat.v4.vec[0]) / q),
|
|
||||||
atInt16(asinf(quat.v4.vec[1]) / q),
|
atInt16(asinf(quat.v4.vec[1]) / q),
|
||||||
atInt16(asinf(quat.v4.vec[2]) / q),
|
atInt16(asinf(quat.v4.vec[2]) / q),
|
||||||
|
atInt16(asinf(quat.v4.vec[3]) / q),
|
||||||
},
|
},
|
||||||
(quat.v4.vec[3] < 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)
|
||||||
|
@ -49,18 +50,33 @@ static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
|
||||||
float q = M_PI / 2.0 / div;
|
float q = M_PI / 2.0 / div;
|
||||||
Value retval =
|
Value retval =
|
||||||
{
|
{
|
||||||
|
0.0,
|
||||||
sinf(v.v[0] * q),
|
sinf(v.v[0] * q),
|
||||||
sinf(v.v[1] * q),
|
sinf(v.v[1] * q),
|
||||||
sinf(v.v[2] * q),
|
sinf(v.v[2] * q),
|
||||||
};
|
};
|
||||||
retval.v4.vec[3] = sqrtf(MAX((1.0 -
|
retval.v4.vec[0] = sqrtf(MAX((1.0 -
|
||||||
(retval.v4.vec[0]*retval.v4.vec[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])), 0.0));
|
retval.v4.vec[3] * retval.v4.vec[3])), 0.0));
|
||||||
retval.v4.vec[3] = v.w ? -retval.v4.vec[3] : retval.v4.vec[3];
|
retval.v4.vec[0] = v.w ? -retval.v4.vec[0] : retval.v4.vec[0];
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BitstreamReader::dequantizeBit(const atUint8* data)
|
||||||
|
{
|
||||||
|
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||||
|
atUint32 bitRem = m_bitCur % 32;
|
||||||
|
|
||||||
|
/* Fill 32 bit buffer with region containing bits */
|
||||||
|
/* Make them least significant */
|
||||||
|
atUint32 tempBuf = HECL::SBig(*(atUint32*)(data + byteCur)) >> bitRem;
|
||||||
|
|
||||||
|
/* That's it */
|
||||||
|
m_bitCur += 1;
|
||||||
|
return tempBuf & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
atInt16 BitstreamReader::dequantize(const atUint8* data, atUint8 q)
|
atInt16 BitstreamReader::dequantize(const atUint8* data, atUint8 q)
|
||||||
{
|
{
|
||||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||||
|
@ -144,7 +160,7 @@ BitstreamReader::read(const atUint8* data,
|
||||||
{
|
{
|
||||||
case Channel::ROTATION:
|
case Channel::ROTATION:
|
||||||
{
|
{
|
||||||
bool wBit = dequantize(data, 1);
|
bool wBit = dequantizeBit(data);
|
||||||
p[0] += dequantize(data, chan.q[0]);
|
p[0] += dequantize(data, chan.q[0]);
|
||||||
p[1] += dequantize(data, chan.q[1]);
|
p[1] += dequantize(data, chan.q[1]);
|
||||||
p[2] += dequantize(data, chan.q[2]);
|
p[2] += dequantize(data, chan.q[2]);
|
||||||
|
@ -175,6 +191,19 @@ BitstreamReader::read(const atUint8* data,
|
||||||
return chanKeys;
|
return chanKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BitstreamWriter::quantizeBit(atUint8* data, bool val)
|
||||||
|
{
|
||||||
|
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||||
|
atUint32 bitRem = m_bitCur % 32;
|
||||||
|
|
||||||
|
/* Fill 32 bit buffer with region containing bits */
|
||||||
|
/* Make them least significant */
|
||||||
|
*(atUint32*)(data + byteCur) =
|
||||||
|
HECL::SBig(HECL::SBig(*(atUint32*)(data + byteCur)) | (val << bitRem));
|
||||||
|
|
||||||
|
m_bitCur += 1;
|
||||||
|
}
|
||||||
|
|
||||||
void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt16 val)
|
void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt16 val)
|
||||||
{
|
{
|
||||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||||
|
@ -344,7 +373,7 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
|
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
|
||||||
quantize(newData, 1, qrCur.w);
|
quantizeBit(newData, qrCur.w);
|
||||||
quantize(newData, chan.q[0], qrCur.v[0] - qrLast.v[0]);
|
quantize(newData, chan.q[0], qrCur.v[0] - qrLast.v[0]);
|
||||||
quantize(newData, chan.q[1], qrCur.v[1] - qrLast.v[0]);
|
quantize(newData, chan.q[1], qrCur.v[1] - qrLast.v[0]);
|
||||||
quantize(newData, chan.q[2], qrCur.v[2] - qrLast.v[0]);
|
quantize(newData, chan.q[2], qrCur.v[2] - qrLast.v[0]);
|
||||||
|
|
|
@ -24,6 +24,13 @@ union Value
|
||||||
v3.vec[2] = z;
|
v3.vec[2] = z;
|
||||||
v4.vec[3] = 0.0;
|
v4.vec[3] = 0.0;
|
||||||
}
|
}
|
||||||
|
Value(float w, float x, float y, float z)
|
||||||
|
{
|
||||||
|
v4.vec[0] = w;
|
||||||
|
v4.vec[1] = x;
|
||||||
|
v4.vec[2] = y;
|
||||||
|
v4.vec[3] = z;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct QuantizedValue
|
struct QuantizedValue
|
||||||
{
|
{
|
||||||
|
@ -56,6 +63,7 @@ class BitstreamReader
|
||||||
{
|
{
|
||||||
size_t m_bitCur;
|
size_t m_bitCur;
|
||||||
atInt16 dequantize(const atUint8* data, atUint8 q);
|
atInt16 dequantize(const atUint8* data, atUint8 q);
|
||||||
|
bool dequantizeBit(const atUint8* data);
|
||||||
public:
|
public:
|
||||||
std::vector<std::vector<Value>>
|
std::vector<std::vector<Value>>
|
||||||
read(const atUint8* data,
|
read(const atUint8* data,
|
||||||
|
@ -69,6 +77,7 @@ class BitstreamWriter
|
||||||
{
|
{
|
||||||
size_t m_bitCur;
|
size_t m_bitCur;
|
||||||
void quantize(atUint8* data, atUint8 q, atInt16 val);
|
void quantize(atUint8* data, atUint8 q, atInt16 val);
|
||||||
|
void quantizeBit(atUint8* data, bool val);
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<atUint8[]>
|
std::unique_ptr<atUint8[]>
|
||||||
write(const std::vector<std::vector<Value>>& chanKeys,
|
write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
|
|
|
@ -7,8 +7,7 @@ namespace DNAMP1
|
||||||
|
|
||||||
void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
|
void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
|
||||||
{
|
{
|
||||||
os.format("bone_trans_heads = []\n"
|
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
|
||||||
"act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
|
|
||||||
|
|
||||||
auto kit = chanKeys.begin();
|
auto kit = chanKeys.begin();
|
||||||
for (const std::pair<atUint32, bool>& bone : bones)
|
for (const std::pair<atUint32, bool>& bone : bones)
|
||||||
|
@ -16,23 +15,22 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
|
||||||
os.format("bone_string = '%s'\n", cinf.getBoneNameFromId(bone.first)->c_str());
|
os.format("bone_string = '%s'\n", cinf.getBoneNameFromId(bone.first)->c_str());
|
||||||
os << "action_group = act.groups.new(bone_string)\n"
|
os << "action_group = act.groups.new(bone_string)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string)\n"
|
"rotCurves = []\n"
|
||||||
"crv = 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=0, action_group=bone_string))\n"
|
||||||
"crv = 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=1, action_group=bone_string))\n"
|
||||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, 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";
|
"\n";
|
||||||
|
|
||||||
if (bone.second)
|
if (bone.second)
|
||||||
os << "bone_parent_head = (0.0,0.0,0.0)\n"
|
os << "bone_trans_head = (0.0,0.0,0.0)\n"
|
||||||
"if arm_obj.data.bones[bone_string].parent is not None:\n"
|
"if arm_obj.data.bones[bone_string].parent is not None:\n"
|
||||||
" bone_parent_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
|
" bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
|
||||||
"bone_trans_heads.append(bone_parent_head)\n"
|
"transCurves = []\n"
|
||||||
"crv = 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=0, action_group=bone_string))\n"
|
||||||
"crv = 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=1, action_group=bone_string))\n"
|
||||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string)\n"
|
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
|
||||||
"\n";
|
"\n";
|
||||||
else
|
|
||||||
os << "bone_trans_heads.append((0,0,0))\n";
|
|
||||||
|
|
||||||
os << "crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\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.add()\n"
|
||||||
|
@ -41,31 +39,31 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
|
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
|
||||||
auto timeit = times.begin();
|
auto frameit = frames.begin();
|
||||||
for (const DNAANIM::Value& val : rotKeys)
|
for (const DNAANIM::Value& val : rotKeys)
|
||||||
{
|
{
|
||||||
float time = *timeit++;
|
atUint32 frame = *frameit++;
|
||||||
for (int c=0 ; c<4 ; ++c)
|
for (int c=0 ; c<4 ; ++c)
|
||||||
os.format("crv = act.fcurves[%d]\n"
|
os.format("crv = rotCurves[%d]\n"
|
||||||
"crv.keyframe_points.add()\n"
|
"crv.keyframe_points.add()\n"
|
||||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||||
"crv.keyframe_points[-1].co = (%f, %f)\n",
|
"crv.keyframe_points[-1].co = (%u, %f)\n",
|
||||||
c, time, val.v4.vec[c]);
|
c, frame, val.v4.vec[c]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bone.second)
|
if (bone.second)
|
||||||
{
|
{
|
||||||
const std::vector<DNAANIM::Value>& transKeys = *kit++;
|
const std::vector<DNAANIM::Value>& transKeys = *kit++;
|
||||||
auto timeit = times.begin();
|
auto frameit = frames.begin();
|
||||||
for (const DNAANIM::Value& val : transKeys)
|
for (const DNAANIM::Value& val : transKeys)
|
||||||
{
|
{
|
||||||
float time = *timeit++;
|
atUint32 frame = *frameit++;
|
||||||
for (int c=0 ; c<3 ; ++c)
|
for (int c=0 ; c<3 ; ++c)
|
||||||
os.format("crv = act.fcurves[%d+4]\n"
|
os.format("crv = transCurves[%d]\n"
|
||||||
"crv.keyframe_points.add()\n"
|
"crv.keyframe_points.add()\n"
|
||||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||||
"crv.keyframe_points[-1].co = (%f, %f)\n",
|
"crv.keyframe_points[-1].co = (%u, %f - bone_trans_head[%d])\n",
|
||||||
c, time, val.v4.vec[c]);
|
c, frame, val.v4.vec[c], c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,14 +75,10 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
|
||||||
head.read(reader);
|
head.read(reader);
|
||||||
mainInterval = head.interval;
|
mainInterval = head.interval;
|
||||||
|
|
||||||
times.clear();
|
frames.clear();
|
||||||
times.reserve(head.keyCount);
|
frames.reserve(head.keyCount);
|
||||||
float timeAccum = 0.0;
|
|
||||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||||
{
|
frames.push_back(k);
|
||||||
times.push_back(timeAccum);
|
|
||||||
timeAccum += head.interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<atUint8, atUint32> boneMap;
|
std::map<atUint8, atUint32> boneMap;
|
||||||
for (size_t b=0 ; b<head.boneSlotCount ; ++b)
|
for (size_t b=0 ; b<head.boneSlotCount ; ++b)
|
||||||
|
@ -151,7 +145,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
||||||
head.unk0 = 0;
|
head.unk0 = 0;
|
||||||
head.unk1 = 0;
|
head.unk1 = 0;
|
||||||
head.unk2 = 0;
|
head.unk2 = 0;
|
||||||
head.keyCount = times.size();
|
head.keyCount = frames.size();
|
||||||
head.duration = head.keyCount * mainInterval;
|
head.duration = head.keyCount * mainInterval;
|
||||||
head.interval = mainInterval;
|
head.interval = mainInterval;
|
||||||
|
|
||||||
|
@ -232,13 +226,13 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
||||||
|
|
||||||
WordBitmap keyBmp;
|
WordBitmap keyBmp;
|
||||||
keyBmp.read(reader, head.keyBitmapBitCount);
|
keyBmp.read(reader, head.keyBitmapBitCount);
|
||||||
times.clear();
|
frames.clear();
|
||||||
float timeAccum = 0.0;
|
atUint32 frameAccum = 0;
|
||||||
for (bool bit : keyBmp)
|
for (bool bit : keyBmp)
|
||||||
{
|
{
|
||||||
if (bit)
|
if (bit)
|
||||||
times.push_back(timeAccum);
|
frames.push_back(frameAccum);
|
||||||
timeAccum += head.interval;
|
++frameAccum;
|
||||||
}
|
}
|
||||||
reader.seek(8);
|
reader.seek(8);
|
||||||
|
|
||||||
|
@ -299,19 +293,18 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
|
||||||
|
|
||||||
WordBitmap keyBmp;
|
WordBitmap keyBmp;
|
||||||
size_t frameCount = 0;
|
size_t frameCount = 0;
|
||||||
for (float time : times)
|
for (atUint32 frame : frames)
|
||||||
{
|
{
|
||||||
size_t frameIdx = time / mainInterval;
|
while (keyBmp.getBit(frame))
|
||||||
while (keyBmp.getBit(frameIdx))
|
++frame;
|
||||||
++frameIdx;
|
keyBmp.setBit(frame);
|
||||||
keyBmp.setBit(frameIdx);
|
frameCount = frame + 1;
|
||||||
frameCount = frameIdx + 1;
|
|
||||||
}
|
}
|
||||||
head.keyBitmapBitCount = frameCount;
|
head.keyBitmapBitCount = frameCount;
|
||||||
head.duration = frameCount * mainInterval;
|
head.duration = frameCount * mainInterval;
|
||||||
head.boneChannelCount = bones.size();
|
head.boneChannelCount = bones.size();
|
||||||
|
|
||||||
size_t keyframeCount = times.size();
|
size_t keyframeCount = frames.size();
|
||||||
std::vector<DNAANIM::Channel> qChannels = channels;
|
std::vector<DNAANIM::Channel> qChannels = channels;
|
||||||
DNAANIM::BitstreamWriter bsWriter;
|
DNAANIM::BitstreamWriter bsWriter;
|
||||||
size_t bsSize;
|
size_t bsSize;
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct ANIM : BigDNA
|
||||||
IANIM(atUint32 version) : m_version(version) {}
|
IANIM(atUint32 version) : m_version(version) {}
|
||||||
|
|
||||||
std::vector<std::pair<atUint32, bool>> bones;
|
std::vector<std::pair<atUint32, bool>> bones;
|
||||||
std::vector<float> times;
|
std::vector<atUint32> frames;
|
||||||
std::vector<DNAANIM::Channel> channels;
|
std::vector<DNAANIM::Channel> channels;
|
||||||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||||
float mainInterval = 0.0;
|
float mainInterval = 0.0;
|
||||||
|
|
Loading…
Reference in New Issue