mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-23 09:04:21 +00:00
692 lines
23 KiB
C++
692 lines
23 KiB
C++
#include "Library/LiveActor/ActorCollisionFunction.h"
|
|
|
|
#include "Library/Base/StringUtil.h"
|
|
#include "Library/Collision/Collider.h"
|
|
#include "Library/Collision/CollisionDirector.h"
|
|
#include "Library/Collision/CollisionParts.h"
|
|
#include "Library/Collision/CollisionPartsKeeperUtil.h"
|
|
#include "Library/Collision/CollisionPartsTriangle.h"
|
|
#include "Library/Collision/ICollisionPartsKeeper.h"
|
|
#include "Library/Collision/KCollisionServer.h"
|
|
#include "Library/LiveActor/ActorMovementFunction.h"
|
|
#include "Library/LiveActor/ActorPoseUtil.h"
|
|
#include "Library/LiveActor/LiveActor.h"
|
|
#include "Library/Math/MathUtil.h"
|
|
#include "Project/Collision/ActorCollisionController.h"
|
|
|
|
namespace al {
|
|
|
|
Collider* getActorCollider(const LiveActor* actor) {
|
|
return actor->getCollider();
|
|
}
|
|
|
|
bool isExistActorCollider(const LiveActor* actor) {
|
|
return actor->getCollider() != nullptr;
|
|
}
|
|
|
|
const HitSensor* getActorCollisionPartsSensor(const LiveActor* actor) {
|
|
return actor->getCollisionParts()->getConnectedSensor();
|
|
}
|
|
|
|
bool isExistCollisionParts(const LiveActor* actor) {
|
|
return actor->getCollisionParts() != nullptr;
|
|
}
|
|
|
|
bool isEqualCollisionParts(const LiveActor* actor, const CollisionParts* collisionParts) {
|
|
return collisionParts && actor->getCollisionParts() == collisionParts;
|
|
}
|
|
|
|
void validateCollisionParts(LiveActor* actor) {
|
|
CollisionParts* collisionParts = actor->getCollisionParts();
|
|
if (collisionParts->getSyncCollisonMtx()) {
|
|
collisionParts->resetAllMtx();
|
|
} else {
|
|
sead::Matrix34f mtx;
|
|
makeMtxSRT(&mtx, actor);
|
|
collisionParts->resetAllMtx(mtx);
|
|
}
|
|
collisionParts->validateByUser();
|
|
}
|
|
|
|
void invalidateCollisionParts(LiveActor* actor) {
|
|
actor->getCollisionParts()->invalidateByUser();
|
|
}
|
|
|
|
void validateCollisionPartsBySystem(LiveActor* actor) {
|
|
CollisionParts* collisionParts = actor->getCollisionParts();
|
|
collisionParts->validateBySystem();
|
|
|
|
if (collisionParts->getSyncCollisonMtx()) {
|
|
collisionParts->resetAllMtx();
|
|
} else {
|
|
sead::Matrix34f mtx;
|
|
makeMtxSRT(&mtx, actor);
|
|
collisionParts->resetAllMtx(mtx);
|
|
}
|
|
}
|
|
|
|
void invalidateCollisionPartsBySystem(LiveActor* actor) {
|
|
actor->getCollisionParts()->invalidateBySystem();
|
|
}
|
|
|
|
bool isValidCollisionParts(const LiveActor* actor) {
|
|
return actor->getCollisionParts()->isValidCollision();
|
|
}
|
|
|
|
void setCollisionPartsSpecialPurposeName(LiveActor* actor, const char* name) {
|
|
actor->getCollisionParts()->setSpecialPurpose(name);
|
|
}
|
|
|
|
void resetAllCollisionMtx(LiveActor* actor) {
|
|
CollisionParts* collisionParts = actor->getCollisionParts();
|
|
|
|
if (collisionParts->getSyncCollisonMtx()) {
|
|
collisionParts->resetAllMtx();
|
|
} else {
|
|
sead::Matrix34f mtx;
|
|
makeMtxSRT(&mtx, actor);
|
|
collisionParts->resetAllMtx(mtx);
|
|
}
|
|
|
|
alCollisionUtil::getCollisionPartsKeeper(actor)->resetToCollisionPartsList(collisionParts);
|
|
}
|
|
|
|
void syncCollisionMtx(LiveActor* actor, const sead::Matrix34f* mtx) {
|
|
syncCollisionMtx(actor, actor->getCollisionParts(), mtx);
|
|
}
|
|
|
|
void syncCollisionMtx(LiveActor* actor, CollisionParts* collisionParts,
|
|
const sead::Matrix34f* mtx) {
|
|
if (!collisionParts->isValidCollision())
|
|
return;
|
|
|
|
if (collisionParts->getSyncCollisonMtx()) {
|
|
collisionParts->syncMtx();
|
|
} else if (mtx) {
|
|
collisionParts->syncMtx(*mtx);
|
|
} else {
|
|
sead::Matrix34f newMtx;
|
|
makeMtxSRT(&newMtx, actor);
|
|
collisionParts->syncMtx(newMtx);
|
|
}
|
|
}
|
|
|
|
void setSyncCollisionMtxPtr(LiveActor* actor, const sead::Matrix34f* mtx) {
|
|
actor->getCollisionParts()->setSyncCollisionMtx(mtx);
|
|
}
|
|
|
|
bool isOnGround(const LiveActor* actor, u32 coyoteTime) {
|
|
Collider* collider = actor->getCollider();
|
|
if (!isCollidedGround(actor) && collider->getNoGroundCounter() > coyoteTime)
|
|
return false;
|
|
return !(getVelocity(actor).dot(collider->getRecentOnGroundNormal(coyoteTime)) > 0.0f);
|
|
}
|
|
|
|
bool isOnGroundFace(const LiveActor* actor) {
|
|
return isOnGround(actor, 0) && !isCollidedGroundEdgeOrCorner(actor);
|
|
}
|
|
|
|
bool isCollidedGroundEdgeOrCorner(const LiveActor* actor) {
|
|
return isCollidedGround(actor) && !actor->getCollider()->getFloorHit().isCollisionAtFace();
|
|
}
|
|
|
|
bool isOnGroundNoVelocity(const LiveActor* actor, u32 coyoteTime) {
|
|
if (!isExistActorCollider(actor))
|
|
return getTrans(actor).y <= 0.0f;
|
|
|
|
if (isCollidedGround(actor))
|
|
return true;
|
|
|
|
return actor->getCollider()->getNoGroundCounter() <= coyoteTime;
|
|
}
|
|
|
|
bool isOnGroundDegree(const LiveActor* actor, f32 angle, u32 coyoteTime) {
|
|
Collider* collider = actor->getCollider();
|
|
if (!(isCollidedGround(actor) || collider->getNoGroundCounter() <= coyoteTime))
|
|
return false;
|
|
|
|
if (sead::Mathf::abs(
|
|
(*collider->getActorGravityPtr()).dot(collider->getRecentOnGroundNormal(coyoteTime))) <
|
|
sead::Mathf::cos(sead::Mathf::deg2rad(angle)))
|
|
return false;
|
|
|
|
return !(getVelocity(actor).dot(collider->getRecentOnGroundNormal(coyoteTime)) > 0.0f);
|
|
}
|
|
|
|
bool isOnGroundFaceDegree(const LiveActor* actor, f32 angle) {
|
|
return isOnGroundDegree(actor, angle, 0) && !isCollidedGroundEdgeOrCorner(actor);
|
|
}
|
|
|
|
bool isOnGroundNoVelocityDegree(const LiveActor* actor, f32 angle, u32 coyoteTime) {
|
|
Collider* collider = actor->getCollider();
|
|
if (!collider)
|
|
return getTrans(actor).y <= 0.0;
|
|
|
|
if (!(isCollidedGround(actor) || collider->getNoGroundCounter() <= coyoteTime))
|
|
return false;
|
|
|
|
if (sead::Mathf::abs(
|
|
(*collider->getActorGravityPtr()).dot(collider->getRecentOnGroundNormal(coyoteTime))) <
|
|
sead::Mathf::cos(sead::Mathf::deg2rad(angle)))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
const sead::Vector3f& getOnGroundNormal(const LiveActor* actor, u32 offset) {
|
|
return actor->getCollider()->getRecentOnGroundNormal(offset);
|
|
}
|
|
|
|
void setColliderRadius(LiveActor* actor, f32 radius) {
|
|
actor->getCollider()->setRadius(radius);
|
|
}
|
|
|
|
void setColliderOffsetY(LiveActor* actor, f32 offsety) {
|
|
actor->getCollider()->setOffsetY(offsety);
|
|
}
|
|
|
|
f32 getColliderRadius(const LiveActor* actor) {
|
|
return actor->getCollider()->getRadius();
|
|
}
|
|
|
|
f32 getColliderOffsetY(const LiveActor* actor) {
|
|
return actor->getCollider()->getOffsetY();
|
|
}
|
|
|
|
const sead::Vector3f& getColliderFixReaction(const LiveActor* actor) {
|
|
return actor->getCollider()->getFixReaction();
|
|
}
|
|
|
|
void calcColliderPos(sead::Vector3f* outPos, const LiveActor* actor) {
|
|
actor->getCollider()->calcCheckPos(outPos);
|
|
}
|
|
|
|
void validateColliderRobustCheck(LiveActor* actor) {
|
|
actor->getCollider()->validateRobustCheck();
|
|
}
|
|
|
|
void invalidateColliderRobustCheck(LiveActor* actor) {
|
|
actor->getCollider()->invalidateRobustCheck();
|
|
}
|
|
|
|
void setColliderReactMovePower(LiveActor* actor, bool isEnabled) {
|
|
actor->getCollider()->setReactMovePower(isEnabled);
|
|
}
|
|
|
|
void calcColliderFloorRotatePower(sead::Quatf* outRotatePower, LiveActor* actor) {
|
|
actor->getCollider()->getFloorHit().triangle.calcForceRotatePower(outRotatePower);
|
|
}
|
|
|
|
void calcJumpInertia(sead::Vector3f* outJumpInertia, LiveActor* actor,
|
|
const sead::Vector3f& velocityDir, f32 force) {
|
|
if (!isCollidedGround(actor)) {
|
|
outJumpInertia->set({0.0f, 0.0f, 0.0f});
|
|
return;
|
|
}
|
|
|
|
sead::Vector3f movePower = {0.0f, 0.0f, 0.0f};
|
|
const HitInfo& floorHit = actor->getCollider()->getFloorHit();
|
|
if (floorHit.triangle.getCollisionParts() && floorHit.triangle.isHostMoved())
|
|
floorHit.triangle.calcForceMovePower(&movePower, getTrans(actor));
|
|
|
|
verticalizeVec(&movePower, getGravity(actor), movePower);
|
|
|
|
sead::Vector3f hMoveDir = movePower;
|
|
tryNormalizeOrZero(&hMoveDir);
|
|
|
|
sead::Vector3f hVelDir = {0.0f, 0.0f, 0.0f};
|
|
verticalizeVec(&hVelDir, getGravity(actor), velocityDir);
|
|
if (!tryNormalizeOrZero(&hVelDir)) {
|
|
outJumpInertia->set(movePower * force);
|
|
return;
|
|
}
|
|
|
|
force *= sead::Mathf::clampMin(hMoveDir.dot(hVelDir), 0.0f);
|
|
outJumpInertia->set(movePower * force);
|
|
}
|
|
|
|
bool isCollidedGround(const LiveActor* actor) {
|
|
return actor->getCollider()->get_110() >= 0.0f;
|
|
}
|
|
|
|
void calcJumpInertiaWall(sead::Vector3f* outJumpInertia, LiveActor* actor, f32 force) {
|
|
if (!isCollidedWall(actor)) {
|
|
outJumpInertia->set({0.0f, 0.0f, 0.0f});
|
|
return;
|
|
}
|
|
|
|
sead::Vector3f movePower = {0.0f, 0.0f, 0.0f};
|
|
const sead::Vector3f& trans = getTrans(actor);
|
|
const HitInfo& floorHit = actor->getCollider()->getWallHit();
|
|
|
|
if (floorHit.triangle.getCollisionParts() && alCollisionUtil::isCollisionMoving(&floorHit))
|
|
floorHit.triangle.calcForceMovePower(&movePower, trans);
|
|
|
|
verticalizeVec(&movePower, getGravity(actor), movePower);
|
|
|
|
outJumpInertia->set(movePower * force);
|
|
}
|
|
|
|
bool isCollidedWall(const LiveActor* actor) {
|
|
return actor->getCollider()->get_1b8() >= 0.0f;
|
|
}
|
|
|
|
// TODO: probably a sead function?
|
|
inline f32 normalize2(sead::Vector3f* v, f32 scalar) {
|
|
const f32 len = v->length();
|
|
if (len > 0) {
|
|
const f32 inv_len = scalar / len;
|
|
v->x *= inv_len;
|
|
v->y *= inv_len;
|
|
v->z *= inv_len;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
void scaleVelocityInertiaWallHit(LiveActor* actor, f32 velocityScaleH, f32 maxVelocityH,
|
|
f32 maxScaledVelocityH) {
|
|
if (!isCollidedWall(actor))
|
|
return;
|
|
|
|
sead::Vector3f faceNormal = getCollidedWallNormal(actor);
|
|
verticalizeVec(&faceNormal, getGravity(actor), faceNormal);
|
|
if (!tryNormalizeOrZero(&faceNormal))
|
|
return;
|
|
|
|
sead::Vector3f jumpInertia = {0.0f, 0.0f, 0.0f};
|
|
calcJumpInertiaWall(&jumpInertia, actor, 1.0f);
|
|
|
|
sead::Vector3f velocityH = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f velocityV = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityHV(&velocityH, &velocityV, actor);
|
|
|
|
sead::Vector3f velocityDirH = {0.0f, 0.0f, 0.0f};
|
|
tryNormalizeOrZero(&velocityDirH, velocityH);
|
|
|
|
if (velocityDirH.dot(faceNormal) < -0.5f) {
|
|
f32 speedH = velocityH.length();
|
|
f32 scaledVelocity = speedH * velocityScaleH;
|
|
f32 newSpeedH = sead::Mathf::clamp(scaledVelocity, sead::Mathf::min(speedH, maxVelocityH),
|
|
maxScaledVelocityH);
|
|
|
|
normalize2(&velocityH, newSpeedH);
|
|
|
|
f32 newVelocityH = jumpInertia.dot(velocityDirH);
|
|
if (-newVelocityH < faceNormal.dot(velocityDirH))
|
|
normalize2(&velocityH, newVelocityH);
|
|
}
|
|
|
|
setVelocity(actor, velocityH + velocityV);
|
|
}
|
|
|
|
const sead::Vector3f& getCollidedWallNormal(const LiveActor* actor) {
|
|
return actor->getCollider()->getWallHit().triangle.getFaceNormal();
|
|
}
|
|
|
|
void calcCollidedNormalSum(const LiveActor* actor, sead::Vector3f* outNormal) {
|
|
outNormal->set({0.0f, 0.0f, 0.0f});
|
|
Collider* collider = actor->getCollider();
|
|
|
|
if (collider->get_110() >= 0.0f)
|
|
outNormal->add(collider->getFloorHit().triangle.getFaceNormal());
|
|
|
|
if (collider->get_1b8() >= 0.0f)
|
|
outNormal->add(collider->getWallHit().triangle.getFaceNormal());
|
|
|
|
if (collider->get_260() >= 0.0f)
|
|
outNormal->add(collider->getCeilingHit().triangle.getFaceNormal());
|
|
|
|
*outNormal *= 1.0f / 3.0f;
|
|
}
|
|
|
|
void calcGroundNormalOrUpDir(sead::Vector3f* outDir, const LiveActor* actor) {
|
|
if (isCollidedGround(actor))
|
|
*outDir = getCollidedGroundNormal(actor);
|
|
else
|
|
calcUpDir(outDir, actor);
|
|
}
|
|
|
|
const sead::Vector3f& getCollidedGroundNormal(const LiveActor* actor) {
|
|
return actor->getCollider()->getFloorHit().triangle.getFaceNormal();
|
|
}
|
|
|
|
void calcGroundNormalOrGravityDir(sead::Vector3f* outDir, const LiveActor* actor) {
|
|
if (isCollidedGround(actor))
|
|
*outDir = getCollidedGroundNormal(actor);
|
|
else
|
|
*outDir = -getGravity(actor);
|
|
}
|
|
|
|
void setColliderFilterTriangle(LiveActor* actor, const TriangleFilterBase* triangleFilter) {
|
|
actor->getCollider()->setTriangleFilter(triangleFilter);
|
|
}
|
|
|
|
void setColliderFilterCollisionParts(LiveActor* actor,
|
|
const CollisionPartsFilterBase* collisionPartsFilter) {
|
|
actor->getCollider()->setCollisionPartsFilter(collisionPartsFilter);
|
|
}
|
|
|
|
void createAndSetColliderFilterExistActor(LiveActor* actor) {
|
|
createAndSetColliderFilterExistActor(actor, actor);
|
|
}
|
|
|
|
void createAndSetColliderFilterExistActor(LiveActor* actor, LiveActor* filterActor) {
|
|
CollisionPartsFilterActor* collisionPartsFilter = new CollisionPartsFilterActor(filterActor);
|
|
setColliderFilterCollisionParts(actor, collisionPartsFilter);
|
|
}
|
|
|
|
void createAndSetColliderFilterSubActor(LiveActor* actor) {
|
|
CollisionPartsFilterSubActor* collisionPartsFilter = new CollisionPartsFilterSubActor(actor);
|
|
setColliderFilterCollisionParts(actor, collisionPartsFilter);
|
|
}
|
|
|
|
void createAndSetColliderSpecialPurpose(LiveActor* actor, const char* name) {
|
|
CollisionPartsFilterSpecialPurpose* collisionPartsFilter =
|
|
new CollisionPartsFilterSpecialPurpose(name);
|
|
setColliderFilterCollisionParts(actor, collisionPartsFilter);
|
|
}
|
|
|
|
void createAndSetColliderSpecialPurposeForCollisionActor(LiveActor* actor, const char* name) {
|
|
CollisionPartsFilterMergePair* collisionPartsFilter = new CollisionPartsFilterMergePair(
|
|
new CollisionPartsFilterSpecialPurpose(name), new CollisionPartsFilterActor(actor));
|
|
setColliderFilterCollisionParts(actor, collisionPartsFilter);
|
|
}
|
|
|
|
void createAndSetColliderIgnoreOptionalPurpose(LiveActor* actor, const char* name) {
|
|
CollisionPartsFilterIgnoreOptionalPurpose* collisionPartsFilter =
|
|
new CollisionPartsFilterIgnoreOptionalPurpose(name);
|
|
setColliderFilterCollisionParts(actor, collisionPartsFilter);
|
|
}
|
|
|
|
void createAndSetColliderSpecialAndIgnoreOptionalPurpose(LiveActor* actor, const char* name,
|
|
const char* ignoreName) {
|
|
CollisionPartsFilterMergePair* collisionPartsFilter = new CollisionPartsFilterMergePair(
|
|
new CollisionPartsFilterSpecialPurpose(name),
|
|
new CollisionPartsFilterIgnoreOptionalPurpose(ignoreName));
|
|
setColliderFilterCollisionParts(actor, collisionPartsFilter);
|
|
}
|
|
|
|
ActorCollisionController* createActorCollisionController(LiveActor* actor) {
|
|
return new ActorCollisionController(actor);
|
|
}
|
|
|
|
void setColliderRadius(ActorCollisionController* collisionController, f32 radius) {
|
|
collisionController->setColliderRadius(radius);
|
|
}
|
|
|
|
void setColliderRadiusScale(ActorCollisionController* collisionController, f32 scale) {
|
|
collisionController->setColliderRadiusScale(scale);
|
|
}
|
|
|
|
void setColliderOffsetY(ActorCollisionController* collisionController, f32 offsetY) {
|
|
collisionController->setColliderOffsetY(offsetY);
|
|
}
|
|
|
|
void resetActorCollisionController(ActorCollisionController* collisionController, s32 delay) {
|
|
collisionController->resetToOrigin(delay);
|
|
}
|
|
|
|
void updateActorCollisionController(ActorCollisionController* collisionController) {
|
|
collisionController->update();
|
|
}
|
|
|
|
const char* getCollidedFloorMaterialCodeName(const LiveActor* actor) {
|
|
return getCollidedFloorMaterialCodeName(actor->getCollider());
|
|
}
|
|
|
|
const char* getCollidedFloorMaterialCodeName(const Collider* collider) {
|
|
return getMaterialCodeName(collider->getFloorHit().triangle);
|
|
}
|
|
|
|
const char* getCollidedWallMaterialCodeName(const LiveActor* actor) {
|
|
return getMaterialCodeName(actor->getCollider()->getWallHit().triangle);
|
|
}
|
|
|
|
const char* getCollidedCeilingMaterialCodeName(const LiveActor* actor) {
|
|
return getMaterialCodeName(actor->getCollider()->getCeilingHit().triangle);
|
|
}
|
|
|
|
bool isCollidedFloorCode(const LiveActor* actor, const char* name) {
|
|
return isCollidedCollisionCode(actor, "FloorCode", name);
|
|
}
|
|
|
|
bool isCollidedCollisionCode(const LiveActor* actor, const char* sensorName, const char* name) {
|
|
Collider* collider = actor->getCollider();
|
|
if (collider->getPlaneNum() == 0) {
|
|
if (collider->get_110() >= 0.0f) {
|
|
if (isEqualString(name,
|
|
getCollisionCodeName(collider->getFloorHit().triangle, sensorName))) {
|
|
return true;
|
|
}
|
|
}
|
|
if (collider->get_1b8() >= 0.0f) {
|
|
if (isEqualString(name,
|
|
getCollisionCodeName(collider->getWallHit().triangle, sensorName))) {
|
|
return true;
|
|
}
|
|
}
|
|
if (collider->get_260() >= 0.0f) {
|
|
if (isEqualString(
|
|
name, getCollisionCodeName(collider->getCeilingHit().triangle, sensorName))) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
u32 size = collider->getStoredPlaneNum();
|
|
for (u32 i = 0; i < size; i++)
|
|
if (isEqualString(name, getCollisionCodeName(*collider->getPlane(i), sensorName)))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool isCollidedWallCode(const LiveActor* actor, const char* name) {
|
|
return isCollidedCollisionCode(actor, "WallCode", name);
|
|
}
|
|
|
|
bool isCollidedCameraCode(const LiveActor* actor, const char* name) {
|
|
return isCollidedCollisionCode(actor, "CameraCode", name);
|
|
}
|
|
|
|
bool isCollidedMaterialCode(const LiveActor* actor, const char* name) {
|
|
return isCollidedCollisionCode(actor, "MaterialCode", name);
|
|
}
|
|
|
|
bool isCollidedGroundFloorCode(const LiveActor* actor, const char* name) {
|
|
return isCollidedGroundCollisionCode(actor, "FloorCode", name);
|
|
}
|
|
|
|
bool isCollidedGroundCollisionCode(const LiveActor* actor, const char* sensorName,
|
|
const char* name) {
|
|
if (!isCollidedGround(actor))
|
|
return false;
|
|
|
|
return isEqualString(
|
|
name, getCollisionCodeName(actor->getCollider()->getFloorHit().triangle, sensorName));
|
|
}
|
|
|
|
bool isCollided(const LiveActor* actor) {
|
|
return isCollidedGround(actor) || isCollidedWall(actor) || isCollidedCeiling(actor);
|
|
}
|
|
|
|
bool isCollidedCeiling(const LiveActor* actor) {
|
|
return actor->getCollider()->get_260() >= 0.0f;
|
|
}
|
|
|
|
bool isCollidedWallFace(const LiveActor* actor) {
|
|
if (!isCollidedWall(actor))
|
|
return false;
|
|
|
|
return actor->getCollider()->isCollidedWallFace();
|
|
}
|
|
|
|
bool isCollidedVelocity(const LiveActor* actor) {
|
|
if (isOnGround(actor, 0))
|
|
return true;
|
|
|
|
return isCollidedWallVelocity(actor) || isCollidedCeilingVelocity(actor);
|
|
}
|
|
|
|
bool isCollidedWallVelocity(const LiveActor* actor) {
|
|
return isCollidedWall(actor) && getVelocity(actor).dot(getCollidedWallNormal(actor)) < 0.0f;
|
|
}
|
|
|
|
bool isCollidedCeilingVelocity(const LiveActor* actor) {
|
|
return isCollidedCeiling(actor) &&
|
|
getVelocity(actor).dot(getCollidedCeilingNormal(actor)) < 0.0f;
|
|
}
|
|
|
|
const sead::Vector3f& getCollidedCeilingNormal(const LiveActor* actor) {
|
|
return actor->getCollider()->getCeilingHit().triangle.getFaceNormal();
|
|
}
|
|
|
|
const sead::Vector3f& getCollidedGroundPos(const LiveActor* actor) {
|
|
return actor->getCollider()->getFloorHit().collisionHitPos;
|
|
}
|
|
|
|
const sead::Vector3f& getCollidedWallPos(const LiveActor* actor) {
|
|
return actor->getCollider()->getWallHit().collisionHitPos;
|
|
}
|
|
|
|
const sead::Vector3f& getCollidedCeilingPos(const LiveActor* actor) {
|
|
return actor->getCollider()->getCeilingHit().collisionHitPos;
|
|
}
|
|
|
|
f32 calcSpeedCollideWall(const LiveActor* actor) {
|
|
if (!isCollidedWall(actor))
|
|
return 0.0f;
|
|
sead::Vector3f wallNormal = getCollidedWallNormal(actor);
|
|
return -sead::Mathf::min(wallNormal.dot(getVelocity(actor)), 0.0f);
|
|
}
|
|
|
|
f32 calcSpeedCollideGround(const LiveActor* actor) {
|
|
if (!isCollidedGround(actor))
|
|
return 0.0f;
|
|
sead::Vector3f groundNormal = getCollidedGroundNormal(actor);
|
|
return -sead::Mathf::min(groundNormal.dot(getVelocity(actor)), 0.0f);
|
|
}
|
|
|
|
f32 calcSpeedCollideCeiling(const LiveActor* actor) {
|
|
if (!isCollidedCeiling(actor))
|
|
return 0.0f;
|
|
sead::Vector3f ceilingNormal = getCollidedCeilingNormal(actor);
|
|
return -sead::Mathf::min(ceilingNormal.dot(getVelocity(actor)), 0.0f);
|
|
}
|
|
|
|
const CollisionParts* getCollidedGroundCollisionParts(const LiveActor* actor) {
|
|
return tryGetCollidedGroundCollisionParts(actor);
|
|
}
|
|
|
|
const CollisionParts* tryGetCollidedGroundCollisionParts(const LiveActor* actor) {
|
|
if (!isCollidedGround(actor))
|
|
return nullptr;
|
|
return actor->getCollider()->getFloorHit().triangle.getCollisionParts();
|
|
}
|
|
|
|
const CollisionParts* getCollidedWallCollisionParts(const LiveActor* actor) {
|
|
return tryGetCollidedWallCollisionParts(actor);
|
|
}
|
|
|
|
const CollisionParts* tryGetCollidedWallCollisionParts(const LiveActor* actor) {
|
|
if (!isCollidedWall(actor))
|
|
return nullptr;
|
|
return actor->getCollider()->getWallHit().triangle.getCollisionParts();
|
|
}
|
|
|
|
const CollisionParts* getCollidedCeilingCollisionParts(const LiveActor* actor) {
|
|
return tryGetCollidedCeilingCollisionParts(actor);
|
|
}
|
|
|
|
const CollisionParts* tryGetCollidedCeilingCollisionParts(const LiveActor* actor) {
|
|
if (!isCollidedCeiling(actor))
|
|
return nullptr;
|
|
return actor->getCollider()->getCeilingHit().triangle.getCollisionParts();
|
|
}
|
|
|
|
HitSensor* getCollidedGroundSensor(const LiveActor* actor) {
|
|
return tryGetCollidedGroundSensor(actor);
|
|
}
|
|
|
|
HitSensor* tryGetCollidedGroundSensor(const LiveActor* actor) {
|
|
if (!isCollidedGround(actor))
|
|
return nullptr;
|
|
return actor->getCollider()->getFloorHit().triangle.getCollisionParts()->getConnectedSensor();
|
|
}
|
|
|
|
HitSensor* getCollidedWallSensor(const LiveActor* actor) {
|
|
return tryGetCollidedWallSensor(actor);
|
|
}
|
|
|
|
HitSensor* tryGetCollidedWallSensor(const LiveActor* actor) {
|
|
if (!isCollidedWall(actor))
|
|
return nullptr;
|
|
return actor->getCollider()->getWallHit().triangle.getCollisionParts()->getConnectedSensor();
|
|
}
|
|
|
|
HitSensor* getCollidedCeilingSensor(const LiveActor* actor) {
|
|
return tryGetCollidedCeilingSensor(actor);
|
|
}
|
|
|
|
HitSensor* tryGetCollidedCeilingSensor(const LiveActor* actor) {
|
|
if (!isCollidedCeiling(actor))
|
|
return nullptr;
|
|
return actor->getCollider()->getCeilingHit().triangle.getCollisionParts()->getConnectedSensor();
|
|
}
|
|
|
|
HitSensor* tryGetCollidedSensor(const LiveActor* actor) {
|
|
return tryGetCollidedWallSensor(actor) ?:
|
|
tryGetCollidedGroundSensor(actor) ?:
|
|
tryGetCollidedCeilingSensor(actor);
|
|
}
|
|
|
|
bool tryGetCollidedPos(sead::Vector3f* outPos, const LiveActor* actor) {
|
|
if (isCollidedWall(actor)) {
|
|
outPos->set(getCollidedWallPos(actor));
|
|
return true;
|
|
}
|
|
if (isCollidedGround(actor)) {
|
|
outPos->set(getCollidedGroundPos(actor));
|
|
return true;
|
|
}
|
|
if (isCollidedCeiling(actor)) {
|
|
outPos->set(getCollidedCeilingPos(actor));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void setForceCollisionScaleOne(const LiveActor* actor) {
|
|
actor->getCollisionParts()->setForceCollisionScaleOne();
|
|
}
|
|
|
|
void followRotateFrontAxisUpGround(LiveActor* actor) {
|
|
const CollisionParts* collisionParts = tryGetCollidedGroundCollisionParts(actor);
|
|
|
|
if (collisionParts)
|
|
followRotateFrontAxisUp(actor, collisionParts);
|
|
}
|
|
|
|
void followRotateFrontAxisUp(LiveActor* actor, const CollisionParts* collisionParts) {
|
|
sead::Vector3f frontDir = {0.0f, 0.0f, 0.0f};
|
|
calcFrontDir(&frontDir, actor);
|
|
|
|
sead::Vector3f sideDir = frontDir;
|
|
sideDir.rotate(collisionParts->getPrevBaseInvMtx());
|
|
sideDir.rotate(collisionParts->getBaseMtx());
|
|
|
|
sead::Vector3f upDir = {0.0f, 0.0f, 0.0f};
|
|
calcUpDir(&upDir, actor);
|
|
|
|
sead::Vector3f newFrontDir = {0.0f, 0.0f, 0.0f};
|
|
turnVecToVecCosOnPlane(&newFrontDir, frontDir, sideDir, upDir, -1.0f);
|
|
|
|
sead::Quatf quat = sead::Quatf::unit;
|
|
makeQuatUpFront(&quat, upDir, newFrontDir);
|
|
updatePoseQuat(actor, quat);
|
|
}
|
|
|
|
} // namespace al
|