mirror of https://github.com/AxioDL/metaforce.git
Work on CFBStreamedCompression; defined 24-bit ANIM3 format
This commit is contained in:
parent
d9448cae05
commit
f9cef44029
|
@ -44,9 +44,9 @@ static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div)
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
atInt16(std::asin(quat.v4.vec[1]) / q),
|
atInt32(std::asin(quat.v4.vec[1]) / q),
|
||||||
atInt16(std::asin(quat.v4.vec[2]) / q),
|
atInt32(std::asin(quat.v4.vec[2]) / q),
|
||||||
atInt16(std::asin(quat.v4.vec[3]) / q),
|
atInt32(std::asin(quat.v4.vec[3]) / q),
|
||||||
},
|
},
|
||||||
(quat.v4.vec[0] < 0.f) ? true : false
|
(quat.v4.vec[0] < 0.f) ? true : false
|
||||||
};
|
};
|
||||||
|
@ -102,7 +102,7 @@ bool BitstreamReader::dequantizeBit(const atUint8* data)
|
||||||
return tempBuf & 0x1;
|
return tempBuf & 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
atInt16 BitstreamReader::dequantize(const atUint8* data, atUint8 q)
|
atInt32 BitstreamReader::dequantize(const atUint8* data, atUint8 q)
|
||||||
{
|
{
|
||||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||||
atUint32 bitRem = m_bitCur % 32;
|
atUint32 bitRem = m_bitCur % 32;
|
||||||
|
@ -138,7 +138,8 @@ BitstreamReader::read(const atUint8* data,
|
||||||
size_t keyFrameCount,
|
size_t keyFrameCount,
|
||||||
const std::vector<Channel>& channels,
|
const std::vector<Channel>& channels,
|
||||||
atUint32 rotDiv,
|
atUint32 rotDiv,
|
||||||
float transMult)
|
float transMult,
|
||||||
|
float scaleMult)
|
||||||
{
|
{
|
||||||
m_bitCur = 0;
|
m_bitCur = 0;
|
||||||
std::vector<std::vector<Value>> chanKeys;
|
std::vector<std::vector<Value>> chanKeys;
|
||||||
|
@ -167,7 +168,7 @@ BitstreamReader::read(const atUint8* data,
|
||||||
}
|
}
|
||||||
case Channel::Type::Scale:
|
case Channel::Type::Scale:
|
||||||
{
|
{
|
||||||
keys.push_back({chan.i[0] / float(rotDiv), chan.i[1] / float(rotDiv), chan.i[2] / float(rotDiv)});
|
keys.push_back({chan.i[0] * scaleMult, chan.i[1] * scaleMult, chan.i[2] * scaleMult});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Channel::Type::KfHead:
|
case Channel::Type::KfHead:
|
||||||
|
@ -219,11 +220,11 @@ BitstreamReader::read(const atUint8* data,
|
||||||
}
|
}
|
||||||
case Channel::Type::Translation:
|
case Channel::Type::Translation:
|
||||||
{
|
{
|
||||||
atInt16 val1 = dequantize(data, chan.q[0]);
|
atInt32 val1 = dequantize(data, chan.q[0]);
|
||||||
p[0] += val1;
|
p[0] += val1;
|
||||||
atInt16 val2 = dequantize(data, chan.q[1]);
|
atInt32 val2 = dequantize(data, chan.q[1]);
|
||||||
p[1] += val2;
|
p[1] += val2;
|
||||||
atInt16 val3 = dequantize(data, chan.q[2]);
|
atInt32 val3 = dequantize(data, chan.q[2]);
|
||||||
p[2] += val3;
|
p[2] += val3;
|
||||||
kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult});
|
kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult});
|
||||||
#if DUMP_KEYS
|
#if DUMP_KEYS
|
||||||
|
@ -236,7 +237,7 @@ BitstreamReader::read(const atUint8* 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]);
|
||||||
kit->push_back({p[0] / float(rotDiv), p[1] / float(rotDiv), p[2] / float(rotDiv)});
|
kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult});
|
||||||
#if DUMP_KEYS
|
#if DUMP_KEYS
|
||||||
fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]);
|
fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -249,13 +250,13 @@ BitstreamReader::read(const atUint8* data,
|
||||||
}
|
}
|
||||||
case Channel::Type::RotationMP3:
|
case Channel::Type::RotationMP3:
|
||||||
{
|
{
|
||||||
atInt16 val1 = dequantize(data, chan.q[0]);
|
atInt32 val1 = dequantize(data, chan.q[0]);
|
||||||
p[0] += val1;
|
p[0] += val1;
|
||||||
atInt16 val2 = dequantize(data, chan.q[1]);
|
atInt32 val2 = dequantize(data, chan.q[1]);
|
||||||
p[1] += val2;
|
p[1] += val2;
|
||||||
atInt16 val3 = dequantize(data, chan.q[2]);
|
atInt32 val3 = dequantize(data, chan.q[2]);
|
||||||
p[2] += val3;
|
p[2] += val3;
|
||||||
atInt16 val4 = dequantize(data, chan.q[3]);
|
atInt32 val4 = dequantize(data, chan.q[3]);
|
||||||
p[3] += val4;
|
p[3] += val4;
|
||||||
QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)};
|
QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)};
|
||||||
kit->emplace_back(DequantizeRotation_3(qr, rotDiv));
|
kit->emplace_back(DequantizeRotation_3(qr, rotDiv));
|
||||||
|
@ -287,7 +288,7 @@ void BitstreamWriter::quantizeBit(atUint8* data, bool val)
|
||||||
m_bitCur += 1;
|
m_bitCur += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt16 val)
|
void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt32 val)
|
||||||
{
|
{
|
||||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||||
atUint32 bitRem = m_bitCur % 32;
|
atUint32 bitRem = m_bitCur % 32;
|
||||||
|
@ -313,15 +314,19 @@ void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt16 val)
|
||||||
std::unique_ptr<atUint8[]>
|
std::unique_ptr<atUint8[]>
|
||||||
BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
size_t keyFrameCount, std::vector<Channel>& channels,
|
size_t keyFrameCount, std::vector<Channel>& channels,
|
||||||
|
atUint32 quantRange,
|
||||||
atUint32& rotDivOut,
|
atUint32& rotDivOut,
|
||||||
float& transMultOut,
|
float& transMultOut,
|
||||||
|
float& scaleMultOut,
|
||||||
size_t& sizeOut)
|
size_t& sizeOut)
|
||||||
{
|
{
|
||||||
m_bitCur = 0;
|
m_bitCur = 0;
|
||||||
rotDivOut = 32767; /* Normalized range of values */
|
rotDivOut = quantRange; /* Normalized range of values */
|
||||||
|
float quantRangeF = float(quantRange);
|
||||||
|
|
||||||
/* Pre-pass to calculate translation multiplier */
|
/* Pre-pass to calculate translation multiplier */
|
||||||
float maxTransDiff = 0.0f;
|
float maxTransDiff = 0.0f;
|
||||||
|
float maxScaleDiff = 0.0f;
|
||||||
auto kit = chanKeys.begin();
|
auto kit = chanKeys.begin();
|
||||||
for (Channel& chan : channels)
|
for (Channel& chan : channels)
|
||||||
{
|
{
|
||||||
|
@ -342,11 +347,27 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Channel::Type::Scale:
|
||||||
|
{
|
||||||
|
const Value* last = &(*kit)[0];
|
||||||
|
for (auto it=kit->begin() + 1;
|
||||||
|
it != kit->end();
|
||||||
|
++it)
|
||||||
|
{
|
||||||
|
const Value* current = &*it;
|
||||||
|
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[0] - last->v3.vec[0]);
|
||||||
|
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[1] - last->v3.vec[1]);
|
||||||
|
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[2] - last->v3.vec[2]);
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
++kit;
|
++kit;
|
||||||
}
|
}
|
||||||
transMultOut = maxTransDiff / 32767;
|
transMultOut = maxTransDiff / quantRangeF;
|
||||||
|
scaleMultOut = maxScaleDiff / quantRangeF;
|
||||||
|
|
||||||
/* Output channel inits */
|
/* Output channel inits */
|
||||||
kit = chanKeys.begin();
|
kit = chanKeys.begin();
|
||||||
|
@ -365,16 +386,16 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
}
|
}
|
||||||
case Channel::Type::Translation:
|
case Channel::Type::Translation:
|
||||||
{
|
{
|
||||||
chan.i = {atInt16((*kit)[0].v3.vec[0] / transMultOut),
|
chan.i = {atInt32((*kit)[0].v3.vec[0] / transMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[1] / transMultOut),
|
atInt32((*kit)[0].v3.vec[1] / transMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[2] / transMultOut)};
|
atInt32((*kit)[0].v3.vec[2] / transMultOut)};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Channel::Type::Scale:
|
case Channel::Type::Scale:
|
||||||
{
|
{
|
||||||
chan.i = {atInt16((*kit)[0].v3.vec[0] * rotDivOut),
|
chan.i = {atInt32((*kit)[0].v3.vec[0] / scaleMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[1] * rotDivOut),
|
atInt32((*kit)[0].v3.vec[1] / scaleMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[2] * rotDivOut)};
|
atInt32((*kit)[0].v3.vec[2] / scaleMultOut)};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
|
@ -405,16 +426,16 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
}
|
}
|
||||||
case Channel::Type::Translation:
|
case Channel::Type::Translation:
|
||||||
{
|
{
|
||||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] / transMultOut),
|
QuantizedValue last = {atInt32((*kit)[0].v3.vec[0] / transMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[1] / transMultOut),
|
atInt32((*kit)[0].v3.vec[1] / transMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[2] / transMultOut)};
|
atInt32((*kit)[0].v3.vec[2] / transMultOut)};
|
||||||
for (auto it=kit->begin() + 1;
|
for (auto it=kit->begin() + 1;
|
||||||
it != kit->end();
|
it != kit->end();
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
|
QuantizedValue cur = {atInt32(it->v3.vec[0] / transMultOut),
|
||||||
atInt16(it->v3.vec[1] / transMultOut),
|
atInt32(it->v3.vec[1] / transMultOut),
|
||||||
atInt16(it->v3.vec[2] / transMultOut)};
|
atInt32(it->v3.vec[2] / transMultOut)};
|
||||||
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
|
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
|
||||||
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
|
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
|
||||||
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
|
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
|
||||||
|
@ -424,16 +445,16 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
}
|
}
|
||||||
case Channel::Type::Scale:
|
case Channel::Type::Scale:
|
||||||
{
|
{
|
||||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] * rotDivOut),
|
QuantizedValue last = {atInt32((*kit)[0].v3.vec[0] / scaleMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[1] * rotDivOut),
|
atInt32((*kit)[0].v3.vec[1] / scaleMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[2] * rotDivOut)};
|
atInt32((*kit)[0].v3.vec[2] / scaleMultOut)};
|
||||||
for (auto it=kit->begin() + 1;
|
for (auto it=kit->begin() + 1;
|
||||||
it != kit->end();
|
it != kit->end();
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
|
QuantizedValue cur = {atInt32(it->v3.vec[0] * rotDivOut),
|
||||||
atInt16(it->v3.vec[1] * rotDivOut),
|
atInt32(it->v3.vec[1] * rotDivOut),
|
||||||
atInt16(it->v3.vec[2] * rotDivOut)};
|
atInt32(it->v3.vec[2] * rotDivOut)};
|
||||||
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
|
chan.q[0] = std::max(chan.q[0], atUint8(ceilf(log2f(cur[0] - last[0]))));
|
||||||
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
|
chan.q[1] = std::max(chan.q[1], atUint8(ceilf(log2f(cur[1] - last[1]))));
|
||||||
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
|
chan.q[2] = std::max(chan.q[2], atUint8(ceilf(log2f(cur[2] - last[2]))));
|
||||||
|
@ -474,16 +495,16 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
}
|
}
|
||||||
case Channel::Type::Translation:
|
case Channel::Type::Translation:
|
||||||
{
|
{
|
||||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] / transMultOut),
|
QuantizedValue last = {atInt32((*kit)[0].v3.vec[0] / transMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[1] / transMultOut),
|
atInt32((*kit)[0].v3.vec[1] / transMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[2] / transMultOut)};
|
atInt32((*kit)[0].v3.vec[2] / transMultOut)};
|
||||||
for (auto it=kit->begin() + 1;
|
for (auto it=kit->begin() + 1;
|
||||||
it != kit->end();
|
it != kit->end();
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
|
QuantizedValue cur = {atInt32(it->v3.vec[0] / transMultOut),
|
||||||
atInt16(it->v3.vec[1] / transMultOut),
|
atInt32(it->v3.vec[1] / transMultOut),
|
||||||
atInt16(it->v3.vec[2] / transMultOut)};
|
atInt32(it->v3.vec[2] / transMultOut)};
|
||||||
quantize(newData, chan.q[0], cur[0] - last[0]);
|
quantize(newData, chan.q[0], cur[0] - last[0]);
|
||||||
quantize(newData, chan.q[1], cur[1] - last[1]);
|
quantize(newData, chan.q[1], cur[1] - last[1]);
|
||||||
quantize(newData, chan.q[2], cur[2] - last[2]);
|
quantize(newData, chan.q[2], cur[2] - last[2]);
|
||||||
|
@ -493,16 +514,16 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||||
}
|
}
|
||||||
case Channel::Type::Scale:
|
case Channel::Type::Scale:
|
||||||
{
|
{
|
||||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] * rotDivOut),
|
QuantizedValue last = {atInt32((*kit)[0].v3.vec[0] / scaleMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[1] * rotDivOut),
|
atInt32((*kit)[0].v3.vec[1] / scaleMultOut),
|
||||||
atInt16((*kit)[0].v3.vec[2] * rotDivOut)};
|
atInt32((*kit)[0].v3.vec[2] / scaleMultOut)};
|
||||||
for (auto it=kit->begin() + 1;
|
for (auto it=kit->begin() + 1;
|
||||||
it != kit->end();
|
it != kit->end();
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
|
QuantizedValue cur = {atInt32(it->v3.vec[0] / scaleMultOut),
|
||||||
atInt16(it->v3.vec[1] * rotDivOut),
|
atInt32(it->v3.vec[1] / scaleMultOut),
|
||||||
atInt16(it->v3.vec[2] * rotDivOut)};
|
atInt32(it->v3.vec[2] / scaleMultOut)};
|
||||||
quantize(newData, chan.q[0], cur[0] - last[0]);
|
quantize(newData, chan.q[0], cur[0] - last[0]);
|
||||||
quantize(newData, chan.q[1], cur[1] - last[1]);
|
quantize(newData, chan.q[1], cur[1] - last[1]);
|
||||||
quantize(newData, chan.q[2], cur[2] - last[2]);
|
quantize(newData, chan.q[2], cur[2] - last[2]);
|
||||||
|
|
|
@ -31,10 +31,10 @@ union Value
|
||||||
};
|
};
|
||||||
struct QuantizedValue
|
struct QuantizedValue
|
||||||
{
|
{
|
||||||
atInt16 v[4];
|
atInt32 v[4];
|
||||||
atInt16& operator[] (size_t idx)
|
atInt32& operator[] (size_t idx)
|
||||||
{return v[idx];}
|
{return v[idx];}
|
||||||
const atInt16& operator[] (size_t idx) const
|
const atInt32& operator[] (size_t idx) const
|
||||||
{return v[idx];}
|
{return v[idx];}
|
||||||
};
|
};
|
||||||
struct QuantizedRot
|
struct QuantizedRot
|
||||||
|
@ -62,7 +62,7 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
|
||||||
class BitstreamReader
|
class BitstreamReader
|
||||||
{
|
{
|
||||||
size_t m_bitCur;
|
size_t m_bitCur;
|
||||||
atInt16 dequantize(const atUint8* data, atUint8 q);
|
atInt32 dequantize(const atUint8* data, atUint8 q);
|
||||||
bool dequantizeBit(const atUint8* data);
|
bool dequantizeBit(const atUint8* data);
|
||||||
public:
|
public:
|
||||||
std::vector<std::vector<Value>>
|
std::vector<std::vector<Value>>
|
||||||
|
@ -70,20 +70,23 @@ public:
|
||||||
size_t keyFrameCount,
|
size_t keyFrameCount,
|
||||||
const std::vector<Channel>& channels,
|
const std::vector<Channel>& channels,
|
||||||
atUint32 rotDiv,
|
atUint32 rotDiv,
|
||||||
float transMult);
|
float transMult,
|
||||||
|
float scaleMult);
|
||||||
};
|
};
|
||||||
|
|
||||||
class BitstreamWriter
|
class BitstreamWriter
|
||||||
{
|
{
|
||||||
size_t m_bitCur;
|
size_t m_bitCur;
|
||||||
void quantize(atUint8* data, atUint8 q, atInt16 val);
|
void quantize(atUint8* data, atUint8 q, atInt32 val);
|
||||||
void quantizeBit(atUint8* data, bool 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,
|
||||||
size_t keyFrameCount, std::vector<Channel>& channels,
|
size_t keyFrameCount, std::vector<Channel>& channels,
|
||||||
|
atUint32 quantRange,
|
||||||
atUint32& rotDivOut,
|
atUint32& rotDivOut,
|
||||||
float& transMultOut,
|
float& transMultOut,
|
||||||
|
float& scaleMultOut,
|
||||||
size_t& sizeOut);
|
size_t& sizeOut);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1075,6 +1075,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
||||||
const hecl::ProjectPath& inPath,
|
const hecl::ProjectPath& inPath,
|
||||||
const DNAANCS::Actor& actor,
|
const DNAANCS::Actor& actor,
|
||||||
hecl::BlenderConnection::DataStream& ds,
|
hecl::BlenderConnection::DataStream& ds,
|
||||||
|
bool pc,
|
||||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc)
|
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc)
|
||||||
{
|
{
|
||||||
/* Search for yaml */
|
/* Search for yaml */
|
||||||
|
@ -1248,7 +1249,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
||||||
if (w.hasError())
|
if (w.hasError())
|
||||||
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
||||||
cookedOut.getRelativePath().c_str());
|
cookedOut.getRelativePath().c_str());
|
||||||
ANIM anim(act, boneIdMap, *rigInv);
|
ANIM anim(act, boneIdMap, *rigInv, pc);
|
||||||
|
|
||||||
ancs.animationSet.animResources.emplace_back();
|
ancs.animationSet.animResources.emplace_back();
|
||||||
ancs.animationSet.animResources.back().animId = pathOut;
|
ancs.animationSet.animResources.back().animId = pathOut;
|
||||||
|
|
|
@ -540,6 +540,7 @@ struct ANCS : BigYAML
|
||||||
const hecl::ProjectPath& inPath,
|
const hecl::ProjectPath& inPath,
|
||||||
const DNAANCS::Actor& actor,
|
const DNAANCS::Actor& actor,
|
||||||
hecl::BlenderConnection::DataStream& ds,
|
hecl::BlenderConnection::DataStream& ds,
|
||||||
|
bool pc,
|
||||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,7 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
|
||||||
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
|
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
|
||||||
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
|
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
|
||||||
DNAANIM::BitstreamReader bsReader;
|
DNAANIM::BitstreamReader bsReader;
|
||||||
chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult);
|
chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
||||||
|
@ -336,7 +336,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
||||||
head.evnt = evnt;
|
head.evnt = evnt;
|
||||||
head.unk0 = 1;
|
head.unk0 = 1;
|
||||||
head.interval = mainInterval;
|
head.interval = mainInterval;
|
||||||
head.unk1 = 3;
|
head.rootBoneId = 3;
|
||||||
head.unk2 = 0;
|
head.unk2 = 0;
|
||||||
head.unk3 = 1;
|
head.unk3 = 1;
|
||||||
|
|
||||||
|
@ -357,8 +357,10 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
||||||
std::vector<DNAANIM::Channel> qChannels = channels;
|
std::vector<DNAANIM::Channel> qChannels = channels;
|
||||||
DNAANIM::BitstreamWriter bsWriter;
|
DNAANIM::BitstreamWriter bsWriter;
|
||||||
size_t bsSize;
|
size_t bsSize;
|
||||||
|
float scaleMult;
|
||||||
std::unique_ptr<atUint8[]> bsData = bsWriter.write(chanKeys, keyframeCount, qChannels,
|
std::unique_ptr<atUint8[]> bsData = bsWriter.write(chanKeys, keyframeCount, qChannels,
|
||||||
head.rotDiv, head.translationMult, bsSize);
|
m_version == 3 ? 0x7fffff : 0x7fff,
|
||||||
|
head.rotDiv, head.translationMult, scaleMult, bsSize);
|
||||||
|
|
||||||
/* TODO: Figure out proper scratch size computation */
|
/* TODO: Figure out proper scratch size computation */
|
||||||
head.scratchSize = keyframeCount * channels.size() * 16;
|
head.scratchSize = keyframeCount * channels.size() * 16;
|
||||||
|
@ -424,9 +426,10 @@ size_t ANIM::ANIM2::binarySize(size_t __isz) const
|
||||||
|
|
||||||
ANIM::ANIM(const BlenderAction& act,
|
ANIM::ANIM(const BlenderAction& act,
|
||||||
const std::unordered_map<std::string, atInt32>& idMap,
|
const std::unordered_map<std::string, atInt32>& idMap,
|
||||||
const DNAANIM::RigInverter<CINF>& rig)
|
const DNAANIM::RigInverter<CINF>& rig,
|
||||||
|
bool pc)
|
||||||
{
|
{
|
||||||
m_anim.reset(new struct ANIM0);
|
m_anim.reset(new struct ANIM2(pc));
|
||||||
IANIM& newAnim = *m_anim;
|
IANIM& newAnim = *m_anim;
|
||||||
|
|
||||||
newAnim.bones.reserve(act.channels.size());
|
newAnim.bones.reserve(act.channels.size());
|
||||||
|
|
|
@ -53,18 +53,18 @@ struct ANIM : BigDNA
|
||||||
struct ANIM2 : IANIM
|
struct ANIM2 : IANIM
|
||||||
{
|
{
|
||||||
DECL_EXPLICIT_DNA
|
DECL_EXPLICIT_DNA
|
||||||
ANIM2() : IANIM(2) {}
|
ANIM2(bool pc) : IANIM(pc ? 3 : 2) {}
|
||||||
|
|
||||||
struct Header : BigDNA
|
struct Header : BigDNA
|
||||||
{
|
{
|
||||||
DECL_DNA
|
DECL_DNA
|
||||||
Value<atUint32> scratchSize;
|
Value<atUint32> scratchSize;
|
||||||
UniqueID32 evnt;
|
UniqueID32 evnt;
|
||||||
Value<atUint32> unk0;
|
Value<atUint32> unk0 = 1;
|
||||||
Value<float> duration;
|
Value<float> duration;
|
||||||
Value<float> interval;
|
Value<float> interval;
|
||||||
Value<atUint32> unk1;
|
Value<atUint32> rootBoneId = 3;
|
||||||
Value<atUint32> unk2;
|
Value<atUint32> unk2 = 0;
|
||||||
Value<atUint32> rotDiv;
|
Value<atUint32> rotDiv;
|
||||||
Value<float> translationMult;
|
Value<float> translationMult;
|
||||||
Value<atUint32> boneChannelCount;
|
Value<atUint32> boneChannelCount;
|
||||||
|
@ -154,7 +154,11 @@ struct ANIM : BigDNA
|
||||||
m_anim->read(reader);
|
m_anim->read(reader);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
m_anim.reset(new struct ANIM2);
|
m_anim.reset(new struct ANIM2(false));
|
||||||
|
m_anim->read(reader);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
m_anim.reset(new struct ANIM2(true));
|
||||||
m_anim->read(reader);
|
m_anim->read(reader);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -184,7 +188,8 @@ struct ANIM : BigDNA
|
||||||
ANIM() = default;
|
ANIM() = default;
|
||||||
ANIM(const BlenderAction& act,
|
ANIM(const BlenderAction& act,
|
||||||
const std::unordered_map<std::string, atInt32>& idMap,
|
const std::unordered_map<std::string, atInt32>& idMap,
|
||||||
const DNAANIM::RigInverter<CINF>& rig);
|
const DNAANIM::RigInverter<CINF>& rig,
|
||||||
|
bool pc);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,7 +468,7 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
|
||||||
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
|
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
|
||||||
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
|
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
|
||||||
DNAANIM::BitstreamReader bsReader;
|
DNAANIM::BitstreamReader bsReader;
|
||||||
chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult);
|
chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult, head.scaleMult);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
||||||
|
@ -477,10 +477,8 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
||||||
head.unk1 = 1;
|
head.unk1 = 1;
|
||||||
head.unk2 = 1;
|
head.unk2 = 1;
|
||||||
head.interval = mainInterval;
|
head.interval = mainInterval;
|
||||||
head.unk3 = 0;
|
head.rootBoneId = 0;
|
||||||
head.unk4 = 0;
|
head.scaleMult = 0.f;
|
||||||
head.unk5 = 0;
|
|
||||||
head.unk6 = 1;
|
|
||||||
|
|
||||||
WordBitmap keyBmp;
|
WordBitmap keyBmp;
|
||||||
size_t frameCount = 0;
|
size_t frameCount = 0;
|
||||||
|
@ -500,7 +498,8 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
||||||
DNAANIM::BitstreamWriter bsWriter;
|
DNAANIM::BitstreamWriter bsWriter;
|
||||||
size_t bsSize;
|
size_t bsSize;
|
||||||
std::unique_ptr<atUint8[]> bsData = bsWriter.write(chanKeys, keyframeCount, qChannels,
|
std::unique_ptr<atUint8[]> bsData = bsWriter.write(chanKeys, keyframeCount, qChannels,
|
||||||
head.rotDiv, head.translationMult, bsSize);
|
m_version == 3 ? 0x7fffff : 0x7fff,
|
||||||
|
head.rotDiv, head.translationMult, head.scaleMult, bsSize);
|
||||||
|
|
||||||
/* TODO: Figure out proper scratch size computation */
|
/* TODO: Figure out proper scratch size computation */
|
||||||
head.scratchSize = keyframeCount * channels.size() * 16;
|
head.scratchSize = keyframeCount * channels.size() * 16;
|
||||||
|
|
|
@ -58,17 +58,16 @@ struct ANIM : BigDNA
|
||||||
{
|
{
|
||||||
DECL_DNA
|
DECL_DNA
|
||||||
Value<atUint32> scratchSize;
|
Value<atUint32> scratchSize;
|
||||||
Value<atUint8> unk1;
|
Value<atUint16> unk1;
|
||||||
Value<atUint8> unk2;
|
|
||||||
Value<float> duration;
|
Value<float> duration;
|
||||||
Value<float> interval;
|
Value<float> interval;
|
||||||
Value<atUint32> unk3;
|
Value<atUint32> rootBoneId = 3;
|
||||||
Value<atUint32> unk4;
|
Value<atUint32> unk2 = 0;
|
||||||
Value<atUint32> rotDiv;
|
Value<atUint32> rotDiv;
|
||||||
Value<float> translationMult;
|
Value<float> translationMult;
|
||||||
Value<atUint32> unk5;
|
Value<float> scaleMult;
|
||||||
Value<atUint32> boneChannelCount;
|
Value<atUint32> boneChannelCount;
|
||||||
Value<atUint32> unk6;
|
Value<atUint32> unk3 = 1;
|
||||||
Value<atUint32> keyBitmapBitCount;
|
Value<atUint32> keyBitmapBitCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ struct CINF : BigDNA
|
||||||
Value<atUint32> id;
|
Value<atUint32> id;
|
||||||
Value<atUint32> parentId;
|
Value<atUint32> parentId;
|
||||||
Value<atVec3f> origin;
|
Value<atVec3f> origin;
|
||||||
Value<float> skinMetrics[8];
|
Value<atVec4f> q1;
|
||||||
|
Value<atVec4f> q2;
|
||||||
Value<atUint32> linkedCount;
|
Value<atUint32> linkedCount;
|
||||||
Vector<atUint32, DNA_COUNT(linkedCount)> linked;
|
Vector<atUint32, DNA_COUNT(linkedCount)> linked;
|
||||||
};
|
};
|
||||||
|
|
|
@ -537,7 +537,7 @@ void ANIM::ANIM1::read(athena::io::IStreamReader& reader)
|
||||||
size_t bsSize = DNAANIM::ComputeBitstreamSize(head.keyCount-1, channels);
|
size_t bsSize = DNAANIM::ComputeBitstreamSize(head.keyCount-1, channels);
|
||||||
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
|
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
|
||||||
DNAANIM::BitstreamReader bsReader;
|
DNAANIM::BitstreamReader bsReader;
|
||||||
chanKeys = bsReader.read(bsData.get(), head.keyCount-1, channels, 32767, head.translationMult);
|
chanKeys = bsReader.read(bsData.get(), head.keyCount-1, channels, 32767, head.translationMult, head.scaleMult);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANIM::ANIM1::write(athena::io::IStreamWriter& writer) const
|
void ANIM::ANIM1::write(athena::io::IStreamWriter& writer) const
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct ANIM : BigDNA
|
||||||
Value<atUint32> unk3;
|
Value<atUint32> unk3;
|
||||||
Value<atUint8> unk4[3];
|
Value<atUint8> unk4[3];
|
||||||
Value<float> translationMult;
|
Value<float> translationMult;
|
||||||
Value<atUint32> unk6;
|
Value<float> scaleMult;
|
||||||
Value<atUint32> unk7;
|
Value<atUint32> unk7;
|
||||||
Value<float> unk8;
|
Value<float> unk8;
|
||||||
Value<float> unk9;
|
Value<float> unk9;
|
||||||
|
|
|
@ -371,7 +371,7 @@ struct SpecMP1 : SpecBase
|
||||||
FCookProgress progress)
|
FCookProgress progress)
|
||||||
{
|
{
|
||||||
Actor actor = ds.compileActor();
|
Actor actor = ds.compileActor();
|
||||||
DNAMP1::ANCS::Cook(out, in, actor, ds,
|
DNAMP1::ANCS::Cook(out, in, actor, ds, m_pc,
|
||||||
[&](const hecl::ProjectPath& modelPath) -> bool
|
[&](const hecl::ProjectPath& modelPath) -> bool
|
||||||
{
|
{
|
||||||
hecl::ProjectPath cooked;
|
hecl::ProjectPath cooked;
|
||||||
|
|
|
@ -277,6 +277,8 @@ public:
|
||||||
}
|
}
|
||||||
T* operator->() {return GetObj();}
|
T* operator->() {return GetObj();}
|
||||||
const T* operator->() const {return GetObj();}
|
const T* operator->() const {return GetObj();}
|
||||||
|
T& operator*() {return *GetObj();}
|
||||||
|
const T& operator*() const {return *GetObj();}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
@ -15,6 +15,9 @@ void CAnimFormatUnion::SubConstruct(u8* storage, EAnimFormat fmt,
|
||||||
case EAnimFormat::Uncompressed:
|
case EAnimFormat::Uncompressed:
|
||||||
new (storage) CAnimSource(in, store);
|
new (storage) CAnimSource(in, store);
|
||||||
break;
|
break;
|
||||||
|
case EAnimFormat::BitstreamCompressed24:
|
||||||
|
new (storage) CAnimSource(in, store);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Log.report(logvisor::Fatal, "unable to read ANIM format %d", int(fmt));
|
Log.report(logvisor::Fatal, "unable to read ANIM format %d", int(fmt));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ enum class EAnimFormat
|
||||||
{
|
{
|
||||||
Uncompressed,
|
Uncompressed,
|
||||||
Unknown,
|
Unknown,
|
||||||
BitstreamCompressed
|
BitstreamCompressed,
|
||||||
|
BitstreamCompressed24
|
||||||
};
|
};
|
||||||
|
|
||||||
class CAnimFormatUnion
|
class CAnimFormatUnion
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
|
||||||
template <class T>
|
|
||||||
using TSubAnimTypeToken = TCachedToken<T>;
|
|
||||||
|
|
||||||
class IAnimSourceInfo
|
class IAnimSourceInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
#include "CFBStreamedAnimReader.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
CFBStreamedAnimReaderTotals::CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source)
|
||||||
|
{
|
||||||
|
const CFBStreamedCompression::Header* header =
|
||||||
|
reinterpret_cast<const CFBStreamedCompression::Header*>(source.xc_rotsAndOffs.get());
|
||||||
|
const u32* bitmap = reinterpret_cast<const u32*>(source.xc_rotsAndOffs.get() + 9);
|
||||||
|
u32 bitmapWordCount = (bitmap[0] + 31) / 32;
|
||||||
|
|
||||||
|
x14_rotDiv = header->rotDiv;
|
||||||
|
x18_transMult = header->translationMult;
|
||||||
|
|
||||||
|
const u8* chans = reinterpret_cast<const u8*>(bitmap + bitmapWordCount + 1);
|
||||||
|
u32 boneChanCount = *reinterpret_cast<const u32*>(chans);
|
||||||
|
x24_boneChanCount = boneChanCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFBStreamedPairOfTotals::CFBStreamedPairOfTotals(const TSubAnimTypeToken<CFBStreamedCompression>& source)
|
||||||
|
: x0_source(source), xc_rotsAndOffs(source->xc_rotsAndOffs.get()), x14_(*source), x3c_(*source)
|
||||||
|
{
|
||||||
|
x0_source.Lock();
|
||||||
|
|
||||||
|
const u32* bitmap = reinterpret_cast<const u32*>(source->xc_rotsAndOffs.get() + 9);
|
||||||
|
u32 bitmapWordCount = (bitmap[0] + 31) / 32;
|
||||||
|
|
||||||
|
const u8* chans = reinterpret_cast<const u8*>(bitmap + bitmapWordCount + 1);
|
||||||
|
u32 boneChanCount = *reinterpret_cast<const u32*>(chans);
|
||||||
|
chans += 4;
|
||||||
|
|
||||||
|
for (int b=0 ; b<boneChanCount ; ++b)
|
||||||
|
{
|
||||||
|
chans += 15;
|
||||||
|
|
||||||
|
u16 tCount = *reinterpret_cast<const u16*>(chans);
|
||||||
|
chans += 2;
|
||||||
|
|
||||||
|
if (tCount)
|
||||||
|
chans += 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
x88_ = chans;
|
||||||
|
x8c_ = &x88_;
|
||||||
|
x90_ = *reinterpret_cast<const u32*>(*x8c_);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSegIdToIndexConverter::CSegIdToIndexConverter(const CFBStreamedAnimReaderTotals& totals)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CFBStreamedAnimReader::CFBStreamedAnimReader(const TSubAnimTypeToken<CFBStreamedCompression>& source, const CCharAnimTime& time)
|
||||||
|
: CAnimSourceReaderBase(std::make_unique<TAnimSourceInfo<CFBStreamedCompression>>(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;
|
||||||
|
|
||||||
|
const CFBStreamedCompression::Header* header =
|
||||||
|
reinterpret_cast<const CFBStreamedCompression::Header*>(x54_source->xc_rotsAndOffs.get());
|
||||||
|
x64_steadyStateInfo.x78_ = header->unk2;
|
||||||
|
|
||||||
|
PostConstruct(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
SAdvancementResults CFBStreamedAnimReader::VGetAdvancementResults(const CCharAnimTime& dt,
|
||||||
|
const CCharAnimTime& startOff) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFBStreamedAnimReader::VSetPhase(float)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SAdvancementResults CFBStreamedAnimReader::VReverseView(const CCharAnimTime& time)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<IAnimReader> CFBStreamedAnimReader::VClone() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFBStreamedAnimReader::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFBStreamedAnimReader::VGetSegStatementSet(const CSegIdList& list,
|
||||||
|
CSegStatementSet& setOut,
|
||||||
|
const CCharAnimTime& time) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SAdvancementResults CFBStreamedAnimReader::VAdvanceView(const CCharAnimTime& a)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CCharAnimTime CFBStreamedAnimReader::VGetTimeRemaining() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CSteadyStateAnimInfo CFBStreamedAnimReader::VGetSteadyStateAnimInfo() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFBStreamedAnimReader::VHasOffset(const CSegId& seg) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CVector3f CFBStreamedAnimReader::VGetOffset(const CSegId& seg) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CVector3f CFBStreamedAnimReader::VGetOffset(const CSegId& seg, const CCharAnimTime& time) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CQuaternion CFBStreamedAnimReader::VGetRotation(const CSegId& seg) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template class TAnimSourceInfo<CFBStreamedCompression>;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
#ifndef __URDE_CFSTREAMEDANIMREADER_HPP__
|
||||||
|
#define __URDE_CFSTREAMEDANIMREADER_HPP__
|
||||||
|
|
||||||
|
#include "CAnimSourceReader.hpp"
|
||||||
|
#include "CFBStreamedCompression.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class TAnimSourceInfo : public IAnimSourceInfo
|
||||||
|
{
|
||||||
|
TSubAnimTypeToken<T> x4_token;
|
||||||
|
public:
|
||||||
|
TAnimSourceInfo(const TSubAnimTypeToken<T>& token);
|
||||||
|
bool HasPOIData() const { return x4_token->GetPOIToken(); }
|
||||||
|
const std::vector<CBoolPOINode>& GetBoolPOIStream() const { return x4_token->GetPOIToken()->GetBoolPOIStream(); }
|
||||||
|
const std::vector<CInt32POINode>& GetInt32POIStream() const { return x4_token->GetPOIToken()->GetInt32POIStream(); }
|
||||||
|
const std::vector<CParticlePOINode>& GetParticlePOIStream() const { return x4_token->GetPOIToken()->GetParticlePOIStream(); }
|
||||||
|
const std::vector<CSoundPOINode>& GetSoundPOIStream() const { return x4_token->GetPOIToken()->GetSoundPOIStream(); }
|
||||||
|
CCharAnimTime GetAnimationDuration() const { return x4_token->GetAnimationDuration(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFBStreamedAnimReaderTotals
|
||||||
|
{
|
||||||
|
std::unique_ptr<u8[]> x0_buffer;
|
||||||
|
u32 x4_ = 0;
|
||||||
|
u32 x8_ = 0;
|
||||||
|
u32 xc_ = 0;
|
||||||
|
u32 x10_ = 0;
|
||||||
|
u32 x14_rotDiv;
|
||||||
|
float x18_transMult;
|
||||||
|
u32 x1c_ = 0;
|
||||||
|
bool x20_ = false;
|
||||||
|
u32 x24_boneChanCount;
|
||||||
|
public:
|
||||||
|
CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFBStreamedPairOfTotals
|
||||||
|
{
|
||||||
|
friend class CFBStreamedAnimReader;
|
||||||
|
|
||||||
|
TSubAnimTypeToken<CFBStreamedCompression> x0_source;
|
||||||
|
u32* xc_rotsAndOffs;
|
||||||
|
bool x10_ = true;
|
||||||
|
CFBStreamedAnimReaderTotals x14_;
|
||||||
|
CFBStreamedAnimReaderTotals x3c_;
|
||||||
|
const u8* x88_;
|
||||||
|
const u8** x8c_;
|
||||||
|
u32 x90_;
|
||||||
|
u32 x94_ = 0;
|
||||||
|
public:
|
||||||
|
CFBStreamedPairOfTotals(const TSubAnimTypeToken<CFBStreamedCompression>& source);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSegIdToIndexConverter
|
||||||
|
{
|
||||||
|
u32 x0_indices[96] = {-1};
|
||||||
|
public:
|
||||||
|
CSegIdToIndexConverter(const CFBStreamedAnimReaderTotals& totals);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFBStreamedAnimReader : public CAnimSourceReaderBase
|
||||||
|
{
|
||||||
|
TSubAnimTypeToken<CFBStreamedCompression> x54_source;
|
||||||
|
CSteadyStateAnimInfo x64_steadyStateInfo;
|
||||||
|
CFBStreamedPairOfTotals x7c_;
|
||||||
|
CSegIdToIndexConverter x114_;
|
||||||
|
public:
|
||||||
|
CFBStreamedAnimReader(const TSubAnimTypeToken<CFBStreamedCompression>& source, const CCharAnimTime& time);
|
||||||
|
|
||||||
|
SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const;
|
||||||
|
bool VSupportsReverseView() const {return false;}
|
||||||
|
void VSetPhase(float);
|
||||||
|
SAdvancementResults VReverseView(const CCharAnimTime& time);
|
||||||
|
std::shared_ptr<IAnimReader> VClone() const;
|
||||||
|
void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const;
|
||||||
|
void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const;
|
||||||
|
SAdvancementResults VAdvanceView(const CCharAnimTime& a);
|
||||||
|
CCharAnimTime VGetTimeRemaining() const;
|
||||||
|
CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const;
|
||||||
|
bool VHasOffset(const CSegId& seg) const;
|
||||||
|
zeus::CVector3f VGetOffset(const CSegId& seg) const;
|
||||||
|
zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& time) const;
|
||||||
|
zeus::CQuaternion VGetRotation(const CSegId& seg) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __URDE_CFSTREAMEDANIMREADER_HPP__
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include "CFBStreamedCompression.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore)
|
||||||
|
{
|
||||||
|
x0_scratchSize = in.readUint32Big();
|
||||||
|
x4_evnt = in.readUint32Big();
|
||||||
|
|
||||||
|
xc_rotsAndOffs = GetRotationsAndOffsets(x0_scratchSize / 4 + 1, in);
|
||||||
|
|
||||||
|
if (x4_evnt)
|
||||||
|
x8_evntToken = objStore.GetObj(SObjectTag{FOURCC('EVNT'), x4_evnt});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<u32[]> CFBStreamedCompression::GetRotationsAndOffsets(u32 words, CInputStream& in)
|
||||||
|
{
|
||||||
|
std::unique_ptr<u32[]> ret(new u32[words]);
|
||||||
|
|
||||||
|
Header head;
|
||||||
|
head.read(in);
|
||||||
|
*reinterpret_cast<Header*>(ret.get()) = head;
|
||||||
|
|
||||||
|
u32* bitmapOut = &ret[9];
|
||||||
|
u32 bitmapBitCount = in.readUint32Big();
|
||||||
|
bitmapOut[0] = bitmapBitCount;
|
||||||
|
u32 bitmapWordCount = (bitmapBitCount + 31) / 32;
|
||||||
|
for (u32 i=0 ; i<bitmapWordCount ; ++i)
|
||||||
|
bitmapOut[i+1] = in.readUint32Big();
|
||||||
|
|
||||||
|
in.readUint32Big();
|
||||||
|
u8* chans = reinterpret_cast<u8*>(bitmapOut + bitmapWordCount + 1);
|
||||||
|
u8* bs = ReadBoneChannelDescriptors(chans, in);
|
||||||
|
u32 bsWords = ComputeBitstreamWords(chans);
|
||||||
|
|
||||||
|
u32* bsPtr = reinterpret_cast<u32*>(bs);
|
||||||
|
for (u32 w=0 ; w<bsWords ; ++w)
|
||||||
|
bsPtr[w] = in.readUint32Big();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* CFBStreamedCompression::ReadBoneChannelDescriptors(u8* out, CInputStream& in)
|
||||||
|
{
|
||||||
|
u32 boneChanCount = in.readUint32Big();
|
||||||
|
*reinterpret_cast<u32*>(out) = boneChanCount;
|
||||||
|
out += 4;
|
||||||
|
|
||||||
|
for (int b=0 ; b<boneChanCount ; ++b)
|
||||||
|
{
|
||||||
|
*reinterpret_cast<u32*>(out) = in.readUint32Big();
|
||||||
|
out += 4;
|
||||||
|
|
||||||
|
*reinterpret_cast<u16*>(out) = in.readUint16Big();
|
||||||
|
out += 2;
|
||||||
|
|
||||||
|
for (int i=0 ; i<3 ; ++i)
|
||||||
|
{
|
||||||
|
*reinterpret_cast<s16*>(out) = in.readInt16Big();
|
||||||
|
out += 2;
|
||||||
|
*reinterpret_cast<u8*>(out) = in.readUByte();
|
||||||
|
out += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 tCount = in.readUint16Big();
|
||||||
|
*reinterpret_cast<u16*>(out) = tCount;
|
||||||
|
out += 2;
|
||||||
|
|
||||||
|
if (tCount)
|
||||||
|
{
|
||||||
|
for (int i=0 ; i<3 ; ++i)
|
||||||
|
{
|
||||||
|
*reinterpret_cast<s16*>(out) = in.readInt16Big();
|
||||||
|
out += 2;
|
||||||
|
*reinterpret_cast<u8*>(out) = in.readUByte();
|
||||||
|
out += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CFBStreamedCompression::ComputeBitstreamWords(const u8* chans)
|
||||||
|
{
|
||||||
|
u32 boneChanCount = *reinterpret_cast<const u32*>(chans);
|
||||||
|
chans += 4;
|
||||||
|
|
||||||
|
u16 keyCount = *reinterpret_cast<const u16*>(chans);
|
||||||
|
|
||||||
|
u32 totalBits = 0;
|
||||||
|
for (u32 c=0 ; c<boneChanCount ; ++c)
|
||||||
|
{
|
||||||
|
totalBits += *reinterpret_cast<const u8*>(chans + 0x8);
|
||||||
|
totalBits += *reinterpret_cast<const u8*>(chans + 0xb);
|
||||||
|
totalBits += *reinterpret_cast<const u8*>(chans + 0xe);
|
||||||
|
u16 tKeyCount = *reinterpret_cast<const u16*>(chans + 0xf);
|
||||||
|
chans += 0x11;
|
||||||
|
if (tKeyCount)
|
||||||
|
{
|
||||||
|
totalBits += *reinterpret_cast<const u8*>(chans + 0x2);
|
||||||
|
totalBits += *reinterpret_cast<const u8*>(chans + 0x5);
|
||||||
|
totalBits += *reinterpret_cast<const u8*>(chans + 0x8);
|
||||||
|
chans += 0x9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (totalBits * keyCount + 31) / 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
#ifndef __URDE_CFSTREAMEDCOMPRESSION_HPP__
|
||||||
|
#define __URDE_CFSTREAMEDCOMPRESSION_HPP__
|
||||||
|
|
||||||
|
#include "RetroTypes.hpp"
|
||||||
|
#include "CToken.hpp"
|
||||||
|
#include "CAnimPOIData.hpp"
|
||||||
|
#include "zeus/CVector3f.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
class IObjectStore;
|
||||||
|
|
||||||
|
class CFBStreamedCompression
|
||||||
|
{
|
||||||
|
friend class CFBStreamedAnimReader;
|
||||||
|
friend class CFBStreamedAnimReaderTotals;
|
||||||
|
friend class CFBStreamedPairOfTotals;
|
||||||
|
|
||||||
|
struct Header
|
||||||
|
{
|
||||||
|
u32 unk0;
|
||||||
|
float duration;
|
||||||
|
float interval;
|
||||||
|
u32 rootBoneId;
|
||||||
|
u32 unk2;
|
||||||
|
u32 rotDiv;
|
||||||
|
float translationMult;
|
||||||
|
u32 boneChannelCount;
|
||||||
|
u32 unk3;
|
||||||
|
|
||||||
|
void read(CInputStream& in)
|
||||||
|
{
|
||||||
|
/* unk0 */
|
||||||
|
unk0 = in.readUint32Big();
|
||||||
|
/* duration */
|
||||||
|
duration = in.readFloatBig();
|
||||||
|
/* interval */
|
||||||
|
interval = in.readFloatBig();
|
||||||
|
/* rootBoneId */
|
||||||
|
rootBoneId = in.readUint32Big();
|
||||||
|
/* unk2 */
|
||||||
|
unk2 = in.readUint32Big();
|
||||||
|
/* rotDiv */
|
||||||
|
rotDiv = in.readUint32Big();
|
||||||
|
/* translationMult */
|
||||||
|
translationMult = in.readFloatBig();
|
||||||
|
/* boneChannelCount */
|
||||||
|
boneChannelCount = in.readUint32Big();
|
||||||
|
/* unk3 */
|
||||||
|
unk3 = in.readUint32Big();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 x0_scratchSize;
|
||||||
|
ResId x4_evnt;
|
||||||
|
TLockedToken<CAnimPOIData> x8_evntToken;
|
||||||
|
std::unique_ptr<u32[]> xc_rotsAndOffs;
|
||||||
|
zeus::CVector3f x14_rootOffset;
|
||||||
|
|
||||||
|
static u8* ReadBoneChannelDescriptors(u8* out, CInputStream& in);
|
||||||
|
static std::unique_ptr<u32[]> GetRotationsAndOffsets(u32 words, CInputStream& in);
|
||||||
|
static u32 ComputeBitstreamWords(const u8* chans);
|
||||||
|
public:
|
||||||
|
CFBStreamedCompression(CInputStream& in, IObjectStore& objStore);
|
||||||
|
CCharAnimTime GetAnimationDuration() const { return reinterpret_cast<const Header*>(xc_rotsAndOffs.get())->duration; }
|
||||||
|
const TLockedToken<CAnimPOIData>& GetPOIToken() const { return x8_evntToken; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __URDE_CFSTREAMEDCOMPRESSION_HPP__
|
|
@ -73,6 +73,8 @@ set(CHARACTER_SOURCES
|
||||||
CParticlePOINode.hpp CParticlePOINode.cpp
|
CParticlePOINode.hpp CParticlePOINode.cpp
|
||||||
CAnimSourceReader.hpp CAnimSourceReader.cpp
|
CAnimSourceReader.hpp CAnimSourceReader.cpp
|
||||||
CAnimSource.hpp CAnimSource.cpp
|
CAnimSource.hpp CAnimSource.cpp
|
||||||
|
CFBStreamedAnimReader.hpp CFBStreamedAnimReader.cpp
|
||||||
|
CFBStreamedCompression.hpp CFBStreamedCompression.cpp
|
||||||
CAllFormatsAnimSource.hpp CAllFormatsAnimSource.cpp
|
CAllFormatsAnimSource.hpp CAllFormatsAnimSource.cpp
|
||||||
CSegStatementSet.hpp CSegStatementSet.cpp
|
CSegStatementSet.hpp CSegStatementSet.cpp
|
||||||
CAnimPerSegmentData.hpp
|
CAnimPerSegmentData.hpp
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "zeus/CVector3f.hpp"
|
#include "zeus/CVector3f.hpp"
|
||||||
#include "zeus/CQuaternion.hpp"
|
#include "zeus/CQuaternion.hpp"
|
||||||
#include "CParticleData.hpp"
|
#include "CParticleData.hpp"
|
||||||
|
#include "CToken.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -36,6 +37,9 @@ struct CSteadyStateAnimInfo
|
||||||
bool x78_ = false;
|
bool x78_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using TSubAnimTypeToken = TCachedToken<T>;
|
||||||
|
|
||||||
class IAnimReader
|
class IAnimReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue