9ChrAnmResult ResAnmChr::getAnmResult(f32 frame,
size_t idx)
const {
10 s32 offset = parse<s32>(m_rawData->toChrDataDic);
11 ResDic dic = ResDic(
reinterpret_cast<void *
>(
reinterpret_cast<uintptr_t
>(m_rawData) + offset));
12 const NodeData *data =
reinterpret_cast<const NodeData *
>(dic[idx]);
14 u32 flags = parse<u32>(data->flags);
17 result.flags = flags &
18 (ChrAnmResult::Flag::FLAG_ANM_EXISTS | ChrAnmResult::Flag::FLAG_MTX_IDENT |
19 ChrAnmResult::Flag::FLAG_ROT_TRANS_ZERO | ChrAnmResult::Flag::FLAG_SCALE_ONE |
20 ChrAnmResult::Flag::FLAG_SCALE_UNIFORM | ChrAnmResult::Flag::FLAG_ROT_ZERO |
21 ChrAnmResult::Flag::FLAG_TRANS_ZERO | ChrAnmResult::Flag::FLAG_PATCH_SCALE |
22 ChrAnmResult::Flag::FLAG_PATCH_ROT | ChrAnmResult::Flag::FLAG_PATCH_TRANS |
23 ChrAnmResult::Flag::FLAG_SSC_APPLY | ChrAnmResult::Flag::FLAG_SSC_PARENT |
24 ChrAnmResult::Flag::FLAG_XSI_SCALING);
26 u32 index = (flags & NodeData::Flag::FLAG_HAS_SRT_MASK) >> 22;
28 ASSERT(index < s_getAnmResultTable.size());
30 (*s_getAnmResultTable[index])(frame, result, m_infoData, data);
36template <
typename TData,
typename TDerived>
41 void operator++(
int) {
44 void operator--(
int) {
48 [[nodiscard]] TDerived operator+(
int n) {
49 return TDerived(mPtr + n);
61 :
public CResAnmChrFrmBase<ResAnmChr::Frm48Data, CResAnmChrFrm<ResAnmChr::Frm48Data>> {
65 [[nodiscard]] s16 GetFrame()
const {
66 return parse<s16>(mPtr->frame);
69 [[nodiscard]] f32 GetFrameF32()
const {
70 return static_cast<f32
>(parse<s16>(mPtr->frame)) * (1.0f / 32.0f);
74 f32 x = parse<f32>(pFVSData->fvs48.scale);
75 f32 y =
static_cast<f32
>(parse<u16>(mPtr->value));
76 f32 z = parse<f32>(pFVSData->fvs48.offset);
81 [[nodiscard]] f32 GetSlope()
const {
82 return static_cast<f32
>(parse<s16>(mPtr->slope)) * (1.0f / 256.0f);
101 [[nodiscard]]
static TFrame QuantizeFrame(f32 frame) {
102 return static_cast<TFrame
>(frame * 32.0f);
111 return parse<f32>(anmData->constValue);
114 const ResAnmChr::AnmData *pFVSAnmData =
reinterpret_cast<const ResAnmChr::AnmData *
>(
115 reinterpret_cast<uintptr_t
>(nodeData) + parse<s32>(anmData->toResAnmChrAnmData));
117 return CalcAnimationFVS<CAnmFmtTraits<T>>(frame, &pFVSAnmData->fvs);
120[[nodiscard]]
inline f32 CalcResult48(f32 frame,
const ResAnmChr::NodeData *nodeData,
121 const ResAnmChr::NodeData::AnmData *anmData,
bool constant) {
122 return CalcResultFVS<ResAnmChr::FVS48Data>(frame, nodeData, anmData, constant);
126template <
typename TTraits>
127[[nodiscard]] f32 CalcAnimationFVS(f32 frame,
const ResAnmChr::FVSData *pFVSData) {
128 auto first = TTraits::GetKeyFrame(pFVSData, 0);
129 auto last = TTraits::GetKeyFrame(pFVSData, parse<u16>(pFVSData->numFrameValues) - 1);
131 if (frame <= first.GetFrameF32()) {
132 return first.GetValue(pFVSData);
135 if (last.GetFrameF32() <= frame) {
136 return last.GetValue(pFVSData);
139 f32 frameOffset = frame - first.GetFrameF32();
140 f32 numKeyFrame =
static_cast<f32
>(parse<u16>(pFVSData->numFrameValues));
142 f32 f_estimatePos = parse<f32>(pFVSData->invKeyFrameRange) * (frameOffset * numKeyFrame);
143 u16 i_estimatePos =
static_cast<u16>(f_estimatePos);
145 auto left = TTraits::GetKeyFrame(pFVSData, i_estimatePos);
146 auto quantized = TTraits::QuantizeFrame(frame);
148 if (quantized < left.GetFrame()) {
151 }
while (quantized < left.GetFrame());
155 }
while (left.GetFrame() <= quantized);
160 if (frame == left.GetFrameF32()) {
161 return left.GetValue(pFVSData);
164 auto right = left + 1;
166 f32 v0 = left.GetValue(pFVSData);
167 f32 t0 = left.GetSlope();
168 f32 v1 = right.GetValue(pFVSData);
169 f32 t1 = right.GetSlope();
171 f32 f0 = left.GetFrameF32();
172 f32 f1 = right.GetFrameF32();
174 f32 frameDelta = frame - f0;
175 f32 keyFrameDelta = f1 - f0;
177 f32 t = frameDelta * keyFrameDeltaInv;
185const ResAnmChr::NodeData::AnmData *GetAnmScale(f32 frame,
EGG::Vector3f &result,
186 const ResAnmChr::NodeData *nodeData,
const ResAnmChr::NodeData::AnmData *anmData) {
187 u32 flags = parse<u32>(nodeData->flags);
189 switch (flags & ResAnmChr::NodeData::Flag::FLAG_SCALE_FMT_MASK) {
191 case ResAnmChr::NodeData::Flag::FLAG_SCALE_FVS32_FMT:
192 case ResAnmChr::NodeData::Flag::FLAG_SCALE_FVS96_FMT:
193 PANIC(
"GetAnmScale flags not handled!");
195 case ResAnmChr::NodeData::Flag::FLAG_SCALE_FVS48_FMT: {
196 result.x = CalcResult48(frame, nodeData, anmData++,
197 flags & ResAnmChr::NodeData::FLAG_SCALE_X_CONST);
199 if (flags & ResAnmChr::NodeData::FLAG_SCALE_UNIFORM) {
203 result.y = CalcResult48(frame, nodeData, anmData++,
204 flags & ResAnmChr::NodeData::Flag::FLAG_SCALE_Y_CONST);
205 result.z = CalcResult48(frame, nodeData, anmData++,
206 flags & ResAnmChr::NodeData::Flag::FLAG_SCALE_Z_CONST);
217void GetAnmResult_Stub(f32 , ChrAnmResult & ,
218 const ResAnmChr::InfoData & ,
const ResAnmChr::NodeData * ) {}
220void GetAnmResult_S(f32 frame, ChrAnmResult &result,
const ResAnmChr::InfoData & ,
221 const ResAnmChr::NodeData *nodeData) {
222 GetAnmScale(frame, result.s, nodeData, nodeData->anms);
223 result.rt = EGG::Matrix34f::ident;
226const std::array<ResAnmChr::GetAnmResultFunc, ResAnmChr::NUM_RESULT_FUNCS>
227 ResAnmChr::s_getAnmResultTable = {{
Represents the CHR0 file format, which pertains to model movement animations.
An abstraction of components from the nw4r and RVL libraries.
static f32 fma(f32 x, f32 y, f32 z)
Fused multiply-add operation.
static f32 finv(f32 x)
Fused Newton-Raphson operation.
static f32 fms(f32 x, f32 y, f32 z)
Fused multiply-subtract operation.
Frame values (FVS) animation data.