metaforce/DataSpec/DNAMP1/ANIM.cpp

504 lines
15 KiB
C++
Raw Normal View History

2015-08-11 23:32:02 +00:00
#include "ANIM.hpp"
2016-04-07 03:40:25 +00:00
#include "zeus/CVector3f.hpp"
2015-08-11 23:32:02 +00:00
2016-02-13 09:02:47 +00:00
namespace DataSpec
2015-08-11 23:32:02 +00:00
{
namespace DNAMP1
{
2016-03-04 23:04:53 +00:00
using ANIMOutStream = hecl::BlenderConnection::PyOutStream::ANIMOutStream;
2016-04-07 03:40:25 +00:00
void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig) const
2015-08-13 07:29:00 +00:00
{
2015-08-13 21:29:07 +00:00
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
2015-08-13 07:29:00 +00:00
auto kit = chanKeys.begin();
2016-04-08 03:37:14 +00:00
std::vector<zeus::CQuaternion> fixedRotKeys;
std::vector<zeus::CVector3f> fixedTransKeys;
2015-08-13 07:29:00 +00:00
for (const std::pair<atUint32, bool>& bone : bones)
{
2016-04-07 03:40:25 +00:00
const std::string* bName = rig.getCINF().getBoneNameFromId(bone.first);
if (!bName)
continue;
os.format("bone_string = '%s'\n", bName->c_str());
2015-08-13 07:29:00 +00:00
os << "action_group = act.groups.new(bone_string)\n"
"\n"
2015-08-13 21:29:07 +00:00
"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"
2015-08-13 07:29:00 +00:00
"\n";
if (bone.second)
2016-04-08 23:11:26 +00:00
os << "transCurves = []\n"
2015-08-13 21:29:07 +00:00
"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"
2015-08-13 07:29:00 +00:00
"\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();
2015-08-13 07:29:00 +00:00
{
2016-04-07 03:40:25 +00:00
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
2016-04-08 03:37:14 +00:00
fixedRotKeys.clear();
2016-04-07 03:40:25 +00:00
fixedRotKeys.resize(rotKeys.size());
2016-04-07 03:40:25 +00:00
for (int c=0 ; c<4 ; ++c)
{
size_t idx = 0;
for (const DNAANIM::Value& val : rotKeys)
2016-04-08 23:21:41 +00:00
fixedRotKeys[idx++][c] = val.v4.vec[c];
2016-04-07 03:40:25 +00:00
}
2016-04-07 03:40:25 +00:00
for (zeus::CQuaternion& rot : fixedRotKeys)
2016-04-08 23:11:26 +00:00
rot = rig.invertRotation(bone.first, rot);
2016-04-07 03:40:25 +00:00
for (int c=0 ; c<4 ; ++c)
{
auto frameit = frames.begin();
ao.changeCurve(ANIMOutStream::CurveType::Rotate, c, rotKeys.size());
for (const zeus::CQuaternion& val : fixedRotKeys)
ao.write(*frameit++, val[c]);
}
2015-08-13 07:29:00 +00:00
}
if (bone.second)
{
const std::vector<DNAANIM::Value>& transKeys = *kit++;
2016-04-08 03:37:14 +00:00
fixedTransKeys.clear();
2016-04-07 03:40:25 +00:00
fixedTransKeys.resize(transKeys.size());
for (int c=0 ; c<3 ; ++c)
2015-08-13 07:29:00 +00:00
{
2016-04-07 03:40:25 +00:00
size_t idx = 0;
for (const DNAANIM::Value& val : transKeys)
2016-04-08 23:21:41 +00:00
fixedTransKeys[idx++][c] = val.v3.vec[c];
2016-04-07 03:40:25 +00:00
}
for (zeus::CVector3f& t : fixedTransKeys)
2016-04-08 23:11:26 +00:00
t = rig.invertPosition(bone.first, t, true);
2016-04-07 03:40:25 +00:00
for (int c=0 ; c<3 ; ++c)
{
auto frameit = frames.begin();
ao.changeCurve(ANIMOutStream::CurveType::Translate, c, fixedTransKeys.size());
for (const zeus::CVector3f& val : fixedTransKeys)
ao.write(*frameit++, val[c]);
2015-08-13 07:29:00 +00:00
}
}
}
}
2016-03-04 23:04:53 +00:00
void ANIM::ANIM0::read(athena::io::IStreamReader& reader)
2015-08-11 23:32:02 +00:00
{
Header head;
head.read(reader);
mainInterval = head.interval;
2015-08-13 21:29:07 +00:00
frames.clear();
frames.reserve(head.keyCount);
2015-08-11 23:32:02 +00:00
for (size_t k=0 ; k<head.keyCount ; ++k)
2015-08-13 21:29:07 +00:00
frames.push_back(k);
2015-08-11 23:32:02 +00:00
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();
2015-08-11 23:32:02 +00:00
bones.clear();
bones.reserve(boneCount);
channels.clear();
for (size_t b=0 ; b<boneCount ; ++b)
{
bones.emplace_back(boneMap[b], false);
atUint8 idx = reader.readUByte();
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
2015-11-21 01:16:07 +00:00
chan.type = DNAANIM::Channel::Type::Rotation;
2015-08-11 23:32:02 +00:00
if (idx != 0xff)
{
bones.back().second = true;
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
2015-11-21 01:16:07 +00:00
chan.type = DNAANIM::Channel::Type::Translation;
2015-08-11 23:32:02 +00:00
}
}
reader.readUint32Big();
2015-08-11 23:32:02 +00:00
chanKeys.clear();
chanKeys.reserve(channels.size());
for (const std::pair<atUint32, bool>& bone : bones)
{
chanKeys.emplace_back();
std::vector<DNAANIM::Value>& keys = chanKeys.back();
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec4fBig());
2015-08-11 23:32:02 +00:00
if (bone.second)
chanKeys.emplace_back();
}
reader.readUint32Big();
2015-08-11 23:32:02 +00:00
auto kit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
++kit;
if (bone.second)
{
std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec3fBig());
2015-08-11 23:32:02 +00:00
}
}
evnt.read(reader);
}
2016-03-04 23:04:53 +00:00
void ANIM::ANIM0::write(athena::io::IStreamWriter& writer) const
2015-08-11 23:32:02 +00:00
{
Header head;
head.unk0 = 0;
head.unk1 = 0;
head.unk2 = 0;
2015-08-13 21:29:07 +00:00
head.keyCount = frames.size();
2015-08-11 23:32:02 +00:00
head.duration = head.keyCount * mainInterval;
head.interval = mainInterval;
atUint32 maxId = 0;
for (const std::pair<atUint32, bool>& bone : bones)
2015-09-26 03:12:08 +00:00
maxId = std::max(maxId, bone.first);
2015-08-11 23:32:02 +00:00
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, bool>& bone : bones)
{
if (s == bone.first)
{
writer.writeUByte(boneIdx);
found = true;
break;
}
++boneIdx;
}
if (!found)
writer.writeUByte(0xff);
}
writer.writeUint32Big(bones.size());
2015-08-11 23:32:02 +00:00
size_t boneIdx = 0;
for (const std::pair<atUint32, bool>& bone : bones)
{
if (bone.second)
writer.writeUByte(boneIdx);
else
writer.writeUByte(0xff);
++boneIdx;
}
writer.writeUint32Big(bones.size() * head.keyCount);
2015-08-11 23:32:02 +00:00
auto cit = chanKeys.begin();
atUint32 transKeyCount = 0;
for (const std::pair<atUint32, bool>& bone : bones)
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec4fBig((*kit++).v4);
2015-08-11 23:32:02 +00:00
if (bone.second)
{
transKeyCount += head.keyCount;
++cit;
}
}
writer.writeUint32Big(transKeyCount);
2015-08-11 23:32:02 +00:00
cit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
++cit;
if (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);
2015-08-11 23:32:02 +00:00
}
}
evnt.write(writer);
}
size_t ANIM::ANIM0::binarySize(size_t __isz) const
{
Header head;
atUint32 maxId = 0;
for (const std::pair<atUint32, bool>& bone : bones)
maxId = std::max(maxId, bone.first);
__isz = head.binarySize(__isz);
__isz += maxId + 1;
__isz += bones.size() + 4;
__isz += 8;
for (const std::pair<atUint32, bool>& bone : bones)
{
__isz += head.keyCount * 16;
if (bone.second)
__isz += head.keyCount * 12;
}
return __isz + 4;
}
2016-03-04 23:04:53 +00:00
void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
2015-08-11 23:32:02 +00:00
{
Header head;
head.read(reader);
evnt = head.evnt;
mainInterval = head.interval;
WordBitmap keyBmp;
keyBmp.read(reader, head.keyBitmapBitCount);
2015-08-13 21:29:07 +00:00
frames.clear();
atUint32 frameAccum = 0;
2015-08-11 23:32:02 +00:00
for (bool bit : keyBmp)
{
if (bit)
2015-08-13 21:29:07 +00:00
frames.push_back(frameAccum);
++frameAccum;
2015-08-11 23:32:02 +00:00
}
2015-08-13 07:29:00 +00:00
reader.seek(8);
2015-08-11 23:32:02 +00:00
bones.clear();
bones.reserve(head.boneChannelCount);
channels.clear();
channels.reserve(head.boneChannelCount);
2015-09-26 03:12:08 +00:00
atUint16 keyframeCount = 0;
2015-08-11 23:32:02 +00:00
for (size_t b=0 ; b<head.boneChannelCount ; ++b)
{
ChannelDesc desc;
desc.read(reader);
2015-08-31 03:44:42 +00:00
bones.emplace_back(desc.id, desc.keyCount2 != 0);
2015-08-11 23:32:02 +00:00
if (desc.keyCount1)
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
2015-11-21 01:16:07 +00:00
chan.type = DNAANIM::Channel::Type::Rotation;
chan.id = desc.id;
2015-08-11 23:32:02 +00:00
chan.i[0] = desc.initRX;
chan.q[0] = desc.qRX;
chan.i[1] = desc.initRY;
chan.q[1] = desc.qRY;
chan.i[2] = desc.initRZ;
chan.q[2] = desc.qRZ;
}
2015-09-26 03:12:08 +00:00
keyframeCount = std::max(keyframeCount, desc.keyCount1);
2015-08-11 23:32:02 +00:00
if (desc.keyCount2)
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
2015-11-21 01:16:07 +00:00
chan.type = DNAANIM::Channel::Type::Translation;
chan.id = desc.id;
2015-08-11 23:32:02 +00:00
chan.i[0] = desc.initTX;
chan.q[0] = desc.qTX;
chan.i[1] = desc.initTY;
chan.q[1] = desc.qTY;
chan.i[2] = desc.initTZ;
chan.q[2] = desc.qTZ;
}
}
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
DNAANIM::BitstreamReader bsReader;
chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult);
}
2016-03-04 23:04:53 +00:00
void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
2015-08-11 23:32:02 +00:00
{
Header head;
head.evnt = evnt;
head.unk0 = 1;
head.interval = mainInterval;
head.unk1 = 3;
head.unk2 = 0;
head.unk3 = 1;
WordBitmap keyBmp;
size_t frameCount = 0;
2015-08-13 21:29:07 +00:00
for (atUint32 frame : frames)
2015-08-11 23:32:02 +00:00
{
2015-08-13 21:29:07 +00:00
while (keyBmp.getBit(frame))
++frame;
keyBmp.setBit(frame);
frameCount = frame + 1;
2015-08-11 23:32:02 +00:00
}
head.keyBitmapBitCount = frameCount;
head.duration = frameCount * mainInterval;
head.boneChannelCount = bones.size();
2015-08-13 21:29:07 +00:00
size_t keyframeCount = frames.size();
2015-08-11 23:32:02 +00:00
std::vector<DNAANIM::Channel> qChannels = channels;
DNAANIM::BitstreamWriter bsWriter;
size_t bsSize;
std::unique_ptr<atUint8[]> bsData = bsWriter.write(chanKeys, keyframeCount, qChannels,
head.rotDiv, head.translationMult, bsSize);
/* TODO: Figure out proper scratch size computation */
head.scratchSize = keyframeCount * channels.size() * 16;
head.write(writer);
keyBmp.write(writer);
writer.writeUint32Big(head.boneChannelCount);
writer.writeUint32Big(head.boneChannelCount);
2015-08-11 23:32:02 +00:00
auto cit = qChannels.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
ChannelDesc desc;
desc.id = bone.first;
DNAANIM::Channel& chan = *cit++;
desc.keyCount1 = keyframeCount;
desc.initRX = chan.i[0];
desc.qRX = chan.q[0];
desc.initRY = chan.i[1];
desc.qRY = chan.q[1];
desc.initRZ = chan.i[2];
desc.qRZ = chan.q[2];
if (bone.second)
{
DNAANIM::Channel& chan = *cit++;
desc.keyCount2 = keyframeCount;
desc.initTX = chan.i[0];
desc.qTX = chan.q[0];
desc.initTY = chan.i[1];
desc.qTY = chan.q[1];
desc.initTZ = chan.i[2];
desc.qTZ = chan.q[2];
}
desc.write(writer);
}
writer.writeUBytes(bsData.get(), bsSize);
}
size_t ANIM::ANIM2::binarySize(size_t __isz) const
{
Header head;
WordBitmap keyBmp;
for (atUint32 frame : frames)
{
while (keyBmp.getBit(frame))
++frame;
keyBmp.setBit(frame);
}
__isz = head.binarySize(__isz);
__isz = keyBmp.binarySize(__isz);
__isz += 8;
for (const std::pair<atUint32, bool>& bone : bones)
{
__isz += 17;
if (bone.second)
__isz += 9;
}
return __isz + DNAANIM::ComputeBitstreamSize(frames.size(), channels);
}
2016-04-09 23:19:17 +00:00
ANIM::ANIM(const BlenderAction& act, const std::unordered_map<std::string, atInt32>& idMap)
{
m_anim.reset(new struct ANIM0);
IANIM& newAnim = *m_anim;
newAnim.bones.reserve(act.channels.size());
size_t extChanCount = 0;
for (const BlenderAction::Channel& chan : act.channels)
{
auto search = idMap.find(chan.boneName);
if (search == idMap.cend())
{
Log.report(logvisor::Warning, "unable to find id for bone '%s'", chan.boneName.c_str());
continue;
}
extChanCount += std::max(zeus::PopCount(chan.attrMask), 2);
newAnim.bones.emplace_back(search->second, (chan.attrMask & 0x2) != 0);
}
newAnim.frames.reserve(act.frames.size());
for (int32_t frame : act.frames)
newAnim.frames.push_back(frame);
newAnim.channels.reserve(extChanCount);
newAnim.chanKeys.reserve(extChanCount);
for (const BlenderAction::Channel& chan : act.channels)
{
auto search = idMap.find(chan.boneName);
if (search == idMap.cend())
continue;
newAnim.channels.emplace_back();
DNAANIM::Channel& newChan = newAnim.channels.back();
newChan.type = DNAANIM::Channel::Type::Rotation;
newChan.id = search->second;
newAnim.chanKeys.emplace_back();
std::vector<DNAANIM::Value>& rotVals = newAnim.chanKeys.back();
rotVals.reserve(chan.keys.size());
for (const BlenderAction::Channel::Key& key : chan.keys)
{
rotVals.emplace_back(key.rotation.val.vec[0],
key.rotation.val.vec[1],
key.rotation.val.vec[2],
key.rotation.val.vec[3]);
}
if (chan.attrMask & 0x2)
{
newAnim.channels.emplace_back();
DNAANIM::Channel& newChan = newAnim.channels.back();
newChan.type = DNAANIM::Channel::Type::Translation;
newChan.id = search->second;
newAnim.chanKeys.emplace_back();
std::vector<DNAANIM::Value>& transVals = newAnim.chanKeys.back();
transVals.reserve(chan.keys.size());
for (const BlenderAction::Channel::Key& key : chan.keys)
{
transVals.emplace_back(key.position.val.vec[0],
key.position.val.vec[1],
key.position.val.vec[2]);
}
}
}
newAnim.mainInterval = act.interval;
}
2015-08-11 23:32:02 +00:00
}
}