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);
88 :
public CResAnmChrFrmBase<ResAnmChr::Frm96Data, CResAnmChrFrm<ResAnmChr::Frm96Data>> {
92 [[nodiscard]] f32 GetFrame()
const {
93 return parse<f32>(mPtr->frame);
96 [[nodiscard]] f32 GetFrameF32()
const {
97 return parse<f32>(mPtr->frame);
101 return parse<f32>(mPtr->value);
104 [[nodiscard]] f32 GetSlope()
const {
105 return parse<f32>(mPtr->slope);
124 [[nodiscard]]
static TFrame QuantizeFrame(f32 frame) {
125 return static_cast<TFrame
>(frame * 32.0f);
140 [[nodiscard]]
static TFrame QuantizeFrame(f32 frame) {
150 return parse<f32>(anmData->constValue);
153 const ResAnmChr::AnmData *pFVSAnmData =
reinterpret_cast<const ResAnmChr::AnmData *
>(
154 reinterpret_cast<uintptr_t
>(nodeData) + parse<s32>(anmData->toResAnmChrAnmData));
156 return CalcAnimationFVS<CAnmFmtTraits<T>>(frame, &pFVSAnmData->fvs);
159[[nodiscard]]
inline f32 CalcResult48(f32 frame,
const ResAnmChr::NodeData *nodeData,
160 const ResAnmChr::NodeData::AnmData *anmData,
bool constant) {
161 return CalcResultFVS<ResAnmChr::FVS48Data>(frame, nodeData, anmData, constant);
164[[nodiscard]]
inline f32 CalcResult96(f32 frame,
const ResAnmChr::NodeData *nodeData,
165 const ResAnmChr::NodeData::AnmData *anmData,
bool constant) {
166 return CalcResultFVS<ResAnmChr::FVS96Data>(frame, nodeData, anmData, constant);
170template <
typename TTraits>
171[[nodiscard]] f32 CalcAnimationFVS(f32 frame,
const ResAnmChr::FVSData *pFVSData) {
172 auto first = TTraits::GetKeyFrame(pFVSData, 0);
173 auto last = TTraits::GetKeyFrame(pFVSData, parse<u16>(pFVSData->numFrameValues) - 1);
175 if (frame <= first.GetFrameF32()) {
176 return first.GetValue(pFVSData);
179 if (last.GetFrameF32() <= frame) {
180 return last.GetValue(pFVSData);
183 f32 frameOffset = frame - first.GetFrameF32();
184 f32 numKeyFrame =
static_cast<f32
>(parse<u16>(pFVSData->numFrameValues));
186 f32 f_estimatePos = parse<f32>(pFVSData->invKeyFrameRange) * (frameOffset * numKeyFrame);
187 u16 i_estimatePos =
static_cast<u16>(f_estimatePos);
189 auto left = TTraits::GetKeyFrame(pFVSData, i_estimatePos);
190 auto quantized = TTraits::QuantizeFrame(frame);
192 if (quantized < left.GetFrame()) {
195 }
while (quantized < left.GetFrame());
199 }
while (left.GetFrame() <= quantized);
204 if (frame == left.GetFrameF32()) {
205 return left.GetValue(pFVSData);
208 auto right = left + 1;
210 f32 v0 = left.GetValue(pFVSData);
211 f32 t0 = left.GetSlope();
212 f32 v1 = right.GetValue(pFVSData);
213 f32 t1 = right.GetSlope();
215 f32 f0 = left.GetFrameF32();
216 f32 f1 = right.GetFrameF32();
218 f32 frameDelta = frame - f0;
219 f32 keyFrameDelta = f1 - f0;
221 f32 t = frameDelta * keyFrameDeltaInv;
229const ResAnmChr::NodeData::AnmData *GetAnmScale(f32 frame,
EGG::Vector3f &result,
230 const ResAnmChr::NodeData *nodeData,
const ResAnmChr::NodeData::AnmData *anmData) {
231 u32 flags = parse<u32>(nodeData->flags);
233 switch (flags & ResAnmChr::NodeData::Flag::FLAG_SCALE_FMT_MASK) {
235 case ResAnmChr::NodeData::Flag::FLAG_SCALE_FVS32_FMT:
236 case ResAnmChr::NodeData::Flag::FLAG_SCALE_FVS48_FMT: {
237 result.x = CalcResult48(frame, nodeData, anmData++,
238 flags & ResAnmChr::NodeData::FLAG_SCALE_X_CONST);
240 if (flags & ResAnmChr::NodeData::FLAG_SCALE_UNIFORM) {
244 result.y = CalcResult48(frame, nodeData, anmData++,
245 flags & ResAnmChr::NodeData::Flag::FLAG_SCALE_Y_CONST);
246 result.z = CalcResult48(frame, nodeData, anmData++,
247 flags & ResAnmChr::NodeData::Flag::FLAG_SCALE_Z_CONST);
250 case ResAnmChr::NodeData::Flag::FLAG_SCALE_FVS96_FMT: {
251 result.x = CalcResult96(frame, nodeData, anmData++,
252 flags & ResAnmChr::NodeData::FLAG_SCALE_X_CONST);
254 if (flags & ResAnmChr::NodeData::FLAG_SCALE_UNIFORM) {
258 result.y = CalcResult96(frame, nodeData, anmData++,
259 flags & ResAnmChr::NodeData::FLAG_SCALE_Y_CONST);
260 result.z = CalcResult96(frame, nodeData, anmData++,
261 flags & ResAnmChr::NodeData::FLAG_SCALE_Z_CONST);
272void GetAnmResult_Stub(f32 , ChrAnmResult & ,
273 const ResAnmChr::InfoData & ,
const ResAnmChr::NodeData * ) {}
275void GetAnmResult_S(f32 frame, ChrAnmResult &result,
const ResAnmChr::InfoData & ,
276 const ResAnmChr::NodeData *nodeData) {
277 GetAnmScale(frame, result.s, nodeData, nodeData->anms);
278 result.rt = EGG::Matrix34f::ident;
281const std::array<ResAnmChr::GetAnmResultFunc, ResAnmChr::NUM_RESULT_FUNCS>
282 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.