From c5ddb51dfc67f4719bd9ad1fe78cdd06caecebb5 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 26 Aug 2016 15:02:12 -1000 Subject: [PATCH] Define ChannelDescPC for 24-bit ANIM3 --- DataSpec/DNAMP1/ANIM.cpp | 188 +++++++++++++------ DataSpec/DNAMP1/ANIM.hpp | 52 +++++ Runtime/Character/CFBStreamedAnimReader.cpp | 43 ++++- Runtime/Character/CFBStreamedAnimReader.hpp | 9 +- Runtime/Character/CFBStreamedCompression.cpp | 115 +++++++++--- Runtime/Character/CFBStreamedCompression.hpp | 9 +- Runtime/Character/IAnimReader.hpp | 2 +- 7 files changed, 318 insertions(+), 100 deletions(-) diff --git a/DataSpec/DNAMP1/ANIM.cpp b/DataSpec/DNAMP1/ANIM.cpp index c0835ee95..738b5479e 100644 --- a/DataSpec/DNAMP1/ANIM.cpp +++ b/DataSpec/DNAMP1/ANIM.cpp @@ -287,40 +287,82 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader) bones.reserve(head.boneChannelCount); channels.clear(); channels.reserve(head.boneChannelCount); - atUint16 keyframeCount = 0; - for (size_t b=0 ; b> 8; + chan.q[0] = desc.QinitRX & 0xff; + chan.i[1] = atInt32(desc.QinitRY) >> 8; + chan.q[1] = desc.QinitRY & 0xff; + chan.i[2] = atInt32(desc.QinitRZ) >> 8; + chan.q[2] = desc.QinitRZ & 0xff; + } + keyframeCount = std::max(keyframeCount, desc.keyCount1); + + if (desc.keyCount2) + { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Translation; + chan.id = desc.id; + chan.i[0] = atInt32(desc.QinitTX) >> 8; + chan.q[0] = desc.QinitTX & 0xff; + chan.i[1] = atInt32(desc.QinitTY) >> 8; + chan.q[1] = desc.QinitTY & 0xff; + chan.i[2] = atInt32(desc.QinitTZ) >> 8; + chan.q[2] = desc.QinitTZ & 0xff; + } } - keyframeCount = std::max(keyframeCount, desc.keyCount1); - - if (desc.keyCount2) + } + else + { + for (size_t b=0 ; b& bone : bones) + + if (m_version == 3) { - 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) + for (const std::pair& bone : bones) { + ChannelDescPC desc; + desc.id = bone.first; 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.keyCount1 = keyframeCount; + desc.QinitRX = (chan.i[0] << 8) | chan.q[0]; + desc.QinitRY = (chan.i[1] << 8) | chan.q[1]; + desc.QinitRZ = (chan.i[2] << 8) | chan.q[2]; + if (bone.second) + { + DNAANIM::Channel& chan = *cit++; + desc.keyCount2 = keyframeCount; + desc.QinitTX = (chan.i[0] << 8) | chan.q[0]; + desc.QinitTY = (chan.i[1] << 8) | chan.q[1]; + desc.QinitTZ = (chan.i[2] << 8) | chan.q[2]; + } + desc.write(writer); + } + } + else + { + for (const std::pair& 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); } - desc.write(writer); } writer.writeUBytes(bsData.get(), bsSize); @@ -414,11 +482,23 @@ size_t ANIM::ANIM2::binarySize(size_t __isz) const __isz = head.binarySize(__isz); __isz = keyBmp.binarySize(__isz); __isz += 8; - for (const std::pair& bone : bones) + if (m_version == 3) { - __isz += 17; - if (bone.second) - __isz += 9; + for (const std::pair& bone : bones) + { + __isz += 24; + if (bone.second) + __isz += 12; + } + } + else + { + for (const std::pair& bone : bones) + { + __isz += 17; + if (bone.second) + __isz += 9; + } } return __isz + DNAANIM::ComputeBitstreamSize(frames.size(), channels); diff --git a/DataSpec/DNAMP1/ANIM.hpp b/DataSpec/DNAMP1/ANIM.hpp index 31a70e765..7f11ebf47 100644 --- a/DataSpec/DNAMP1/ANIM.hpp +++ b/DataSpec/DNAMP1/ANIM.hpp @@ -141,6 +141,58 @@ struct ANIM : BigDNA return __isz; } }; + + struct ChannelDescPC : BigDNA + { + Delete expl; + Value id = 0; + Value keyCount1 = 0; + Value QinitRX = 0; + Value QinitRY = 0; + Value QinitRZ = 0; + Value keyCount2 = 0; + Value QinitTX = 0; + Value QinitTY = 0; + Value QinitTZ = 0; + + void read(athena::io::IStreamReader& reader) + { + id = reader.readUint32Big(); + keyCount1 = reader.readUint32Big(); + QinitRX = reader.readUint32Big(); + QinitRY = reader.readUint32Big(); + QinitRZ = reader.readUint32Big(); + keyCount2 = reader.readUint32Big(); + if (keyCount2) + { + QinitTX = reader.readUint32Big(); + QinitTY = reader.readUint32Big(); + QinitTZ = reader.readUint32Big(); + } + } + void write(athena::io::IStreamWriter& writer) const + { + writer.writeUint32Big(id); + writer.writeUint32Big(keyCount1); + writer.writeUint32Big(QinitRX); + writer.writeUint32Big(QinitRY); + writer.writeUint32Big(QinitRZ); + writer.writeUint32Big(keyCount2); + if (keyCount2) + { + writer.writeUint32Big(QinitTX); + writer.writeUint32Big(QinitTY); + writer.writeUint32Big(QinitTZ); + } + } + size_t binarySize(size_t __isz) const + { + __isz += 24; + if (keyCount2) + __isz += 12; + return __isz; + } + }; }; std::unique_ptr m_anim; diff --git a/Runtime/Character/CFBStreamedAnimReader.cpp b/Runtime/Character/CFBStreamedAnimReader.cpp index 60b16e0a9..c122c91e0 100644 --- a/Runtime/Character/CFBStreamedAnimReader.cpp +++ b/Runtime/Character/CFBStreamedAnimReader.cpp @@ -3,6 +3,19 @@ namespace urde { +void CFBStreamedAnimReaderTotals::Allocate(u32 chanCount) +{ + u32 chan16 = chanCount * 16; + u32 chan2 = chanCount * 2; + u32 chan32 = chanCount * 32; + + x0_buffer.reset(new u8[chan16 + chanCount + chan2 + chan32]); + x4_first16 = x0_buffer.get(); + x8_second1 = x4_first16 + chan16; + xc_third2 = x8_second1 + chanCount; + x10_fourth32 = xc_third2 + chan2; +} + CFBStreamedAnimReaderTotals::CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source) { const CFBStreamedCompression::Header* header = @@ -16,13 +29,12 @@ CFBStreamedAnimReaderTotals::CFBStreamedAnimReaderTotals(const CFBStreamedCompre const u8* chans = reinterpret_cast(bitmap + bitmapWordCount + 1); u32 boneChanCount = *reinterpret_cast(chans); x24_boneChanCount = boneChanCount; + Allocate(x24_boneChanCount); } CFBStreamedPairOfTotals::CFBStreamedPairOfTotals(const TSubAnimTypeToken& source) : x0_source(source), xc_rotsAndOffs(source->xc_rotsAndOffs.get()), x14_(*source), x3c_(*source) { - x0_source.Lock(); - const u32* bitmap = reinterpret_cast(source->xc_rotsAndOffs.get() + 9); u32 bitmapWordCount = (bitmap[0] + 31) / 32; @@ -30,15 +42,29 @@ CFBStreamedPairOfTotals::CFBStreamedPairOfTotals(const TSubAnimTypeToken(chans); chans += 4; - for (int b=0 ; bm_pc) { - chans += 15; + for (int b=0 ; b(chans); - chans += 2; + u32 tCount = *reinterpret_cast(chans); + chans += 4; + if (tCount) + chans += 12; + } + } + else + { + for (int b=0 ; b(chans); + chans += 2; + if (tCount) + chans += 9; + } } x88_ = chans; @@ -54,7 +80,6 @@ CFBStreamedAnimReader::CFBStreamedAnimReader(const TSubAnimTypeToken>(source), time), x54_source(source), x7c_(source), x114_(x7c_.x10_ ? x7c_.x14_ : x7c_.x3c_) { - x54_source.Lock(); x64_steadyStateInfo.x64_duration = x54_source->GetAnimationDuration(); x64_steadyStateInfo.x6c_curRootOffset = x54_source->x14_rootOffset; diff --git a/Runtime/Character/CFBStreamedAnimReader.hpp b/Runtime/Character/CFBStreamedAnimReader.hpp index 1926876b5..f06970fad 100644 --- a/Runtime/Character/CFBStreamedAnimReader.hpp +++ b/Runtime/Character/CFBStreamedAnimReader.hpp @@ -24,15 +24,16 @@ public: class CFBStreamedAnimReaderTotals { std::unique_ptr x0_buffer; - u32 x4_ = 0; - u32 x8_ = 0; - u32 xc_ = 0; - u32 x10_ = 0; + u8* x4_first16; + u8* x8_second1; + u8* xc_third2; + u8* x10_fourth32; u32 x14_rotDiv; float x18_transMult; u32 x1c_ = 0; bool x20_ = false; u32 x24_boneChanCount; + void Allocate(u32 chanCount); public: CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source); }; diff --git a/Runtime/Character/CFBStreamedCompression.cpp b/Runtime/Character/CFBStreamedCompression.cpp index 047a95e19..8f36d74de 100644 --- a/Runtime/Character/CFBStreamedCompression.cpp +++ b/Runtime/Character/CFBStreamedCompression.cpp @@ -3,7 +3,8 @@ namespace urde { -CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore) +CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc) +: m_pc(pc) { x0_scratchSize = in.readUint32Big(); x4_evnt = in.readUint32Big(); @@ -47,28 +48,46 @@ u8* CFBStreamedCompression::ReadBoneChannelDescriptors(u8* out, CInputStream& in *reinterpret_cast(out) = boneChanCount; out += 4; - for (int b=0 ; b(out) = in.readUint32Big(); - out += 4; - - *reinterpret_cast(out) = in.readUint16Big(); - out += 2; - - for (int i=0 ; i<3 ; ++i) + for (int b=0 ; b(out) = in.readInt16Big(); - out += 2; - *reinterpret_cast(out) = in.readUByte(); - out += 1; + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; + + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; + + for (int i=0 ; i<3 ; ++i) + { + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; + } + + u32 tCount = in.readUint32Big(); + *reinterpret_cast(out) = tCount; + out += 4; + + if (tCount) + { + for (int i=0 ; i<3 ; ++i) + { + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; + } + } } - - u16 tCount = in.readUint16Big(); - *reinterpret_cast(out) = tCount; - out += 2; - - if (tCount) + } + else + { + for (int b=0 ; b(out) = in.readUint32Big(); + out += 4; + + *reinterpret_cast(out) = in.readUint16Big(); + out += 2; + for (int i=0 ; i<3 ; ++i) { *reinterpret_cast(out) = in.readInt16Big(); @@ -76,6 +95,21 @@ u8* CFBStreamedCompression::ReadBoneChannelDescriptors(u8* out, CInputStream& in *reinterpret_cast(out) = in.readUByte(); out += 1; } + + u16 tCount = in.readUint16Big(); + *reinterpret_cast(out) = tCount; + out += 2; + + if (tCount) + { + for (int i=0 ; i<3 ; ++i) + { + *reinterpret_cast(out) = in.readInt16Big(); + out += 2; + *reinterpret_cast(out) = in.readUByte(); + out += 1; + } + } } } @@ -87,22 +121,47 @@ u32 CFBStreamedCompression::ComputeBitstreamWords(const u8* chans) u32 boneChanCount = *reinterpret_cast(chans); chans += 4; - u16 keyCount = *reinterpret_cast(chans); + u32 keyCount; u32 totalBits = 0; - for (u32 c=0 ; c(chans + 0x8); - totalBits += *reinterpret_cast(chans + 0xb); - totalBits += *reinterpret_cast(chans + 0xe); - u16 tKeyCount = *reinterpret_cast(chans + 0xf); - chans += 0x11; - if (tKeyCount) + keyCount = *reinterpret_cast(chans + 0x4); + for (u32 c=0 ; c(chans) & 0xff; + totalBits += *reinterpret_cast(chans + 0x4) & 0xff; + totalBits += *reinterpret_cast(chans + 0x8) & 0xff; + u32 tKeyCount = *reinterpret_cast(chans + 0xc); + chans += 0x10; + if (tKeyCount) + { + totalBits += *reinterpret_cast(chans) & 0xff; + totalBits += *reinterpret_cast(chans + 0x4) & 0xff; + totalBits += *reinterpret_cast(chans + 0x8) & 0xff; + chans += 0xc; + } + } + } + else + { + keyCount = *reinterpret_cast(chans + 0x4); + for (u32 c=0 ; c(chans + 0x2); totalBits += *reinterpret_cast(chans + 0x5); totalBits += *reinterpret_cast(chans + 0x8); - chans += 0x9; + u16 tKeyCount = *reinterpret_cast(chans + 0x9); + chans += 0xb; + if (tKeyCount) + { + totalBits += *reinterpret_cast(chans + 0x2); + totalBits += *reinterpret_cast(chans + 0x5); + totalBits += *reinterpret_cast(chans + 0x8); + chans += 0x9; + } } } diff --git a/Runtime/Character/CFBStreamedCompression.hpp b/Runtime/Character/CFBStreamedCompression.hpp index cff98c756..8e6f08cd4 100644 --- a/Runtime/Character/CFBStreamedCompression.hpp +++ b/Runtime/Character/CFBStreamedCompression.hpp @@ -51,17 +51,18 @@ class CFBStreamedCompression } }; + bool m_pc; u32 x0_scratchSize; ResId x4_evnt; TLockedToken x8_evntToken; std::unique_ptr xc_rotsAndOffs; zeus::CVector3f x14_rootOffset; - static u8* ReadBoneChannelDescriptors(u8* out, CInputStream& in); - static std::unique_ptr GetRotationsAndOffsets(u32 words, CInputStream& in); - static u32 ComputeBitstreamWords(const u8* chans); + u8* ReadBoneChannelDescriptors(u8* out, CInputStream& in); + u32 ComputeBitstreamWords(const u8* chans); + std::unique_ptr GetRotationsAndOffsets(u32 words, CInputStream& in); public: - CFBStreamedCompression(CInputStream& in, IObjectStore& objStore); + CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc); CCharAnimTime GetAnimationDuration() const { return reinterpret_cast(xc_rotsAndOffs.get())->duration; } const TLockedToken& GetPOIToken() const { return x8_evntToken; } }; diff --git a/Runtime/Character/IAnimReader.hpp b/Runtime/Character/IAnimReader.hpp index e0d5275e5..912140ee0 100644 --- a/Runtime/Character/IAnimReader.hpp +++ b/Runtime/Character/IAnimReader.hpp @@ -38,7 +38,7 @@ struct CSteadyStateAnimInfo }; template -using TSubAnimTypeToken = TCachedToken; +using TSubAnimTypeToken = TLockedToken; class IAnimReader {