mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-28 11:33:55 +00:00
533 lines
19 KiB
C++
533 lines
19 KiB
C++
#include "Library/Camera/CameraInterpole.h"
|
|
|
|
#include "Library/Camera/CameraPoser.h"
|
|
#include "Library/Camera/CameraPoserFlag.h"
|
|
#include "Library/Camera/CameraPoserFunction.h"
|
|
#include "Library/Camera/CameraTicket.h"
|
|
#include "Library/Math/MathUtil.h"
|
|
#include "Library/Nerve/NerveSetupUtil.h"
|
|
#include "Library/Nerve/NerveUtil.h"
|
|
#include "math/seadQuat.h"
|
|
|
|
namespace {
|
|
using namespace al;
|
|
NERVE_IMPL(CameraInterpole, Deactive);
|
|
NERVE_IMPL(CameraInterpole, ActiveRotateAxisY);
|
|
NERVE_IMPL(CameraInterpole, ActiveHermiteDistanceHV);
|
|
NERVE_IMPL(CameraInterpole, ActiveHermite);
|
|
// NERVE_IMPL(CameraInterpole, ActiveBrigade);
|
|
|
|
NERVES_MAKE_STRUCT(CameraInterpole, Deactive, ActiveRotateAxisY, ActiveHermiteDistanceHV,
|
|
ActiveHermite);
|
|
} // namespace
|
|
|
|
namespace al {
|
|
|
|
CameraInterpole::CameraInterpole() : NerveExecutor("カメラ補間") {
|
|
initNerve(&NrvCameraInterpole.Deactive, 0);
|
|
}
|
|
|
|
const f32 interpoleMinDistance = 150.0f;
|
|
const f32 interpoleMaxDistance = 2000.0f;
|
|
const f32 maxStepsNoEaseOut = 60.0f;
|
|
const f32 maxStepsEaseOut = 90.0f;
|
|
|
|
void CameraInterpole::start(const CameraTicket* ticket, f32 prevFovyDegree, s32 endInterpoleStep) {
|
|
_48.getPos() = _118.getPos();
|
|
_48.getAt() = _118.getAt();
|
|
_48.getUp() = _118.getUp();
|
|
_48.getUp().normalize();
|
|
|
|
if (mPrevPoser) {
|
|
mPrevPoser->setField98(false);
|
|
mPrevPoser = nullptr;
|
|
}
|
|
|
|
const CameraTicket* prevTicket = mNextTicket;
|
|
mNextTicket = ticket;
|
|
mPrevTicket = prevTicket;
|
|
mPrevFovyDegree = prevFovyDegree;
|
|
|
|
if (endInterpoleStep >= 0) {
|
|
mEndInterpoleStep = endInterpoleStep;
|
|
} else if (prevTicket->getPoser()->isEndInterpoleByStep()) {
|
|
mEndInterpoleStep = mPrevTicket->getPoser()->getEndInterpoleStep();
|
|
} else if (ticket->getPoser()->isInterpoleByCameraDistance()) {
|
|
f32 normalizedDistance =
|
|
normalize((_118.getPos() - ticket->getPoser()->getPosition()).length(),
|
|
interpoleMinDistance, interpoleMaxDistance);
|
|
f32 maxSteps =
|
|
ticket->getPoser()->isInterpoleEaseOut() ? maxStepsEaseOut : maxStepsNoEaseOut;
|
|
s32 interpoleSteps = (s32)lerpValue(30.0f, maxSteps, normalizedDistance);
|
|
|
|
sead::Vector3f prevCamDir = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f nextCamDir = {0.0f, 0.0f, 0.0f};
|
|
alCameraPoserFunction::calcCameraDir(&prevCamDir, mPrevTicket->getPoser());
|
|
alCameraPoserFunction::calcCameraDir(&nextCamDir, ticket->getPoser());
|
|
f32 yDiffDegrees = sead::Mathf::abs(sead::Mathf::rad2deg(sead::Mathf::asin(prevCamDir.y)) -
|
|
sead::Mathf::rad2deg(sead::Mathf::asin(nextCamDir.y)));
|
|
s32 yDiffInterpoleSteps = yDiffDegrees < 0.75f ? 0 : (int)(yDiffDegrees / 0.75f);
|
|
|
|
mEndInterpoleStep = sead::Mathi::max(interpoleSteps, yDiffInterpoleSteps);
|
|
} else {
|
|
mEndInterpoleStep = ticket->getPoser()->getInterpoleStep();
|
|
}
|
|
|
|
if (mEndInterpoleStep < 1 || mIsRequestCancel) {
|
|
mIsRequestCancel = false;
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
return;
|
|
}
|
|
|
|
if (mPrevTicket) {
|
|
if (!isActive() && !alCameraPoserFunction::isChangeTarget(mPrevTicket->getPoser()) &&
|
|
alCameraPoserFunction::isTargetEnableEndAfterInterpole(mPrevTicket->getPoser()) &&
|
|
!alCameraPoserFunction::isInvalidPreCameraEndAfterInterpole(ticket->getPoser())) {
|
|
if (mPrevTicket->getPoser() != ticket->getPoser()) {
|
|
mPrevPoser = mPrevTicket->getPoser();
|
|
mPrevPoser->setField98(true);
|
|
}
|
|
}
|
|
|
|
sead::Vector3f x =
|
|
mPrevTicket->getPoser()->getPosition() - mPrevTicket->getPoser()->getTargetTrans();
|
|
sead::Vector3f v45 =
|
|
ticket->getPoser()->getPosition() - ticket->getPoser()->getTargetTrans();
|
|
x.y = 0.0;
|
|
v45.y = 0.0;
|
|
if (tryNormalizeOrZero(&x) && tryNormalizeOrZero(&v45)) {
|
|
f32 v41 = calcAngleDegree(x, v45);
|
|
if (v41 > 105.0f) {
|
|
if (!ticket->getPoser()->isInterpoleByCameraDistance())
|
|
mEndInterpoleStep =
|
|
(int)lerpValue(60.0f, 90.0f, normalize(v41, 105.0f, 180.0f));
|
|
|
|
setNerve(this, &NrvCameraInterpole.ActiveRotateAxisY);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isNear(_3c_at, mNextTicket->getPoser()->getTargetTrans(), 250.0f) ||
|
|
(mNextTicket->getPoser()->getTargetTrans() - _3c_at)
|
|
.dot(mNextTicket->getPoser()->getPosition() - _30_pos) >= 0.0f)
|
|
setNerve(this, &NrvCameraInterpole.ActiveHermiteDistanceHV);
|
|
|
|
else
|
|
setNerve(this, &NrvCameraInterpole.ActiveHermite);
|
|
}
|
|
|
|
void CameraInterpole::update(const sead::LookAtCamera& camera) {
|
|
_178.getPos() = camera.getPos();
|
|
_178.getAt() = camera.getAt();
|
|
_178.getUp() = camera.getUp();
|
|
_178.getUp().normalize();
|
|
|
|
if (mIsRequestCancel) {
|
|
mIsRequestCancel = false;
|
|
if (isActive())
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
}
|
|
|
|
updateNerve();
|
|
if (isActive() && isNear(_30_pos, _3c_at, 0.001f)) {
|
|
_30_pos.set(_178.getPos());
|
|
_3c_at.set(_178.getAt());
|
|
_49_up.set(_178.getUp());
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
}
|
|
|
|
if (isActive() && mNextTicket) {
|
|
if ((mPrevTicket && !alCameraPoserFunction::isInvalidCollider(mPrevTicket->getPoser())) ||
|
|
!alCameraPoserFunction::isInvalidCollider(mNextTicket->getPoser()) ||
|
|
mNextTicket->getPoser()->getPoserFlag()->_c) {
|
|
sead::Vector3f v11v = _30_pos - _3c_at;
|
|
float v14 = v11v.length();
|
|
sead::Vector3f a2 = v11v;
|
|
normalize(&a2);
|
|
sead::Vector3f a3 = _49_up;
|
|
verticalizeVec(&a3, a2, a3);
|
|
if (tryNormalizeOrZero(&a3)) {
|
|
sead::Vector2f v54[5];
|
|
/* = {
|
|
sead::Vector2f::zero,
|
|
{-((75.0f / (v14 * sead::Mathf::pi2())) * 360.0f), 0.0f},
|
|
{(75.0f / (v14 * sead::Mathf::pi2())) * 360.0f, 0.0f},
|
|
{0.0f, -(15.0f / (v14 * sead::Mathf::pi2())) * 360.0f},
|
|
{0.0f, (15.0f / (v14 * sead::Mathf::pi2())) * 360.0f},
|
|
};*/
|
|
f32 p75 = (75.0f / (v14 * sead::Mathf::pi2())) * 360.0f;
|
|
f32 p15 = (15.0f / (v14 * sead::Mathf::pi2())) * 360.0f;
|
|
|
|
sead::Vector3f a1;
|
|
a1.setCross(a3, a2);
|
|
normalize(&a1);
|
|
|
|
// NON_MATCHING: order of loading/storing values
|
|
v54[0] = sead::Vector2f::zero;
|
|
v54[1] = {-p75, 0.0f};
|
|
v54[2] = {p75, 0.0f};
|
|
v54[3] = {0.0f, -p15};
|
|
v54[4] = {0.0f, p15};
|
|
|
|
bool v16 = false;
|
|
for (s32 i = 0; i != 5; i++) {
|
|
sead::Vector3f v53 = v11v;
|
|
rotateVectorDegree(&v53, v53, a3, v54[i].x);
|
|
rotateVectorDegree(&v53, v53, a1, v54[i].y);
|
|
alCameraPoserFunction::CameraCollisionHitResult v52;
|
|
v52.mCollisionLocation = 3;
|
|
|
|
if (alCameraPoserFunction::checkFirstCameraCollisionArrow(
|
|
&v52, mNextTicket->getPoser(), _3c_at, v53) &&
|
|
!v52.mCollisionLocation) {
|
|
sead::Vector3f v51 = v52.mCollisionHitPos - _30_pos;
|
|
sead::Vector3f v50 = {0.0f, 0.0f, 0.0f};
|
|
if (!isNearZero(v51, 0.001f)) {
|
|
// NON_MATCHING: somehow stores an unused boolean pair per result
|
|
// first: false;false
|
|
// second: true;false
|
|
// third: true;true
|
|
if (alCameraPoserFunction::checkFirstCameraCollisionArrow(
|
|
&v50, 0LL, mNextTicket->getPoser(), _30_pos, v51) ||
|
|
alCameraPoserFunction::checkFirstCameraCollisionArrow(
|
|
&v50, 0LL, mNextTicket->getPoser(), _30_pos + a1 * 10.0f,
|
|
v51) ||
|
|
alCameraPoserFunction::checkFirstCameraCollisionArrow(
|
|
&v50, 0LL, mNextTicket->getPoser(), _30_pos - a1 * 10.0f,
|
|
v51)) {
|
|
if ((_30_pos - v50).length() < 75.0f) {
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
sead::Vector3f v47 = v51;
|
|
float v33 = v51.length();
|
|
float v34 = v47.length();
|
|
if (v34 > 0.0)
|
|
v47 *= (v33 + 75.0f) / v34;
|
|
|
|
parallelizeVec(&v47, a2, v47);
|
|
float v36 = v47.length();
|
|
if (_1f0 < v36) {
|
|
v16 = true;
|
|
_1f4 = 0.0f;
|
|
_1f0 = sead::Mathf::min(v36, (v14 + -100.0f));
|
|
}
|
|
}
|
|
}
|
|
if (v16) {
|
|
makeLookAtCamera(&_118);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
float v37 = lerpValue(_1f4, 1.0f, 0.3f);
|
|
_1f4 = lerpValue(_1f4, v37, 0.3f);
|
|
// NON_MATCHING: order of loads/argument setup
|
|
f32 v38 = lerpValue(_1f0, 0.0f, _1f4 * 0.3f);
|
|
_1f0 = lerpValue(_1f0, v38, _1f4 * 0.3f);
|
|
float v44 = (_30_pos - _3c_at).length();
|
|
if ((v44 + -100.0f) < _1f0)
|
|
_1f0 = sead::Mathf::clampMax(_1f0, sead::Mathf::max(v44, (v44 + -100.0f)));
|
|
|
|
makeLookAtCamera(&_118);
|
|
}
|
|
|
|
bool CameraInterpole::isActive() const {
|
|
return !isNerve(this, &NrvCameraInterpole.Deactive);
|
|
}
|
|
|
|
void CameraInterpole::makeLookAtCamera(sead::LookAtCamera* camera) const {
|
|
sead::Vector3f v5v = {0.0f, 0.0f, 0.0f};
|
|
|
|
if (isActive() && _1f0 > 0.1f) {
|
|
v5v.set(_3c_at - _30_pos);
|
|
f32 v8 = v5v.length();
|
|
f32 f10 = _1f0;
|
|
f32 v9 = v5v.length();
|
|
if (v9 > 0.0f)
|
|
v5v *= sead::Mathf::min(v8 + -100.0f, f10) / v9;
|
|
}
|
|
|
|
camera->getPos() = _30_pos + v5v;
|
|
camera->getAt() = _3c_at;
|
|
camera->getUp() = _49_up;
|
|
camera->getUp().normalize();
|
|
}
|
|
|
|
void CameraInterpole::lerpFovyDegree(f32 a2) {
|
|
_1d8 = lerpValue(mPrevFovyDegree, mNextTicket->getPoser()->getFovyDegree(), a2);
|
|
}
|
|
|
|
void CameraInterpole::exeDeactive() {
|
|
if (isFirstStep(this)) {
|
|
if (mPrevPoser) {
|
|
mPrevPoser->setField98(false);
|
|
mPrevPoser = nullptr;
|
|
}
|
|
_1f0 = 0.0f;
|
|
}
|
|
|
|
_30_pos.set(_178.getPos());
|
|
_3c_at.set(_178.getAt());
|
|
_49_up.set(_178.getUp());
|
|
}
|
|
|
|
void sub_something(sead::Vector3f*, const sead::LookAtCamera&, const sead::LookAtCamera&,
|
|
sead::Vector3f, sead::Vector3f, f32);
|
|
|
|
void CameraInterpole::exeActiveHermite() {
|
|
sead::LookAtCamera* cam = &_48;
|
|
if (mPrevPoser) {
|
|
if (alCameraPoserFunction::isChangeTarget(mPrevPoser))
|
|
mPrevPoser = nullptr;
|
|
else {
|
|
mPrevPoser->movement();
|
|
mPrevPoser->calcCameraPose(cam);
|
|
}
|
|
}
|
|
|
|
CameraPoser* poser = mNextTicket->getPoser();
|
|
s32 v28 = mEndInterpoleStep;
|
|
f32 v8 = normalize(sead::Mathi::clampMin(getNerveStep(this) + 1, 1), 0, v28);
|
|
f32 v10 = hermiteRate(v8, 1.5f, 0.0f);
|
|
|
|
if (poser->isInterpoleEaseOut())
|
|
v10 = easeOut(v10);
|
|
|
|
lerpVec(&_30_pos, _48.getPos(), _178.getPos(), v10);
|
|
lerpVec(&_3c_at, _48.getAt(), _178.getAt(), v10);
|
|
|
|
sub_something(&_49_up, _48, _178, _30_pos, _3c_at, v10);
|
|
|
|
lerpFovyDegree(v10);
|
|
|
|
if (isGreaterEqualStep(this, mEndInterpoleStep - 1))
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
}
|
|
|
|
f32 cameraGetHAngle(const sead::LookAtCamera&);
|
|
|
|
void sub_something(sead::Vector3f* up, const sead::LookAtCamera& cam1,
|
|
const sead::LookAtCamera& cam2, sead::Vector3f pos, sead::Vector3f at,
|
|
f32 interpole) {
|
|
sead::StorageFor<sead::Quatf> quat;
|
|
sead::Vector3f back = at - pos;
|
|
if (tryNormalizeOrZero(&back) && !isParallelDirection(sead::Vector3f::ey, back, 0.01f)) {
|
|
sead::Vector3f side;
|
|
side.setCross(sead::Vector3f::ey, back);
|
|
normalize(&side);
|
|
rotateVectorDegree(up, sead::Vector3f::ey, side,
|
|
lerpValue(cameraGetHAngle(cam1), cameraGetHAngle(cam2), interpole));
|
|
return;
|
|
}
|
|
|
|
if (isNearDirection(cam1.getUp(), cam2.getUp(), 0.01f))
|
|
return;
|
|
|
|
quat.construct(sead::Quatf::unit);
|
|
makeQuatRotationRate(quat.data(), cam1.getUp(), cam2.getUp(), interpole);
|
|
up->setRotated(*quat.data(), cam1.getUp());
|
|
normalize(up);
|
|
}
|
|
|
|
const sead::Vector3f stru_something = {0.0f, 1.0f, 0.0f};
|
|
|
|
void CameraInterpole::exeActiveHermiteDistanceHV() {
|
|
sead::LookAtCamera* cam = &_48;
|
|
if (mPrevPoser) {
|
|
if (alCameraPoserFunction::isChangeTarget(mPrevPoser))
|
|
mPrevPoser = nullptr;
|
|
else {
|
|
mPrevPoser->movement();
|
|
mPrevPoser->calcCameraPose(cam);
|
|
}
|
|
}
|
|
|
|
CameraPoser* poser1 = mNextTicket->getPoser();
|
|
s32 v28_ = mEndInterpoleStep;
|
|
f32 v7 = normalize(sead::Mathi::clampMin(getNerveStep(this), 1), 0, v28_);
|
|
f32 v9 = hermiteRate(v7, 1.5f, 0.0f);
|
|
|
|
if (poser1->isInterpoleEaseOut())
|
|
v9 = easeOut(v9);
|
|
|
|
CameraPoser* poser2 = mNextTicket->getPoser();
|
|
s32 v28_2 = mEndInterpoleStep;
|
|
f32 v14 = normalize(sead::Mathi::clampMin(getNerveStep(this) + 1, 1), 0, v28_2);
|
|
f32 v16 = hermiteRate(v14, 1.5f, 0.0f);
|
|
|
|
if (poser2->isInterpoleEaseOut())
|
|
v16 = easeOut(v16);
|
|
|
|
sead::Vector3f a3 = _30_pos - _3c_at;
|
|
verticalizeVec(&a3, stru_something, a3);
|
|
if (!tryNormalizeOrZero(&a3)) {
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
return;
|
|
}
|
|
|
|
lerpVec(&_3c_at, _48.getAt(), _178.getAt(), v16);
|
|
|
|
sead::Vector3f x = _48.getPos() - _48.getAt();
|
|
sead::Vector3f a1 = _178.getPos() - _178.getAt();
|
|
|
|
f32 v25 = lerpValue(x.length(), a1.length(), v16);
|
|
|
|
tryNormalizeOrZero(&a1);
|
|
if (!tryNormalizeOrZero(&x))
|
|
x.set(a1);
|
|
|
|
f32 v28 = lerpValue(sead::Mathf::rad2deg(sead::Mathf::asin(x.y)),
|
|
sead::Mathf::rad2deg(sead::Mathf::asin(a1.y)), v16);
|
|
|
|
verticalizeVec(&a1, stru_something, a1);
|
|
tryNormalizeOrZero(&a1);
|
|
if (!isNormalize(a1, 0.001f)) {
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
return;
|
|
}
|
|
|
|
sead::Vector3f v49 = {0.0f, 0.0f, 0.0f};
|
|
turnVecToVecRate(&v49, a3, a1, normalize(v16 - v9, 0.0f, 1.0f - v9));
|
|
normalize(&v49);
|
|
|
|
sead::Vector3f v333435 = sead::Mathf::cos(sead::Mathf::deg2rad(v28)) * v49;
|
|
v49 = v333435 + sead::Mathf::sin(sead::Mathf::deg2rad(v28)) * sead::Vector3f{0.0f, 1.0f, 0.0f};
|
|
normalize(&v49);
|
|
|
|
_30_pos = (v25 * v49) + _3c_at;
|
|
|
|
// NON_MATCHING: Stores reference to _178 in local variable
|
|
sub_something(&_49_up, _48, _178, _30_pos, _3c_at, v16);
|
|
|
|
lerpFovyDegree(v16);
|
|
|
|
if (isGreaterEqualStep(this, mEndInterpoleStep - 1))
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
}
|
|
|
|
void CameraInterpole::exeActiveRotateAxisY() {
|
|
sead::LookAtCamera* cam = &_48;
|
|
if (mPrevPoser) {
|
|
if (alCameraPoserFunction::isChangeTarget(mPrevPoser))
|
|
mPrevPoser = nullptr;
|
|
else {
|
|
mPrevPoser->movement();
|
|
mPrevPoser->calcCameraPose(cam);
|
|
}
|
|
}
|
|
|
|
CameraPoser* poser = mNextTicket->getPoser();
|
|
s32 v28_ = mEndInterpoleStep;
|
|
f32 v8 = normalize(sead::Mathi::clampMin(getNerveStep(this) + 1, 1), 0, v28_);
|
|
f32 v10 = hermiteRate(v8, 1.5f, 0.0f);
|
|
|
|
if (poser->isInterpoleEaseOut())
|
|
v10 = easeOut(v10);
|
|
|
|
lerpVec(&_3c_at, _48.getAt(), _178.getAt(), v10);
|
|
|
|
sead::Vector3f v47 = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f a1 = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f a3 = _48.getPos() - _48.getAt();
|
|
normalize(&a3);
|
|
v47.set(a3);
|
|
verticalizeVec(&a1, sead::Vector3f::ey, a3);
|
|
normalize(&a1);
|
|
|
|
sead::Vector3f v45 = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f v44 = {0.0f, 0.0f, 0.0f};
|
|
a3 = _178.getPos() - _178.getAt();
|
|
normalize(&a3);
|
|
v45.set(a3);
|
|
verticalizeVec(&v44, sead::Vector3f::ey, a3);
|
|
normalize(&v44);
|
|
|
|
if (isFirstStep(this)) {
|
|
mAngleRotateY = 0.0f;
|
|
_1e4.set(a1);
|
|
}
|
|
|
|
mAngleRotateY += calcAngleOnPlaneDegree(_1e4, v44, sead::Vector3f::ey);
|
|
a3.set(a1);
|
|
rotateVectorDegreeY(&a3, mAngleRotateY);
|
|
|
|
mAngleRotateY += calcAngleOnPlaneDegree(a3, v44, sead::Vector3f::ey);
|
|
a3.set(a1);
|
|
rotateVectorDegreeY(&a3, v10 * mAngleRotateY);
|
|
|
|
_1e4.set(v44);
|
|
|
|
sead::Vector3f v43 = a3.cross(sead::Vector3f::ey);
|
|
f32 v18 = calcAngleOnPlaneDegree(a1, v47, a1.cross(sead::Vector3f::ey));
|
|
f32 v19 = calcAngleOnPlaneDegree(v44, v45, v44.cross(sead::Vector3f::ey));
|
|
f32 v20 = lerpValue(v18, v19, v10);
|
|
sead::Vector3f v42;
|
|
v42.set(a3);
|
|
rotateVectorDegree(&v42, v42, v43, v20);
|
|
|
|
f32 v28 = lerpValue((_48.getPos() - _3c_at).length(), (_178.getPos() - _3c_at).length(), v10);
|
|
_30_pos.setScaleAdd(v28, v42, _3c_at);
|
|
|
|
sub_something(&_49_up, _48, _178, _30_pos, _3c_at, v10);
|
|
|
|
lerpFovyDegree(v10);
|
|
|
|
if (isGreaterEqualStep(this, mEndInterpoleStep - 1))
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
}
|
|
|
|
void CameraInterpole::exeActiveBrigade() {
|
|
if (mPrevPoser) {
|
|
if (alCameraPoserFunction::isChangeTarget(mPrevPoser))
|
|
mPrevPoser = nullptr;
|
|
else {
|
|
sead::LookAtCamera* cam = &_48;
|
|
mPrevPoser->movement();
|
|
mPrevPoser->calcCameraPose(cam);
|
|
}
|
|
}
|
|
|
|
s32 v28 = mEndInterpoleStep;
|
|
f32 v7 = normalize(sead::Mathi::clampMin(getNerveStep(this) + 1, 1), 0, v28);
|
|
f32 v9 = easeInOut(v7);
|
|
|
|
lerpVec(&_30_pos, _48.getPos(), _178.getPos(), v9);
|
|
lerpVec(&_3c_at, _48.getAt(), _178.getAt(), v9);
|
|
|
|
f32 v10 = calcAngleDegree(_48.getUp(), _178.getUp());
|
|
if (isReverseDirection(_48.getUp(), _178.getUp(), 0.01f)) {
|
|
sead::Vector3f v19 = {0.0f, 0.0f, 0.0f};
|
|
calcDirVerticalAny(&v19, _48.getUp());
|
|
sead::Vector3f v17 = _48.getUp();
|
|
rotateVectorDegree(&v17, v17, v19, v9 * v10);
|
|
_49_up.set(v17);
|
|
} else {
|
|
turnVecToVecDegree(&_49_up, _48.getUp(), _178.getUp(), v9 * v10);
|
|
}
|
|
|
|
lerpFovyDegree(v9);
|
|
|
|
if (isGreaterEqualStep(this, mEndInterpoleStep - 1))
|
|
setNerve(this, &NrvCameraInterpole.Deactive);
|
|
}
|
|
|
|
f32 cameraGetHAngle(const sead::LookAtCamera& camera) {
|
|
// back = -front
|
|
sead::Vector3f back = camera.getAt() - camera.getPos();
|
|
if (!tryNormalizeOrZero(&back))
|
|
return 0.0f;
|
|
|
|
sead::Vector3f side = camera.getUp().cross(back);
|
|
normalize(&side);
|
|
return calcAngleOnPlaneDegree(sead::Vector3f::ey, camera.getUp(), side);
|
|
}
|
|
|
|
} // namespace al
|