void ANIM::ANIM2::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) { Header head; WordBitmap keyBmp; for (atUint32 frame : frames) { while (keyBmp.getBit(frame)) ++frame; keyBmp.setBit(frame); } head.binarySize(s); keyBmp.binarySize(s); s += 4; for (const std::pair<atUint32, std::tuple<bool, bool, bool>>& bone : bones) { s += 7; if (std::get<0>(bone.second)) s += 9; if (std::get<1>(bone.second)) s += 9; if (std::get<2>(bone.second)) s += 9; } s += DNAANIM::ComputeBitstreamSize(frames.size(), channels); }
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); }
void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const { 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; for (atUint32 frame : frames) { while (keyBmp.getBit(frame)) ++frame; keyBmp.setBit(frame); frameCount = frame + 1; } head.keyBitmapBitCount = frameCount; head.duration = frameCount * mainInterval; head.boneChannelCount = bones.size(); size_t keyframeCount = frames.size(); 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); 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); }
void ANIM::ANIM2::read(athena::io::IStreamReader& reader) { Header head; head.read(reader); evnt = head.evnt; mainInterval = head.interval; WordBitmap keyBmp; keyBmp.read(reader, head.keyBitmapBitCount); frames.clear(); atUint32 frameAccum = 0; for (bool bit : keyBmp) { if (bit) frames.push_back(frameAccum); ++frameAccum; } reader.seek(8); bones.clear(); bones.reserve(head.boneChannelCount); channels.clear(); channels.reserve(head.boneChannelCount); atUint16 keyframeCount = 0; for (size_t b=0 ; b<head.boneChannelCount ; ++b) { ChannelDesc desc; desc.read(reader); bones.emplace_back(desc.id, desc.keyCount2 != 0); if (desc.keyCount1) { channels.emplace_back(); DNAANIM::Channel& chan = channels.back(); chan.type = DNAANIM::Channel::Type::Rotation; 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; } keyframeCount = std::max(keyframeCount, desc.keyCount1); if (desc.keyCount2) { channels.emplace_back(); DNAANIM::Channel& chan = channels.back(); chan.type = DNAANIM::Channel::Type::Translation; 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); }
void ANIM::ANIM2::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) { /* TODO: conform to MP1 ANIM3 */ Header head; head.unk1 = 1; head.looping = looping; head.interval = mainInterval; head.rootBoneId = 0; head.scaleMult = 0.f; WordBitmap keyBmp; size_t frameCount = 0; for (atUint32 frame : frames) { while (keyBmp.getBit(frame)) ++frame; keyBmp.setBit(frame); frameCount = frame + 1; } head.keyBitmapBitCount = keyBmp.getBitCount(); head.duration = frameCount * mainInterval; head.boneChannelCount = bones.size(); size_t keyframeCount = frames.size(); std::vector<DNAANIM::Channel> qChannels = channels; DNAANIM::BitstreamWriter bsWriter; size_t bsSize; std::unique_ptr<atUint8[]> bsData = bsWriter.write(chanKeys, keyframeCount, qChannels, m_version == 3 ? 0x7fffff : 0x7fff, head.rotDiv, head.translationMult, head.scaleMult, bsSize); /* TODO: Figure out proper scratch size computation */ head.scratchSize = keyframeCount * channels.size() * 16; head.write(writer); keyBmp.write(writer); writer.writeUint32Big(head.boneChannelCount); auto cit = qChannels.begin(); for (const std::pair<atUint32, std::tuple<bool, bool, bool>>& bone : bones) { ChannelDesc desc; if (std::get<0>(bone.second)) { 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 (std::get<1>(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]; } if (std::get<2>(bone.second)) { DNAANIM::Channel& chan = *cit++; desc.keyCount3 = keyframeCount; desc.initSX = chan.i[0]; desc.qSX = chan.q[0]; desc.initSY = chan.i[1]; desc.qSY = chan.q[1]; desc.initSZ = chan.i[2]; desc.qSZ = chan.q[2]; } } writer.writeUBytes(bsData.get(), bsSize); }
void ANIM::ANIM2::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) { Header head; head.read(reader); mainInterval = head.interval; looping = bool(head.looping); WordBitmap keyBmp; keyBmp.read(reader, head.keyBitmapBitCount); frames.clear(); atUint32 frameAccum = 0; for (bool bit : keyBmp) { if (bit) frames.push_back(frameAccum); ++frameAccum; } reader.seek(4); bones.clear(); bones.reserve(head.boneChannelCount); channels.clear(); channels.reserve(head.boneChannelCount); atUint16 keyframeCount = 0; for (size_t b = 0; b < head.boneChannelCount; ++b) { ChannelDesc desc; desc.read(reader); bones.emplace_back(desc.id, std::make_tuple(desc.keyCount1 != 0, desc.keyCount2 != 0, desc.keyCount3 != 0)); if (desc.keyCount1) { channels.emplace_back(); DNAANIM::Channel& chan = channels.back(); chan.type = DNAANIM::Channel::Type::Rotation; 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; } keyframeCount = std::max(keyframeCount, desc.keyCount1); if (desc.keyCount2) { channels.emplace_back(); DNAANIM::Channel& chan = channels.back(); chan.type = DNAANIM::Channel::Type::Translation; 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; } keyframeCount = std::max(keyframeCount, desc.keyCount2); if (desc.keyCount3) { channels.emplace_back(); DNAANIM::Channel& chan = channels.back(); chan.type = DNAANIM::Channel::Type::Scale; chan.i[0] = desc.initSX; chan.q[0] = desc.qSX; chan.i[1] = desc.initSY; chan.q[1] = desc.qSY; chan.i[2] = desc.initSZ; chan.q[2] = desc.qSZ; } keyframeCount = std::max(keyframeCount, desc.keyCount3); } 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, head.scaleMult); }