mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-29 20:14:41 +00:00
176 lines
6 KiB
C++
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
|