OdysseyDecomp/lib/al/Project/LiveActor/ConveyerKeyKeeper.cpp

176 lines
6 KiB
C++

#include "Project/LiveActor/ConveyerKeyKeeper.h"
#include "Library/LiveActor/ActorInitInfo.h"
#include "Library/Math/MathUtil.h"
#include "Library/Placement/PlacementFunction.h"
#include "Library/Placement/PlacementInfo.h"
namespace al {
void ConveyerKey::init(const sead::Vector3f& keeperTrans, const sead::Vector3f& keeperDir,
const PlacementInfo& placement) {
sead::Vector3f trans;
tryGetTrans(&trans, placement);
moveDistance = (trans - keeperTrans).dot(keeperDir);
totalMoveDistance = 0.0f;
interpolateType = 0;
tryGetArg(&interpolateType, placement, "InterpolateType");
quat.set(sead::Quatf::unit);
placementInfo = new PlacementInfo(placement);
tryGetQuat(&quat, placement);
verticalizeVec(&moveDistanceVertical, keeperDir, trans - keeperTrans);
}
ConveyerKeyKeeper::ConveyerKeyKeeper() = default;
void ConveyerKeyKeeper::init(const ActorInitInfo& info) {
tryGetQuat(&mQuat, info);
tryGetTrans(&mTrans, info);
s32 moveAxis = 2;
tryGetArg(&moveAxis, info, "MoveAxis");
tryGetLocalAxis(&mMoveDirection, info, moveAxis);
mConveyerKeyCount = calcLinkNestNum(info, "KeyMoveNext") + 1;
mConveyerKeys = new ConveyerKey[mConveyerKeyCount];
mConveyerKeys[0].init(mTrans, mMoveDirection, *info.placementInfo);
PlacementInfo linkPlacementSource = *info.placementInfo;
PlacementInfo linkPlacement;
for (s32 i = 0; i < mConveyerKeyCount - 1; i++) {
getLinksInfo(&linkPlacement, linkPlacementSource, "KeyMoveNext");
mConveyerKeys[i + 1].init(mTrans, mMoveDirection, linkPlacement);
linkPlacementSource = linkPlacement;
}
mTotalMoveDistance = 0.0f;
for (s32 i = 1; i < mConveyerKeyCount; i++) {
ConveyerKey* key = &mConveyerKeys[i - 1];
ConveyerKey* nextKey = &mConveyerKeys[i];
f32 distance = sead::Mathf::abs(nextKey->moveDistance - key->moveDistance);
mTotalMoveDistance += distance;
nextKey->totalMoveDistance = mTotalMoveDistance;
}
}
// Mismatch: Same as calcPosAndQuatByKeyIndex
// https://decomp.me/scratch/kmQvB
void ConveyerKeyKeeper::calcPosAndQuat(sead::Vector3f* pos, sead::Quatf* quat, s32* index,
f32 coord) const {
if (coord <= 0.0f) {
if (pos)
pos->set(mTrans);
if (quat)
quat->set(mQuat);
if (index)
*index = -1;
return;
}
if (coord >= mTotalMoveDistance) {
// Pretty sure this should be a call to calcPosAndQuatByKeyIndex, but the match becomes
// worse
const ConveyerKey& key = getConveyerKey(mConveyerKeyCount - 1);
if (pos)
pos->set(key.moveDistanceVertical + key.moveDistance * mMoveDirection + mTrans);
if (quat)
quat->set(getConveyerKey(mConveyerKeyCount - 1).quat);
if (index)
*index = -1;
return;
}
s32 keyIndex = 0;
for (s32 i = 0; i < mConveyerKeyCount; i++) {
if (getConveyerKey(i).totalMoveDistance > coord) {
keyIndex = i;
break;
}
}
sead::Vector3f moveDistanceVertical = sead::Vector3f::zero;
sead::Quatf q = sead::Quatf::unit;
f32 moveDistance;
if (keyIndex < 1) {
const ConveyerKey& key = getConveyerKey(0);
moveDistanceVertical.set(key.moveDistanceVertical);
q.set(key.quat);
moveDistance = 0.0f;
} else {
const ConveyerKey& key = getConveyerKey(keyIndex);
const ConveyerKey& prevKey = getConveyerKey(keyIndex - 1);
sead::Vector3f prevKeyVec = prevKey.moveDistanceVertical;
sead::Vector3f keyVec = key.moveDistanceVertical;
f32 totalMoveDistance = key.totalMoveDistance - prevKey.totalMoveDistance;
f32 t;
if (isNearZero(totalMoveDistance))
t = 0.0f;
else
t = (coord - prevKey.totalMoveDistance) / totalMoveDistance;
f32 ease = easeByType(t, getConveyerKey(keyIndex - 1).interpolateType);
lerpVec(&moveDistanceVertical, prevKeyVec, keyVec, ease);
moveDistance = lerpValue(getConveyerKey(keyIndex - 1).moveDistance,
getConveyerKey(keyIndex).moveDistance, t);
sead::Quatf prevKeyQuat = getConveyerKey(keyIndex - 1).quat;
sead::Quatf keyQuat = getConveyerKey(keyIndex).quat;
slerpQuat(&q, prevKeyQuat, keyQuat, ease);
}
if (pos)
pos->set(moveDistance * mMoveDirection + mTrans + moveDistanceVertical);
if (quat)
quat->set(q);
if (index)
*index = keyIndex - 1;
return;
}
// Mismatch: The math is right, but the registers don't match
// probably inlined (and optimized) in a few other places
// https://decomp.me/scratch/kmQvB
void ConveyerKeyKeeper::calcPosAndQuatByKeyIndex(sead::Vector3f* pos, sead::Quatf* quat,
s32 index) const {
const ConveyerKey& key = getConveyerKey(index);
if (pos)
pos->set(key.moveDistance * mMoveDirection + mTrans + key.moveDistanceVertical);
if (quat)
quat->set(getConveyerKey(index).quat);
}
// Mismatch: Same as calcPosAndQuatByKeyIndex
// https://decomp.me/scratch/kmQvB
void ConveyerKeyKeeper::calcClippingSphere(sead::Vector3f* clippingTrans, f32* clippingRadius,
f32 offset) const {
if (clippingTrans) {
const ConveyerKey& key = getConveyerKey(0);
clippingTrans->set(key.moveDistance * mMoveDirection + mTrans + key.moveDistanceVertical);
}
*clippingRadius = offset;
for (s32 i = 1; i < mConveyerKeyCount; i++) {
const ConveyerKey& key = getConveyerKey(i);
sead::Vector3f pos = key.moveDistance * mMoveDirection + mTrans + key.moveDistanceVertical;
calcSphereMargeSpheres(clippingTrans, clippingRadius, *clippingTrans, *clippingRadius, pos,
offset);
}
}
const ConveyerKey& ConveyerKeyKeeper::getConveyerKey(s32 index) const {
return mConveyerKeys[index];
}
} // namespace al