mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-05-10 17:29:13 +00:00
178 lines
6.9 KiB
C++
178 lines
6.9 KiB
C++
#include "Library/Play/Camera/CameraVerticalAbsorber.h"
|
|
|
|
#include <gfx/seadViewport.h>
|
|
|
|
#include "Library/Camera/CameraPoser.h"
|
|
#include "Library/Camera/CameraPoserFunction.h"
|
|
#include "Library/Camera/CameraStartInfo.h"
|
|
#include "Library/Math/MathUtil.h"
|
|
#include "Library/Nerve/NerveSetupUtil.h"
|
|
#include "Library/Nerve/NerveUtil.h"
|
|
#include "Library/Screen/ScreenFunction.h"
|
|
#include "Library/Yaml/ByamlUtil.h"
|
|
|
|
namespace {
|
|
using namespace al;
|
|
NERVE_IMPL(CameraVerticalAbsorber, FollowGround);
|
|
NERVE_IMPL(CameraVerticalAbsorber, FollowAbsolute);
|
|
NERVE_IMPL_(CameraVerticalAbsorber, FollowClimbPoleNoInterp, FollowClimbPole);
|
|
NERVE_IMPL_(CameraVerticalAbsorber, FollowSlow, Follow);
|
|
NERVE_IMPL(CameraVerticalAbsorber, Absorb);
|
|
NERVE_IMPL(CameraVerticalAbsorber, Follow);
|
|
NERVE_IMPL(CameraVerticalAbsorber, FollowClimbPole);
|
|
|
|
NERVES_MAKE_STRUCT(CameraVerticalAbsorber, FollowGround, FollowAbsolute, FollowClimbPoleNoInterp,
|
|
FollowSlow, Absorb, Follow, FollowClimbPole);
|
|
} // namespace
|
|
|
|
namespace al {
|
|
CameraVerticalAbsorber::CameraVerticalAbsorber(const CameraPoser* cameraParent,
|
|
bool isCameraPosAbsorb)
|
|
: NerveExecutor("カメラの縦パン"), mCameraPoser(cameraParent),
|
|
mIsNoCameraPosAbsorb(isCameraPosAbsorb) {
|
|
initNerve(&NrvCameraVerticalAbsorber.FollowGround);
|
|
}
|
|
|
|
void CameraVerticalAbsorber::load(const ByamlIter& iter) {
|
|
ByamlIter verticalAbsorbIter;
|
|
if (!iter.tryGetIterByKey(&verticalAbsorbIter, "VerticalAbsorb"))
|
|
return;
|
|
|
|
tryGetByamlF32(&mAbsorbScreenPosUp, verticalAbsorbIter, "AbsorbScreenPosUp");
|
|
tryGetByamlF32(&mAbsorbScreenPosDown, verticalAbsorbIter, "AbsorbScreenPosDown");
|
|
tryGetByamlF32(&mHighJumpJudgeSpeedV, verticalAbsorbIter, "HighJumpJudgeSpeedV");
|
|
|
|
ByamlIter advanceAbsorbUpIter;
|
|
if (verticalAbsorbIter.tryGetIterByKey(&advanceAbsorbUpIter, "AdvanceAbsorbUp")) {
|
|
mIsAdvanceAbsorbUp = true;
|
|
mAdvanceAbsorbScreenPosUp =
|
|
getByamlKeyFloat(advanceAbsorbUpIter, "AdvanceAbsorbScreenPosUp");
|
|
}
|
|
}
|
|
|
|
void CameraVerticalAbsorber::start(const sead::Vector3f& pos, const CameraStartInfo& info) {
|
|
alCameraPoserFunction::calcTargetFront(&mPrevTargetFront, mCameraPoser);
|
|
|
|
mAbsorbVec = {0.0f, 0.0f, 0.0f};
|
|
mPrevTargetTrans.set(pos);
|
|
|
|
if (!isValid() || alCameraPoserFunction::isPlayerTypeNotTouchGround(mCameraPoser))
|
|
return setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute);
|
|
|
|
if (alCameraPoserFunction::isTargetClimbPole(mCameraPoser))
|
|
return setNerve(this, &NrvCameraVerticalAbsorber.FollowClimbPoleNoInterp);
|
|
|
|
if (alCameraPoserFunction::isTargetGrabCeil(mCameraPoser))
|
|
return setNerve(this, &NrvCameraVerticalAbsorber.FollowSlow);
|
|
|
|
if (!info._25 || alCameraPoserFunction::isTargetCollideGround(mCameraPoser))
|
|
return setNerve(this, &NrvCameraVerticalAbsorber.FollowGround);
|
|
|
|
mPrevTargetTrans.set(alCameraPoserFunction::getPreLookAtPos(mCameraPoser));
|
|
|
|
const CameraPoser* poser = mCameraPoser;
|
|
sead::Vector3f gravity = {0.0f, 0.0f, 0.0f};
|
|
alCameraPoserFunction::calcTargetGravity(&gravity, poser);
|
|
|
|
mAbsorbVec = pos - mPrevTargetTrans;
|
|
parallelizeVec(&mAbsorbVec, gravity, mAbsorbVec);
|
|
setNerve(this, &NrvCameraVerticalAbsorber.Absorb);
|
|
}
|
|
|
|
bool CameraVerticalAbsorber::isValid() const {
|
|
return !_1aa && !mIsInvalidated;
|
|
}
|
|
|
|
inline void updateAbsorbVec(sead::Vector3f* absorbVec, const CameraPoser* poser,
|
|
const sead::Vector3f& prevTrans) {
|
|
sead::Vector3f gravity = {0.0f, 0.0f, 0.0f};
|
|
alCameraPoserFunction::calcTargetGravity(&gravity, poser);
|
|
*absorbVec = poser->getTargetTrans() - prevTrans;
|
|
parallelizeVec(absorbVec, gravity, *absorbVec);
|
|
}
|
|
|
|
void CameraVerticalAbsorber::update() {
|
|
if (mIsStopUpdate)
|
|
return;
|
|
|
|
updateAbsorbVec(&mAbsorbVec, mCameraPoser, mPrevTargetTrans);
|
|
|
|
mLookAtCamera.setPos(mCameraPoser->getPosition());
|
|
mLookAtCamera.setAt(mCameraPoser->getTargetTrans());
|
|
mLookAtCamera.setUp(mCameraPoser->getCameraUp());
|
|
mLookAtCamera.normalizeUp();
|
|
|
|
makeLookAtCamera(&mLookAtCamera);
|
|
mLookAtCamera.updateViewMatrix();
|
|
mProjection.set(alCameraPoserFunction::getNear(mCameraPoser),
|
|
alCameraPoserFunction::getFar(mCameraPoser),
|
|
sead::Mathf::deg2rad(mCameraPoser->getFovyDegree()),
|
|
alCameraPoserFunction::getAspect(mCameraPoser));
|
|
|
|
alCameraPoserFunction::calcTargetFront(&mTargetFront, mCameraPoser);
|
|
|
|
if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowGround) &&
|
|
alCameraPoserFunction::isTargetCollideGround(mCameraPoser))
|
|
setNerve(this, &NrvCameraVerticalAbsorber.FollowGround);
|
|
if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute) &&
|
|
alCameraPoserFunction::isPlayerTypeNotTouchGround(mCameraPoser))
|
|
setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute);
|
|
updateNerve();
|
|
|
|
sead::Vector3f offset = {0.0f, 0.0f, 0.0f};
|
|
if (mIsKeepInFrame) {
|
|
sead::Vector3f offsetTrans = {0.0f, 0.0f, 0.0f};
|
|
alCameraPoserFunction::calcTargetTransWithOffset(&offsetTrans, mCameraPoser);
|
|
|
|
alCameraPoserFunction::calcOffsetCameraKeepInFrameV(
|
|
&offset, &mLookAtCamera, offsetTrans, mCameraPoser, mKeepInFrameOffsetUp,
|
|
alCameraPoserFunction::isPlayerTypeHighJump(mCameraPoser) ? 300.0f :
|
|
mKeepInFrameOffsetDown);
|
|
mAbsorbVec -= offset;
|
|
}
|
|
mPrevTargetTrans.set(mCameraPoser->getTargetTrans() - mAbsorbVec);
|
|
mPrevTargetFront.set(mTargetFront);
|
|
}
|
|
|
|
void CameraVerticalAbsorber::makeLookAtCamera(sead::LookAtCamera* lookAtCamera) const {
|
|
if (!isValid())
|
|
return;
|
|
|
|
lookAtCamera->setAt(lookAtCamera->getAt() - mAbsorbVec);
|
|
if (!mIsNoCameraPosAbsorb)
|
|
lookAtCamera->setPos(lookAtCamera->getPos() - mAbsorbVec);
|
|
}
|
|
|
|
void CameraVerticalAbsorber::liberateAbsorb() {
|
|
if (isNerve(this, &NrvCameraVerticalAbsorber.Absorb))
|
|
setNerve(this, &NrvCameraVerticalAbsorber.Follow);
|
|
}
|
|
|
|
bool CameraVerticalAbsorber::isAbsorbing() const {
|
|
return isValid() && isNerve(this, &NrvCameraVerticalAbsorber.Absorb);
|
|
}
|
|
|
|
void CameraVerticalAbsorber::invalidate() {
|
|
mIsInvalidated = true;
|
|
if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute))
|
|
setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute);
|
|
}
|
|
|
|
void CameraVerticalAbsorber::tryResetAbsorbVecIfInCollision(const sead::Vector3f& pos) {
|
|
if (!alCameraPoserFunction::checkFirstCameraCollisionArrow(nullptr, nullptr, mCameraPoser,
|
|
pos + mAbsorbVec, -mAbsorbVec))
|
|
return;
|
|
|
|
mAbsorbVec = {0.0f, 0.0f, 0.0f};
|
|
if (alCameraPoserFunction::isTargetCollideGround(mCameraPoser))
|
|
setNerve(this, &NrvCameraVerticalAbsorber.FollowGround);
|
|
else
|
|
setNerve(this, &NrvCameraVerticalAbsorber.Follow);
|
|
}
|
|
|
|
void CameraVerticalAbsorber::exeFollowAbsolute() {
|
|
mAbsorbVec *= 0.8f;
|
|
}
|
|
|
|
} // namespace al
|