diff --git a/data/file_list.yml b/data/file_list.yml index 607a4630..e4cfe231 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -230947,7 +230947,7 @@ Library/Clipping/FrustumRadar.o: size: 12 label: _ZNK2al12FrustumRadar19judgeInAreaObbNoFarEPKN4sead8Matrix34IfEERKNS1_9BoundBox3IfEE status: NotDecompiled -Library/Collision/Collider.o: +Library/Collision/Angle.o: '.text': - offset: 0x8443d8 size: 120 @@ -230973,84 +230973,86 @@ Library/Collision/Collider.o: size: 196 label: _ZN2al24calcTriangleColorByAngleEPN4sead7Color4fEPfRKNS0_7Vector3IfEE status: NotDecompiled +Library/Collision/Collider.o: + '.text': - offset: 0x844740 size: 316 label: - _ZN2al8ColliderC1EPNS_17CollisionDirectorEPKN4sead8Matrix34IfEEPKNS3_7Vector3IfEESB_ffj - _ZN2al8ColliderC2EPNS_17CollisionDirectorEPKN4sead8Matrix34IfEEPKNS3_7Vector3IfEESB_ffj - status: NotDecompiled + status: Matching - offset: 0x84487c size: 36 label: _ZN2al8Collider5clearEv - status: NotDecompiled + status: Matching - offset: 0x8448a0 size: 8 label: _ZN2al8Collider17setTriangleFilterEPKNS_18TriangleFilterBaseE - status: NotDecompiled + status: Matching - offset: 0x8448a8 size: 8 label: _ZN2al8Collider23setCollisionPartsFilterEPKNS_24CollisionPartsFilterBaseE - status: NotDecompiled + status: Matching - offset: 0x8448b0 size: 100 label: _ZN2al8Collider24updateRecentOnGroundInfoEv - status: NotDecompiled + status: Matching - offset: 0x844914 size: 8 label: _ZN2al8Collider19clearStoredPlaneNumEv - status: NotDecompiled + status: Matching - offset: 0x84491c size: 32 label: _ZN2al8Collider17clearContactPlaneEv - status: NotDecompiled + status: Matching - offset: 0x84493c size: 84 label: _ZN2al8Collider12onInvalidateEv - status: NotDecompiled + status: Matching - offset: 0x844990 size: 444 label: _ZNK2al8Collider12calcCheckPosEPN4sead7Vector3IfEE - status: NotDecompiled + status: Matching - offset: 0x844b4c size: 48 label: _ZNK2al8Collider23getRecentOnGroundNormalEj - status: NotDecompiled + status: Matching - offset: 0x844b7c size: 16 label: _ZNK2al8Collider8getPlaneEi - status: NotDecompiled + status: Matching - offset: 0x844b8c size: 168 label: _ZN2al8Collider22calcMovePowerByContactEPN4sead7Vector3IfEERKS3_ - status: NotDecompiled + status: Matching - offset: 0x844c34 size: 428 label: _ZN2al8Collider19storeCurrentHitInfoEPNS_13SphereHitInfoEj - status: NotDecompiled + status: Matching - offset: 0x844de0 size: 1184 label: _ZN2al8Collider23obtainMomentFixReactionEPNS_13SphereHitInfoEPN4sead7Vector3IfEES6_bj - status: NotDecompiled + status: NonMatchingMajor - offset: 0x845280 size: 1104 label: _ZN2al8Collider17storeContactPlaneEPNS_13SphereHitInfoE - status: NotDecompiled + status: Matching - offset: 0x8456d0 size: 1688 label: _ZN2al8Collider7collideERKN4sead7Vector3IfEE - status: NotDecompiled + status: NonMatchingMajor - offset: 0x845d68 size: 484 label: _ZN2al8Collider10preCollideEPNS_18SphereInterpolatorEPN4sead7Vector3IfEEPfRKS5_PNS_13SphereHitInfoEj - status: NotDecompiled + status: Matching - offset: 0x845f4c size: 244 label: _ZN2al8Collider14findCollidePosEPiPNS_18SphereInterpolatorEPNS_13SphereHitInfoEj - status: NotDecompiled + status: Matching - offset: 0x846040 size: 8 label: _ZNK2al8Collider20getCollisionDirectorEv - status: NotDecompiled + status: Matching lazy: true Library/Collision/CollisionCodeFunction.o: '.text': diff --git a/lib/al/Library/Collision/Angle.h b/lib/al/Library/Collision/Angle.h new file mode 100644 index 00000000..675ec244 --- /dev/null +++ b/lib/al/Library/Collision/Angle.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +namespace al { + +enum class PolygonType : s32 { /* TODO: MISSING */ }; + +bool isWallPolygon(const sead::Vector3f&, const sead::Vector3f&); +bool isFloorPolygon(const sead::Vector3f&, const sead::Vector3f&); +bool isFloorPolygonCos(const sead::Vector3f&, const sead::Vector3f&, f32); +bool isCeilingPolygon(const sead::Vector3f&, const sead::Vector3f&); +PolygonType calcPolygonType(const sead::Vector3f&, const sead::Vector3f&); +void calcTriangleColorByAngle(sead::Color4f*, f32*, const sead::Vector3f&); + +} // namespace al diff --git a/lib/al/Library/Collision/Collider.cpp b/lib/al/Library/Collision/Collider.cpp new file mode 100644 index 00000000..3dde9f41 --- /dev/null +++ b/lib/al/Library/Collision/Collider.cpp @@ -0,0 +1,483 @@ +#include "Library/Collision/Collider.h" + +#include "Library/Collision/Angle.h" +#include "Library/Collision/CollisionDirector.h" +#include "Library/Collision/CollisionPartsKeeperUtil.h" +#include "Library/Collision/KCollisionServer.h" +#include "Library/Math/MathUtil.h" + +namespace al { + +Collider::Collider(CollisionDirector* director, const sead::Matrix34f* actorBaseMtx, + const sead::Vector3f* actorTrans, const sead::Vector3f* actorGravity, f32 radius, + f32 offsetY, u32 planeNum) + : mCollisionDirector(director), mActorBaseMtx(actorBaseMtx), mActorTrans(actorTrans), + mActorGravity(actorGravity), mRadius(radius), mOffsetY(offsetY), mPlaneNum(planeNum) { + mCurrentTrans.set(*actorTrans); + mCurrentRadius = radius; + if (mPlaneNum != 0) { + mPlanes = new SphereHitInfo[mPlaneNum]; + __asm(""); + } else + mPlanes = nullptr; + clear(); + flags2 = (flags2 & 0x80) | 3; +} + +void Collider::clear() { + clearStoredPlaneNum(); + clearContactPlane(); +} + +void Collider::setTriangleFilter(const TriangleFilterBase* filter) { + mTriangleFilter = filter; +} + +void Collider::setCollisionPartsFilter(const CollisionPartsFilterBase* filter) { + mCollisionPartsFilter = filter; +} + +void Collider::updateRecentOnGroundInfo() { + if (mFloor_70 >= 0.0f) { + mNoGroundCounter = 0; + mRecentOnGroundNormal = mFloorHit.triangle.getFaceNormal(); + } else if (mNoGroundCounter != -1) { + mNoGroundCounter++; + } +} + +void Collider::clearStoredPlaneNum() { + mStoredPlaneNum = 0; +} + +void Collider::clearContactPlane() { + mFloor_70 = -99999.0f; + mWall_70 = -99999.0f; + mCeiling_70 = -99999.0f; + mFixReaction = {0.0f, 0.0f, 0.0f}; + mMovePower = {0.0f, 0.0f, 0.0f}; +} + +void Collider::onInvalidate() { + clear(); + mNoGroundCounter = -1; + calcCheckPos(&mCurrentTrans); + mCurrentRadius = mRadius; +} + +void Collider::calcCheckPos(sead::Vector3f* outPos) const { + // many things are done manually here, which is visible in the assembly as unoptimized + // reading/writing to memory - for example, the matrix multiplication here ends up writing to + // outPos 4 times + + *outPos = *mActorTrans; + + if (unknown) { + if ((flags2 & 0x4) && mActorBaseMtx) { + outPos->x += mActorBaseMtx->getBase(0).x * unknown->x; + outPos->x += mActorBaseMtx->getBase(1).x * unknown->y; + outPos->x += mActorBaseMtx->getBase(2).x * unknown->z; + outPos->y += mActorBaseMtx->getBase(0).y * unknown->x; + outPos->y += mActorBaseMtx->getBase(1).y * unknown->y; + outPos->y += mActorBaseMtx->getBase(2).y * unknown->z; + outPos->z += mActorBaseMtx->getBase(0).z * unknown->x; + outPos->z += mActorBaseMtx->getBase(1).z * unknown->y; + outPos->z += mActorBaseMtx->getBase(2).z * unknown->z; + return; + } + outPos->x += unknown->x; + outPos->y += unknown->y; + outPos->z += unknown->z; + return; + } + + if (mActorBaseMtx) { + outPos->x += mActorBaseMtx->getBase(1).x * mOffsetY; + outPos->y += mActorBaseMtx->getBase(1).y * mOffsetY; + outPos->z += mActorBaseMtx->getBase(1).z * mOffsetY; + return; + } + + outPos->y += mOffsetY; +} + +static const sead::Vector3f sDefaultGroundNormal = {0.0f, 1.0f, 0.0f}; + +const sead::Vector3f& Collider::getRecentOnGroundNormal(u32 coyoteTime) const { + if (mFloor_70 >= 0.0f) + return mFloorHit.triangle.getFaceNormal(); + + if ((u32)mNoGroundCounter <= coyoteTime) + return mRecentOnGroundNormal; + + return sDefaultGroundNormal; +} + +const Triangle& Collider::getPlane(s32 index) const { + return mPlanes[index].triangle; +} + +bool Collider::calcMovePowerByContact(sead::Vector3f* movePower, const sead::Vector3f& pos) { + if (mFloor_70 < 0.0f) + return false; + if (!mFloorHit.triangle.isHostMoved()) + return false; + + mFloorHit.triangle.calcForceMovePower(movePower, pos); + const sead::Vector3f& normal = mFloorHit.triangle.getFaceNormal(); + if (normal.dot(*movePower) > 0.0f) + verticalizeVec(movePower, normal, *movePower); + return true; +} + +u32 Collider::storeCurrentHitInfo(SphereHitInfo* buffer, u32 bufferSize) { + u32 strikeInfoNum = alCollisionUtil::getStrikeSphereInfoNum(this); + u32 i; + for (i = 0; i < strikeInfoNum; i++) { + if (i + mStoredPlaneNum >= bufferSize) { + u32 stored = bufferSize - mStoredPlaneNum; + mStoredPlaneNum = bufferSize; + return stored; + } + + const al::SphereHitInfo& info = alCollisionUtil::getStrikeSphereInfo(this, i); + buffer[i + mStoredPlaneNum] = info; + } + + mStoredPlaneNum += i; + return i; +} + +// TODO: cleanup +void al::Collider::obtainMomentFixReaction(al::SphereHitInfo* a2, sead::Vector3f* a3, + sead::Vector3f* a4, bool a5, u32 a6) { + flags2 &= ~(0x10 | 0x20 | 0x40); + for (u32 i = a6; i < mStoredPlaneNum; i++) { + const sead::Vector3f& normal = a2[i].triangle.getFaceNormal(); + if (al::isFloorPolygon(normal, *mActorGravity)) { + if (a2[i].isCollisionAtFace()) + flags2 |= 0x10; + } else if (al::isWallPolygon(normal, *mActorGravity)) { + if (a2[i].isCollisionAtFace()) + flags2 |= 0x20; + } else { + if (a2[i].isCollisionAtFace()) + flags2 |= 0x40; + } + } + + f32 maxAX = 0.0f; + f32 maxAY = 0.0f; + f32 maxAZ = 0.0f; + f32 minAX = 0.0f; + f32 minAY = 0.0f; + f32 minAZ = 0.0f; + f32 maxBX = 0.0f; + f32 maxBY = 0.0f; + f32 maxBZ = 0.0f; + f32 minBX = 0.0f; + f32 minBY = 0.0f; + f32 minBZ = 0.0f; + + for (u32 i = a6; i < mStoredPlaneNum; i++) { + const sead::Vector3f& normal = a2[i].triangle.getFaceNormal(); + sead::Vector3f a; + sead::Vector3f b; + if (al::isFloorPolygon(normal, *mActorGravity)) + if (!flags1 || (flags2 & 0x10) != 0) + a2[i].calcFixVectorNormal(&a, &b); + else + a2[i].calcFixVector(&a, &b); + else if (al::isWallPolygon(normal, *mActorGravity)) + if ((flags2 & 0x20) == 0) + a2[i].calcFixVector(&a, &b); + else + a2[i].calcFixVectorNormal(&a, &b); + else if ((flags2 & 0x40) == 0) + a2[i].calcFixVector(&a, &b); + else + a2[i].calcFixVectorNormal(&a, &b); + + if (maxAX < a.x) + maxAX = a.x; + else if (a.x < minAX) + minAX = a.x; + + if (maxAY < a.y) + maxAY = a.y; + else if (a.y < minAY) + minAY = a.y; + + if (maxAZ < a.z) + maxAZ = a.z; + else if (a.z < minAZ) + minAZ = a.z; + + if (a4) { + if (maxBX < b.x) + maxBX = b.x; + else if (b.x < minBX) + minBX = b.x; + + if (maxBY < b.y) + maxBY = b.y; + else if (b.y < minBY) + minBY = b.y; + + if (maxBZ < b.z) + maxBZ = b.z; + else if (b.z < minBZ) + minBZ = b.z; + } + + if ((flags2 & 2) == 0 || !a2[i].triangle.isHostMoved()) + continue; + + sead::Vector3f collisionMovingReaction = a2[i].collisionMovingReaction; + if (a.dot(collisionMovingReaction) < 0.0f) + continue; + + if (maxAX < collisionMovingReaction.x) + maxAX = collisionMovingReaction.x; + else if (collisionMovingReaction.x < minAX) + minAX = collisionMovingReaction.x; + + if (maxAY < collisionMovingReaction.y) + maxAY = collisionMovingReaction.y; + else if (collisionMovingReaction.y < minAY) + minAY = collisionMovingReaction.y; + + if (maxAZ < collisionMovingReaction.z) + maxAZ = collisionMovingReaction.z; + else if (collisionMovingReaction.z < minAZ) + minAZ = collisionMovingReaction.z; + + if (a4) { + if (maxBX < collisionMovingReaction.x) + maxBX = collisionMovingReaction.x; + else if (collisionMovingReaction.x < minBX) + minBX = collisionMovingReaction.x; + + if (maxBY < collisionMovingReaction.y) + maxBY = collisionMovingReaction.y; + else if (collisionMovingReaction.y < minBY) + minBY = collisionMovingReaction.y; + + if (maxBZ < collisionMovingReaction.z) + maxBZ = collisionMovingReaction.z; + else if (!(collisionMovingReaction.z < minBZ)) // FIXME: wrong way around? + minBZ = collisionMovingReaction.z; + } + } + + a3->x = maxAX + minAX; + a3->y = maxAY + minAY; + a3->z = maxAZ + minAZ; + if (a4) { + a4->x = maxBX + minBX; + a4->y = maxBY + minBY; + a4->z = maxBZ + minBZ; + } +} + +void Collider::storeContactPlane(SphereHitInfo* hitInfos) { + for (u32 i = 0; i < mStoredPlaneNum; i++) { + const sead::Vector3f& normal = hitInfos[i].triangle.getNormal(0); + if (isFloorPolygon(normal, *mActorGravity)) { + if (mFloor_70 < hitInfos[i]._70) { + mFloorHit = hitInfos[i]; + mFloor_70 = hitInfos[i]._70; + } + } else if (isWallPolygon(normal, *mActorGravity)) { + if (mWall_70 < hitInfos[i]._70) { + mWallHit = hitInfos[i]; + mWall_70 = hitInfos[i]._70; + } + } else if (mCeiling_70 < hitInfos[i]._70) { + mCeilingHit = hitInfos[i]; + mCeiling_70 = hitInfos[i]._70; + } + } +} + +// TODO: cleanup +sead::Vector3f al::Collider::collide(const sead::Vector3f& velocity) { + al::SphereHitInfo* planes; + u32 planeNum; + if (mPlaneNum) { + planes = mPlanes; + planeNum = mPlaneNum; + } else { + getCollisionDirector()->getSphereHitInfoArrayForCollider(&planes, &planeNum); + } + + sead::Vector3f checkPos = {0.0f, 0.0f, 0.0f}; + calcCheckPos(&checkPos); + + /*-----------------*/ + + sead::Vector3f transStart = mCurrentTrans; + f32 currentRadius = mCurrentRadius; + f32 v8 = sead::Mathf::clampMax(sead::Mathf::min(0.9f * mRadius, 0.9f * mCurrentRadius), 35.0f); + sead::Vector3f movePower = {0.0f, 0.0f, 0.0f}; + if ((flags2 & 1) != 0) + calcMovePowerByContact(&movePower, checkPos); + + clear(); + mMovePower = movePower; + al::SphereInterpolator interpolator; + interpolator.startInterp(mCurrentTrans, checkPos + movePower, mCurrentRadius, mRadius, v8); + s32 v56 = 0; + sead::Vector3f moveDist = (checkPos + movePower) - mCurrentTrans; + if (!al::isNearZero(moveDist) || !al::isNearZero(mCurrentRadius - mRadius)) + preCollide(&interpolator, &transStart, ¤tRadius, moveDist, planes, planeNum); + + f32 v19 = sead::Mathf::clampMax(mCurrentRadius * 0.9f, 35.0f); + interpolator.startInterp(transStart, transStart + velocity, mRadius, mRadius, v19); + v56 = 0; + sead::Vector3f v232526; + if (!findCollidePos(&v56, &interpolator, planes, planeNum) && + interpolator.getPrevStep() == 1.0 && interpolator.getCurrentStep() == 1.0) { + v232526 = transStart - checkPos + velocity; + } else { + sead::Vector3f v272829 = {0.0f, 0.0f, 0.0f}; + s32 v30 = 0; + bool v31 = true; + sead::Vector3f v53; + do { + sead::Vector3f v55 = {0.0f, 0.0f, 0.0f}; + sead::Vector3f v54 = {0.0f, 0.0f, 0.0f}; + obtainMomentFixReaction(planes, &v55, &v54, v31, v30); + v30 += v56; + + interpolator.calcInterp(&transStart, ¤tRadius, &v53); + transStart += v55; + v272829 += v55; + sead::Vector3f a1a = v55; + if (al::isNearZero(a1a)) + a1a = v54; + + al::tryNormalizeOrZero(&a1a); + f32 v42 = v53.dot(a1a); + if (v42 < 0.0f) + v53 -= a1a * v42; + + if (velocity.dot(v53) < 0.0f) + break; + + interpolator.startInterp(transStart, transStart + v53, currentRadius, mRadius, v19); + interpolator.nextStep(); + v56 = 0; + v31 = false; + bool CollidePos = findCollidePos(&v56, &interpolator, planes, planeNum); + if (!CollidePos || interpolator.getCurrentStep() >= 1.0f) { + interpolator.calcInterpPos(&transStart); + if (CollidePos && v56 > 0) { + obtainMomentFixReaction(planes, &v55, nullptr, false, v30); + transStart += v55; + v30 += v56; + } + break; + } else { + continue; + } + } while (true); + + storeContactPlane(planes); + mFixReaction = v272829; + v232526 = transStart - checkPos; + } + + mCurrentTrans = v232526 + checkPos; + mCurrentRadius = mRadius; + updateRecentOnGroundInfo(); + + return v232526; +} + +// TODO: cleanup +bool Collider::preCollide(al::SphereInterpolator* interpolator, sead::Vector3f* trans, + f32* currentRadius, const sead::Vector3f& moveDist, + al::SphereHitInfo* buffer, u32 bufferSize) { + sead::Vector3f v71415 = {0.0f, 0.0f, 0.0f}; + const al::TriangleFilterBase* triangleFilter = mTriangleFilter; + const al::CollisionPartsFilterBase* collisionPartsFilter = mCollisionPartsFilter; + bool foundHit = false; + u32 totalStored = 0; + while (interpolator->getPrevStep() != 1.0f || interpolator->getCurrentStep() != 1.0f) { + sead::Vector3f pos; + f32 size; + interpolator->calcInterp(&pos, &size, nullptr); + + s32 hits; + if ((flags2 & 2) != 0) { + hits = alCollisionUtil::checkStrikeSphereMovingReaction( + this, v71415 + pos, size, moveDist, collisionPartsFilter, triangleFilter); + } else { + hits = alCollisionUtil::checkStrikeSphere(this, pos, size, collisionPartsFilter, + triangleFilter); + } + + if (hits != 0) { + s32 stored = storeCurrentHitInfo(buffer, bufferSize); + sead::Vector3f a2a = {0.0f, 0.0f, 0.0f}; + obtainMomentFixReaction(buffer, &a2a, nullptr, false, totalStored); + v71415 += a2a; + foundHit = true; + if (interpolator->getCurrentStep() >= 1.0f) + break; + + if (flags2 & 0x8) + totalStored += stored; + } + + interpolator->nextStep(); + } + + interpolator->calcInterp(trans, currentRadius, nullptr); + *trans += v71415; + if (foundHit) { + storeContactPlane(buffer); + mStoredPlaneNum = 0; + } + + return foundHit; +} + +bool Collider::findCollidePos(s32* bufferStored, al::SphereInterpolator* interpolator, + al::SphereHitInfo* buffer, u32 bufferSize) { + const al::TriangleFilterBase* triangleFilter = mTriangleFilter; + const al::CollisionPartsFilterBase* collisionPartsFilter = mCollisionPartsFilter; + while (interpolator->getPrevStep() != 1.0 || interpolator->getCurrentStep() != 1.0) { + sead::Vector3f pos, remainMoveVec; + f32 size; + interpolator->calcInterp(&pos, &size, &remainMoveVec); + + s32 hits; + if (flags2 & 0x2) { + hits = alCollisionUtil::checkStrikeSphereMovingReaction( + this, pos, size, remainMoveVec, collisionPartsFilter, triangleFilter); + } else { + hits = alCollisionUtil::checkStrikeSphere(this, pos, size, collisionPartsFilter, + triangleFilter); + } + + if (hits != 0) { + u32 stored = storeCurrentHitInfo(buffer, bufferSize); + if (bufferStored) + *bufferStored = stored; + + return true; + } + + interpolator->nextStep(); + } + + return false; +} + +CollisionDirector* Collider::getCollisionDirector() const { + return mCollisionDirector; +} + +} // namespace al diff --git a/lib/al/Library/Collision/Collider.h b/lib/al/Library/Collision/Collider.h index 8769860a..d15d7ca8 100644 --- a/lib/al/Library/Collision/Collider.h +++ b/lib/al/Library/Collision/Collider.h @@ -16,105 +16,99 @@ class SphereInterpolator; class Triangle; class TriangleFilterBase; -bool isWallPolygon(const sead::Vector3f&, const sead::Vector3f&); -bool isFloorPolygon(const sead::Vector3f&, const sead::Vector3f&); -bool isCeilingPolygon(const sead::Vector3f&, const sead::Vector3f&); - class Collider : public HioNode, public IUseCollision { public: Collider(CollisionDirector*, const sead::Matrix34f*, const sead::Vector3f*, const sead::Vector3f*, f32, f32, u32); void calcCheckPos(sead::Vector3f*) const; - void calcMovePowerByContact(sead::Vector3f*, const sead::Vector3f&); + bool calcMovePowerByContact(sead::Vector3f*, const sead::Vector3f&); void clear(); void clearContactPlane(); void clearStoredPlaneNum(); sead::Vector3f collide(const sead::Vector3f&); - void findCollidePos(s32*, SphereInterpolator*, SphereHitInfo*, u32); - Triangle* getPlane(s32) const; + bool findCollidePos(s32*, SphereInterpolator*, SphereHitInfo*, u32); + const Triangle& getPlane(s32) const; const sead::Vector3f& getRecentOnGroundNormal(u32) const; void obtainMomentFixReaction(SphereHitInfo*, sead::Vector3f*, sead::Vector3f*, bool, u32); void onInvalidate(); - void preCollide(SphereInterpolator*, sead::Vector3f*, f32*, const sead::Vector3f&, + bool preCollide(SphereInterpolator*, sead::Vector3f*, f32*, const sead::Vector3f&, SphereHitInfo*, u32); void setCollisionPartsFilter(const CollisionPartsFilterBase*); void setTriangleFilter(const TriangleFilterBase*); void storeContactPlane(SphereHitInfo*); - void storeCurrentHitInfo(SphereHitInfo*, u32); + u32 storeCurrentHitInfo(SphereHitInfo*, u32); void updateRecentOnGroundInfo(); CollisionDirector* getCollisionDirector() const override; - sead::Vector3f* get_30() const { return _30; } + const sead::Vector3f* get_30() const { return mActorGravity; } - f32 getRadius() { return mRadius; }; + f32 getRadius() { return mRadius; } - void setRadius(f32 radius) { mRadius = radius; }; + void setRadius(f32 radius) { mRadius = radius; } - f32 getOffsetY() { return mOffsetY; }; + f32 getOffsetY() { return mOffsetY; } - void setOffsetY(f32 offsetY) { mOffsetY = offsetY; }; + void setOffsetY(f32 offsetY) { mOffsetY = offsetY; } - s32 get_48() const { return _48; } + s32 get_48() const { return mPlaneNum; } - u32 getPlaneCount() const { return mPlaneCount; } + u32 getPlaneCount() const { return mStoredPlaneNum; } const sead::Vector3f& getFixReaction() const { return mFixReaction; } const HitInfo& getFloorHit() const { return mFloorHit; } - f32 get_110() const { return _110; } + f32 get_110() const { return mFloor_70; } const HitInfo& getWallHit() const { return mWallHit; } - f32 get_1b8() const { return _1b8; } + f32 get_1b8() const { return mWall_70; } const HitInfo& getCeilingHit() const { return mCeilingHit; } - f32 get_260() const { return _260; } + f32 get_260() const { return mCeiling_70; } - u32 get_264() const { return _264; } + u32 get_264() const { return mNoGroundCounter; } void setReactMovePower(bool isEnabled) { - mFlag &= ~1; - mFlag |= isEnabled; + flags2 &= ~1; + flags2 |= isEnabled; } - void validateRobustCheck() { mFlag |= 2; } + void validateRobustCheck() { flags2 |= 2; } - void invalidateRobustCheck() { mFlag &= ~2; } + void invalidateRobustCheck() { flags2 &= ~2; } - bool isCollidedWallFace() { return mFlag >> 5 & 1; } + bool isCollidedWallFace() { return flags2 >> 5 & 1; } private: - CollisionDirector* _8; - TriangleFilterBase* _10; - CollisionPartsFilterBase* _18; - sead::Matrix34f* _20; - sead::Vector3f* _28; - sead::Vector3f* _30; + CollisionDirector* mCollisionDirector; + const TriangleFilterBase* mTriangleFilter = nullptr; + const CollisionPartsFilterBase* mCollisionPartsFilter = nullptr; + const sead::Matrix34f* mActorBaseMtx; + const sead::Vector3f* mActorTrans; + const sead::Vector3f* mActorGravity; f32 mRadius; f32 mOffsetY; - void* filler1; - u32 _48; - u32 mPlaneCount; - HitInfo* _50; - sead::Vector3f mFixReaction; - sead::Vector3f _64; + sead::Vector3f* unknown = nullptr; + u32 mPlaneNum; + u32 mStoredPlaneNum = 0; + SphereHitInfo* mPlanes = nullptr; + sead::Vector3f mFixReaction = {0.0f, 0.0f, 0.0f}; + sead::Vector3f mMovePower = {0.0f, 0.0f, 0.0f}; HitInfo mFloorHit; - f32 _110; - char filler3[0x4]; + f32 mFloor_70 = 0.0f; HitInfo mWallHit; - f32 _1b8; - char filler4[0x4]; + f32 mWall_70 = 0.0f; HitInfo mCeilingHit; - f32 _260; - u32 _264; - sead::Vector3f _268; - char _274; - char mFlag; - sead::Vector3f _278; - f32 _284; + f32 mCeiling_70 = 0.0f; + s32 mNoGroundCounter = 0; + sead::Vector3f mRecentOnGroundNormal = {0.0f, 1.0f, 0.0f}; + u8 flags1 = 0; + u8 flags2; + sead::Vector3f mCurrentTrans; + f32 mCurrentRadius; }; static_assert(sizeof(Collider) == 0x288); diff --git a/lib/al/Library/Collision/CollisionPartsTriangle.cpp b/lib/al/Library/Collision/CollisionPartsTriangle.cpp index beaf91dc..efb73964 100644 --- a/lib/al/Library/Collision/CollisionPartsTriangle.cpp +++ b/lib/al/Library/Collision/CollisionPartsTriangle.cpp @@ -239,6 +239,7 @@ const sead::Vector3f& HitInfo::tryGetHitEdgeNormal() const { void SphereHitInfo::calcFixVector(sead::Vector3f* a1, sead::Vector3f* a2) const { // TODO add proper names here, once the missing names for _70 and _80 in HitInfo are found + auto* hitInfo = this; if (hitInfo->isCollisionAtFace()) { calcFixVectorNormal(a1, a2); return; @@ -261,6 +262,7 @@ void SphereHitInfo::calcFixVector(sead::Vector3f* a1, sead::Vector3f* a2) const } void SphereHitInfo::calcFixVectorNormal(sead::Vector3f* a1, sead::Vector3f* a2) const { + auto* hitInfo = this; f32 unk = hitInfo->_70; a1->x = hitInfo->triangle.getFaceNormal().x * unk; a1->y = hitInfo->triangle.getFaceNormal().y * unk; @@ -271,21 +273,21 @@ void SphereHitInfo::calcFixVectorNormal(sead::Vector3f* a1, sead::Vector3f* a2) void DiskHitInfo::calcFixVector(sead::Vector3f* a1, sead::Vector3f* a2) const { // TODO add proper names here, once the missing names for _70 and _80 in HitInfo are found - if (hitInfo->isCollisionAtFace()) { + if (isCollisionAtFace()) { calcFixVectorNormal(a1, a2); return; } sead::Vector3f v20; - v20.x = hitInfo->_80.x - hitInfo->collisionHitPos.x; - v20.y = hitInfo->_80.y - hitInfo->collisionHitPos.y; - v20.z = hitInfo->_80.z - hitInfo->collisionHitPos.z; + v20.x = _80.x - collisionHitPos.x; + v20.y = _80.y - collisionHitPos.y; + v20.z = _80.z - collisionHitPos.z; tryNormalizeOrZero(&v20); sead::Vector3f scaled_a1; sead::Vector3f scaled_a2; - f32 v13 = v20.dot(hitInfo->triangle.getFaceNormal() * hitInfo->_70); - f32 v12 = v20.dot(hitInfo->triangle.getFaceNormal()); + f32 v13 = v20.dot(triangle.getFaceNormal() * _70); + f32 v12 = v20.dot(triangle.getFaceNormal()); sead::Vector3CalcCommon::multScalar(scaled_a1, v20, v13); sead::Vector3CalcCommon::multScalar(scaled_a2, v20, v12); *a1 = scaled_a1; @@ -293,12 +295,12 @@ void DiskHitInfo::calcFixVector(sead::Vector3f* a1, sead::Vector3f* a2) const { } void DiskHitInfo::calcFixVectorNormal(sead::Vector3f* a1, sead::Vector3f* a2) const { - f32 unk = hitInfo->_70; - a1->x = hitInfo->triangle.getFaceNormal().x * unk; - a1->y = hitInfo->triangle.getFaceNormal().y * unk; - a1->z = hitInfo->triangle.getFaceNormal().z * unk; + f32 unk = _70; + a1->x = triangle.getFaceNormal().x * unk; + a1->y = triangle.getFaceNormal().y * unk; + a1->z = triangle.getFaceNormal().z * unk; if (a2) - a2->set(hitInfo->triangle.getFaceNormal()); + a2->set(triangle.getFaceNormal()); } } // namespace al diff --git a/lib/al/Library/Collision/CollisionPartsTriangle.h b/lib/al/Library/Collision/CollisionPartsTriangle.h index b30e63ca..ba24c8bb 100644 --- a/lib/al/Library/Collision/CollisionPartsTriangle.h +++ b/lib/al/Library/Collision/CollisionPartsTriangle.h @@ -91,46 +91,17 @@ struct HitInfo { CollisionLocation collisionLocation = CollisionLocation::None; }; -struct ArrowHitInfo { - HitInfo* operator*() { return hitInfo.data(); } - - const HitInfo* operator*() const { return hitInfo.data(); } - - HitInfo& operator->() { return *hitInfo; } - - const HitInfo& operator->() const { return *hitInfo; } - - sead::StorageFor hitInfo{sead::ZeroInitializeTag{}}; +struct ArrowHitInfo : public HitInfo { }; -struct SphereHitInfo { +struct SphereHitInfo : public HitInfo { void calcFixVector(sead::Vector3f* a1, sead::Vector3f* a2) const; void calcFixVectorNormal(sead::Vector3f* a1, sead::Vector3f* a2) const; - - HitInfo* operator*() { return hitInfo.data(); } - - const HitInfo* operator*() const { return hitInfo.data(); } - - HitInfo& operator->() { return *hitInfo; } - - const HitInfo& operator->() const { return *hitInfo; } - - sead::StorageFor hitInfo{sead::ZeroInitializeTag{}}; }; -struct DiskHitInfo { +struct DiskHitInfo : public HitInfo { void calcFixVector(sead::Vector3f* a1, sead::Vector3f* a2) const; void calcFixVectorNormal(sead::Vector3f* a1, sead::Vector3f* a2) const; - - HitInfo* operator*() { return hitInfo.data(); } - - const HitInfo* operator*() const { return hitInfo.data(); } - - HitInfo& operator->() { return *hitInfo; } - - const HitInfo& operator->() const { return *hitInfo; } - - sead::StorageFor hitInfo{sead::ZeroInitializeTag{}}; }; } // namespace al diff --git a/lib/al/Library/Collision/KCollisionServer.h b/lib/al/Library/Collision/KCollisionServer.h index 4cf12bde..f00aaddd 100644 --- a/lib/al/Library/Collision/KCollisionServer.h +++ b/lib/al/Library/Collision/KCollisionServer.h @@ -154,14 +154,22 @@ public: void getMoveVector(sead::Vector3f* moveVec); void calcStepMoveVector(sead::Vector3f* moveVec) const; + f32 getCurrentStep() const { + return mCurrentStep; + } + + f32 getPrevStep() const { + return mPrevStep; + } + private: - sead::Vector3f mPos; - sead::Vector3f mMove; - f32 mSizeStart; - f32 mSizeEnd; - f32 mStepSize; - f32 mCurrentStep; - f32 mPrevStep; + sead::Vector3f mPos = {0.0f, 0.0f, 0.0f}; + sead::Vector3f mMove = {0.0f, 0.0f, 0.0f}; + f32 mSizeStart = 0.0f; + f32 mSizeEnd = 0.0f; + f32 mStepSize = 0.0f; + f32 mCurrentStep = 0.0f; + f32 mPrevStep = 0.0f; }; class SpherePoseInterpolator { diff --git a/lib/al/Library/LiveActor/ActorCollisionFunction.cpp b/lib/al/Library/LiveActor/ActorCollisionFunction.cpp index 3efdcc4f..4ed01394 100644 --- a/lib/al/Library/LiveActor/ActorCollisionFunction.cpp +++ b/lib/al/Library/LiveActor/ActorCollisionFunction.cpp @@ -475,7 +475,7 @@ bool isCollidedCollisionCode(const LiveActor* actor, const char* sensorName, con u32 size = collider->getPlaneCount(); for (u32 i = 0; i < size; i++) - if (isEqualString(name, getCollisionCodeName(*collider->getPlane(i), sensorName))) + if (isEqualString(name, getCollisionCodeName(collider->getPlane(i), sensorName))) return true; return false; diff --git a/lib/al/Library/LiveActor/ActorMovementFunction.cpp b/lib/al/Library/LiveActor/ActorMovementFunction.cpp index 21138150..dbb77202 100644 --- a/lib/al/Library/LiveActor/ActorMovementFunction.cpp +++ b/lib/al/Library/LiveActor/ActorMovementFunction.cpp @@ -2,6 +2,7 @@ #include "Library/Area/AreaObjUtil.h" #include "Library/Audio/System/AudioKeeper.h" +#include "Library/Collision/Angle.h" #include "Library/Collision/Collider.h" #include "Library/Collision/CollisionPartsKeeperUtil.h" #include "Library/Collision/CollisionPartsTriangle.h" @@ -783,7 +784,7 @@ bool reboundVelocityFromTriangles(LiveActor* actor, f32 reboundStrength, f32 reb bool isRebound = false; for (s32 i = 0; i != planeCount; i++) { - sead::Vector3f normal = collider->getPlane(i)->getNormal(0); + sead::Vector3f normal = collider->getPlane(i).getNormal(0); f32 dot = normal.dot(getVelocity(actor)); if (reboundStrength < 0.0) { addVelocity(actor, -((reboundStrength + 1.0f) * dot * normal)); diff --git a/src/Player/CollidedShapeResult.cpp b/src/Player/CollidedShapeResult.cpp index 37f7190f..6c983567 100644 --- a/src/Player/CollidedShapeResult.cpp +++ b/src/Player/CollidedShapeResult.cpp @@ -6,15 +6,15 @@ CollidedShapeResult::CollidedShapeResult(const CollisionShapeInfoBase* shapeInfo : mShapeInfo(shapeInfo) {} void CollidedShapeResult::setArrowHitInfo(const al::ArrowHitInfo& arrowHitInfo) { - *mArrowHitInfo.hitInfo = *arrowHitInfo.hitInfo; + *mArrowHitInfo.data() = arrowHitInfo; } void CollidedShapeResult::setSphereHitInfo(const al::SphereHitInfo& sphereHitInfo) { - *mSphereHitInfo.hitInfo = *sphereHitInfo.hitInfo; + *mSphereHitInfo.data() = sphereHitInfo; } void CollidedShapeResult::setDiskHitInfo(const al::DiskHitInfo& diskHitInfo) { - *mDiskHitInfo.hitInfo = *diskHitInfo.hitInfo; + *mDiskHitInfo.data() = diskHitInfo; } bool CollidedShapeResult::isArrow() const { @@ -30,15 +30,15 @@ bool CollidedShapeResult::isDisk() const { } const al::ArrowHitInfo& CollidedShapeResult::getArrowHitInfo() const { - return mArrowHitInfo; + return mArrowHitInfo.ref(); } const al::SphereHitInfo& CollidedShapeResult::getSphereHitInfo() const { - return mSphereHitInfo; + return mSphereHitInfo.ref(); } const al::DiskHitInfo& CollidedShapeResult::getDiskHitInfo() const { - return mDiskHitInfo; + return mDiskHitInfo.ref(); } const CollisionShapeInfoArrow* CollidedShapeResult::getShapeInfoArrow() const { @@ -55,7 +55,7 @@ const CollisionShapeInfoDisk* CollidedShapeResult::getShapeInfoDisk() const { void CollidedShapeResult::operator=(const CollidedShapeResult& other) { mShapeInfo = other.mShapeInfo; - setArrowHitInfo(other.mArrowHitInfo); - setSphereHitInfo(other.mSphereHitInfo); - setDiskHitInfo(other.mDiskHitInfo); + setArrowHitInfo(other.getArrowHitInfo()); + setSphereHitInfo(other.getSphereHitInfo()); + setDiskHitInfo(other.getDiskHitInfo()); } diff --git a/src/Player/CollidedShapeResult.h b/src/Player/CollidedShapeResult.h index f5b0e0de..112e7563 100644 --- a/src/Player/CollidedShapeResult.h +++ b/src/Player/CollidedShapeResult.h @@ -33,9 +33,9 @@ public: private: const CollisionShapeInfoBase* mShapeInfo; - al::ArrowHitInfo mArrowHitInfo; - al::SphereHitInfo mSphereHitInfo; - al::DiskHitInfo mDiskHitInfo; + sead::StorageFor mArrowHitInfo {sead::ZeroInitializeTag{}}; + sead::StorageFor mSphereHitInfo {sead::ZeroInitializeTag{}}; + sead::StorageFor mDiskHitInfo {sead::ZeroInitializeTag{}}; }; static_assert(sizeof(CollidedShapeResult) == 0x1e8); diff --git a/src/Player/PlayerCeilingCheck.cpp b/src/Player/PlayerCeilingCheck.cpp index c3a7d351..4db2fcb2 100644 --- a/src/Player/PlayerCeilingCheck.cpp +++ b/src/Player/PlayerCeilingCheck.cpp @@ -1,7 +1,7 @@ #include "Player/PlayerCeilingCheck.h" #include "Library/Base/StringUtil.h" -#include "Library/Collision/Collider.h" +#include "Library/Collision/Angle.h" #include "Player/PlayerCollisionCheckSphereMove.h" diff --git a/src/Player/PlayerJudgeWallKeep.cpp b/src/Player/PlayerJudgeWallKeep.cpp index 37819322..ea2de1c3 100644 --- a/src/Player/PlayerJudgeWallKeep.cpp +++ b/src/Player/PlayerJudgeWallKeep.cpp @@ -117,9 +117,9 @@ void PlayerJudgeWallKeep::update() { if (alCollisionUtil::getLastPolyOnArrow(mPlayer, &hitInfo1, nearWallPosition + sideOffset, -sideOffset, nullptr, &filterWallOnly)) { const sead::Vector3f& hitPos = - alCollisionUtil::getCollisionHitPos(hitInfo1->hitInfo.data()); + alCollisionUtil::getCollisionHitPos(hitInfo1); const sead::Vector3f& hitNormal = - alCollisionUtil::getCollisionHitNormal(hitInfo1->hitInfo.data()); + alCollisionUtil::getCollisionHitNormal(hitInfo1); if (!rs::calcExistCollisionBorder(mPlayer, hitPos, hitNormal)) { if (sead::Mathf::abs(al::calcAngleOnPlaneDegree( hitNormal, collidedWallNormal, gravity2)) > mConst->getWallFollowAngleH()) @@ -134,9 +134,9 @@ void PlayerJudgeWallKeep::update() { if (alCollisionUtil::getLastPolyOnArrow(mPlayer, &hitInfo2, nearWallPosition - sideOffset, sideOffset, nullptr, &filterWallOnly)) { const sead::Vector3f& hitPos = - alCollisionUtil::getCollisionHitPos(hitInfo2->hitInfo.data()); + alCollisionUtil::getCollisionHitPos(hitInfo2); const sead::Vector3f& hitNormal = - alCollisionUtil::getCollisionHitNormal(hitInfo2->hitInfo.data()); + alCollisionUtil::getCollisionHitNormal(hitInfo2); if (!rs::calcExistCollisionBorder(mPlayer, hitPos, hitNormal)) { if (sead::Mathf::abs(al::calcAngleOnPlaneDegree( hitNormal, collidedWallNormal, gravity2)) > mConst->getWallFollowAngleH())