Minor fixes, use CUnitVector in CCollionInfo

This commit is contained in:
Phillip Stephens 2021-05-23 13:10:57 -07:00
parent f468adc0a3
commit 8f493f17f1
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
5 changed files with 118 additions and 77 deletions

View File

@ -11,13 +11,15 @@
#include "Runtime/World/CWorld.hpp" #include "Runtime/World/CWorld.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path #include "TCastTo.hpp" // Generated file, do not modify include path
#include "math.h"
namespace metaforce { namespace metaforce {
void CGroundMovement::CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float) { void CGroundMovement::CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float /*dt*/) {
bool oob = true; bool oob = true;
zeus::CAABox plBox = *actor.GetTouchBounds();
for (const CGameArea& area : *mgr.GetWorld()) { for (const CGameArea& area : *mgr.GetWorld()) {
if (area.GetAABB().intersects(*actor.GetTouchBounds())) { if (area.GetAABB().intersects(plBox)) {
oob = false; oob = false;
break; break;
} }
@ -44,8 +46,9 @@ void CGroundMovement::MoveGroundCollider(CStateManager& mgr, CPhysicsActor& acto
CCollisionInfoList collisionList; CCollisionInfoList collisionList;
zeus::CAABox motionVol = actor.GetMotionVolume(dt); zeus::CAABox motionVol = actor.GetMotionVolume(dt);
rstl::reserved_vector<TUniqueId, 1024> useColliderList; rstl::reserved_vector<TUniqueId, 1024> useColliderList;
if (nearList) if (nearList != nullptr) {
useColliderList = *nearList; useColliderList = *nearList;
}
mgr.BuildColliderList(useColliderList, actor, motionVol); mgr.BuildColliderList(useColliderList, actor, motionVol);
CAreaCollisionCache cache(motionVol); CAreaCollisionCache cache(motionVol);
float collideDt = dt; float collideDt = dt;
@ -64,9 +67,8 @@ void CGroundMovement::MoveGroundCollider(CStateManager& mgr, CPhysicsActor& acto
} }
} }
actor.MoveCollisionPrimitive(newState.x0_translation); actor.MoveCollisionPrimitive(newState.x0_translation);
if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetPrimitiveTransform(),
actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), actor.GetMaterialFilter(), useColliderList, idDetect, collisionList)) {
useColliderList, idDetect, collisionList)) {
actor.AddMotionState(newState); actor.AddMotionState(newState);
float resolved = 0.f; float resolved = 0.f;
if (ResolveUpDown(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, actor.GetStepUpHeight(), 0.f, if (ResolveUpDown(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, actor.GetStepUpHeight(), 0.f,
@ -115,8 +117,9 @@ bool CGroundMovement::ResolveUpDown(CAreaCollisionCache& cache, CStateManager& m
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList, const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
float stepUp, float stepDown, float& fOut, CCollisionInfoList& list) { float stepUp, float stepDown, float& fOut, CCollisionInfoList& list) {
float zextent = stepDown; float zextent = stepDown;
if (list.GetCount() <= 0) if (list.GetCount() <= 0) {
return true; return true;
}
zeus::CAABox aabb = zeus::CAABox(); zeus::CAABox aabb = zeus::CAABox();
zeus::CVector3f normAccum = zeus::skZero3f; zeus::CVector3f normAccum = zeus::skZero3f;
@ -128,20 +131,23 @@ bool CGroundMovement::ResolveUpDown(CAreaCollisionCache& cache, CStateManager& m
} }
} }
if (normAccum.canBeNormalized()) if (normAccum.canBeNormalized()) {
normAccum.normalize(); normAccum.normalize();
else } else {
return true; return true;
}
zeus::CAABox actorAABB = actor.GetBoundingBox(); zeus::CAABox actorAABB = actor.GetBoundingBox();
if (normAccum.z() >= 0.f) { if (normAccum.z() >= 0.f) {
zextent = aabb.max.z() - actorAABB.min.z() + 0.02f; zextent = aabb.max.z() - actorAABB.min.z() + 0.02f;
if (zextent > stepUp) if (zextent > stepUp) {
return true; return true;
}
} else { } else {
zextent = aabb.min.z() - actorAABB.max.z() - 0.02f; zextent = aabb.min.z() - actorAABB.max.z() - 0.02f;
if (zextent < -stepDown) if (zextent < -stepDown) {
return true; return true;
}
} }
actor.MoveCollisionPrimitive({0.f, 0.f, zextent}); actor.MoveCollisionPrimitive({0.f, 0.f, zextent});
@ -160,8 +166,9 @@ bool CGroundMovement::ResolveUpDown(CAreaCollisionCache& cache, CStateManager& m
} }
} }
if (!floor) if (!floor) {
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor); mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor);
}
return false; return false;
} }
@ -208,17 +215,20 @@ bool CGroundMovement::MoveGroundColliderZ(CAreaCollisionCache& cache, CStateMana
} }
} }
if (!floor) if (!floor) {
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor); mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor);
}
CCollisionInfoList filteredList; CCollisionInfoList filteredList;
if (amt > 0.f) if (amt > 0.f) {
CollisionUtil::FilterByClosestNormal({0.f, 0.f, -1.f}, list, filteredList); CollisionUtil::FilterByClosestNormal({0.f, 0.f, -1.f}, list, filteredList);
else } else {
CollisionUtil::FilterByClosestNormal({0.f, 0.f, 1.f}, list, filteredList); CollisionUtil::FilterByClosestNormal({0.f, 0.f, 1.f}, list, filteredList);
}
if (filteredList.GetCount() > 0) if (filteredList.GetCount() > 0) {
CGameCollision::MakeCollisionCallbacks(mgr, actor, idOut, filteredList); CGameCollision::MakeCollisionCallbacks(mgr, actor, idOut, filteredList);
}
return true; return true;
} }
@ -237,11 +247,12 @@ void CGroundMovement::MoveGroundColliderXY(CAreaCollisionCache& cache, CStateMan
CCollisionInfoList collisionList; CCollisionInfoList collisionList;
CMotionState newMState = actor.PredictMotion_Internal(dt); CMotionState newMState = actor.PredictMotion_Internal(dt);
float transMag = newMState.x0_translation.magnitude(); float transMag = newMState.x0_translation.magnitude();
float divMag; float divMag = NAN;
if (isPlayer) if (isPlayer) {
divMag = std::max(transMag / 5.f, 0.005f); divMag = std::max(transMag / 5.f, 0.005f);
else } else {
divMag = std::max(transMag / 3.f, 0.02f); divMag = std::max(transMag / 3.f, 0.02f);
}
float minExtent = 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive()); float minExtent = 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive());
if (transMag > minExtent) { if (transMag > minExtent) {
@ -259,16 +270,19 @@ void CGroundMovement::MoveGroundColliderXY(CAreaCollisionCache& cache, CStateMan
bool collided = bool collided =
CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
actor.GetPrimitiveTransform(), filter, nearList, otherId, collisionList); actor.GetPrimitiveTransform(), filter, nearList, otherId, collisionList);
if (collided) if (collided) {
otherActor = mgr.ObjectById(otherId); otherActor = mgr.ObjectById(otherId);
}
actor.MoveCollisionPrimitive(zeus::skZero3f); actor.MoveCollisionPrimitive(zeus::skZero3f);
if (collided) { if (collided) {
didCollide = true; didCollide = true;
if (newMState.x0_translation.magnitude() < divMag) { if (newMState.x0_translation.magnitude() < divMag) {
CCollisionInfoList backfaceFilteredList, floorFilteredList; CCollisionInfoList backfaceFilteredList;
CCollisionInfoList floorFilteredList;
zeus::CVector3f deltaVel = actor.GetVelocity(); zeus::CVector3f deltaVel = actor.GetVelocity();
if (otherActor) if (otherActor) {
deltaVel -= otherActor->GetVelocity(); deltaVel -= otherActor->GetVelocity();
}
CollisionUtil::FilterOutBackfaces(deltaVel, collisionList, backfaceFilteredList); CollisionUtil::FilterOutBackfaces(deltaVel, collisionList, backfaceFilteredList);
CAABoxFilter::FilterBoxFloorCollisions(backfaceFilteredList, floorFilteredList); CAABoxFilter::FilterBoxFloorCollisions(backfaceFilteredList, floorFilteredList);
CGameCollision::MakeCollisionCallbacks(mgr, actor, otherId, floorFilteredList); CGameCollision::MakeCollisionCallbacks(mgr, actor, otherId, floorFilteredList);
@ -282,11 +296,12 @@ void CGroundMovement::MoveGroundColliderXY(CAreaCollisionCache& cache, CStateMan
CCollisionInfo infoCopy = info; CCollisionInfo infoCopy = info;
float restitution = float restitution =
CGameCollision::GetCoefficientOfRestitution(infoCopy) + actor.GetCoefficientOfRestitutionModifier(); CGameCollision::GetCoefficientOfRestitution(infoCopy) + actor.GetCoefficientOfRestitutionModifier();
if (otherActor) if (otherActor) {
CGameCollision::CollideWithDynamicBodyNoRot(actor, *otherActor, infoCopy, restitution, true); CGameCollision::CollideWithDynamicBodyNoRot(actor, *otherActor, infoCopy, restitution, true);
else } else {
CGameCollision::CollideWithStaticBodyNoRot(actor, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(), CGameCollision::CollideWithStaticBodyNoRot(actor, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(),
infoCopy.GetNormalLeft(), restitution, true); infoCopy.GetNormalLeft(), restitution, true);
}
} }
remDt -= dt; remDt -= dt;
nonCollideDt = std::min(originalDt, remDt); nonCollideDt = std::min(originalDt, remDt);
@ -305,8 +320,9 @@ void CGroundMovement::MoveGroundColliderXY(CAreaCollisionCache& cache, CStateMan
newMState = actor.PredictMotion_Internal(dt); newMState = actor.PredictMotion_Internal(dt);
} while (remDt > 0.f); } while (remDt > 0.f);
if (!didCollide && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) if (!didCollide && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) {
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling); mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling);
}
actor.MoveCollisionPrimitive(zeus::skZero3f); actor.MoveCollisionPrimitive(zeus::skZero3f);
} }
@ -322,20 +338,23 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
const rstl::reserved_vector<TUniqueId, 1024>* nearList) { const rstl::reserved_vector<TUniqueId, 1024>* nearList) {
zeus::CAABox motionVol = actor.GetMotionVolume(dt); zeus::CAABox motionVol = actor.GetMotionVolume(dt);
rstl::reserved_vector<TUniqueId, 1024> useNearList; rstl::reserved_vector<TUniqueId, 1024> useNearList;
if (nearList) if (nearList != nullptr) {
useNearList = *nearList; useNearList = *nearList;
else } else {
mgr.BuildColliderList(useNearList, actor, motionVol); mgr.BuildColliderList(useNearList, actor, motionVol);
}
CAreaCollisionCache cache(motionVol); CAreaCollisionCache cache(motionVol);
CGameCollision::BuildAreaCollisionCache(mgr, cache); CGameCollision::BuildAreaCollisionCache(mgr, cache);
CPlayer& player = static_cast<CPlayer&>(actor); auto& player = static_cast<CPlayer&>(actor);
player.x9c5_28_slidingOnWall = false; player.x9c5_28_slidingOnWall = false;
bool applyJump = player.x258_movementState == CPlayer::EPlayerMovementState::ApplyJump; bool applyJump = player.x258_movementState == CPlayer::EPlayerMovementState::ApplyJump;
bool dampUnderwater = false; bool dampUnderwater = false;
if (player.x9c4_31_inWaterMovement) if (player.x9c4_31_inWaterMovement) {
if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) {
dampUnderwater = true; dampUnderwater = true;
}
}
bool noJump = (player.x258_movementState != CPlayer::EPlayerMovementState::ApplyJump && bool noJump = (player.x258_movementState != CPlayer::EPlayerMovementState::ApplyJump &&
player.x258_movementState != CPlayer::EPlayerMovementState::Jump); player.x258_movementState != CPlayer::EPlayerMovementState::Jump);
@ -383,7 +402,7 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
CPhysicsState physStatePost = actor.GetPhysicsState(); CPhysicsState physStatePost = actor.GetPhysicsState();
/* NoStepLogic must be the only set material bit to bypass step logic */ /* NoStepLogic must be the only set material bit to bypass step logic */
if (material2.XOR({EMaterialTypes::NoStepLogic})) { if (material2.XOR({EMaterialTypes::NoStepLogic}) != 0u) {
SMovementOptions optsCopy = opts; SMovementOptions optsCopy = opts;
optsCopy.x19_alwaysClip = noJump; optsCopy.x19_alwaysClip = noJump;
optsCopy.x30_wallElasticConstant = 0.03f; optsCopy.x30_wallElasticConstant = 0.03f;
@ -412,7 +431,7 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
} }
if (useStepUp > 0.0005) { if (useStepUp > 0.0005) {
actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, useStepUp)); actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, static_cast<float>(useStepUp)));
SMoveObjectResult result2; SMoveObjectResult result2;
CMaterialList material3 = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, optsCopy, result2); CMaterialList material3 = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, optsCopy, result2);
@ -435,7 +454,7 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
float stepDelta = postToPre2.magSquared(); float stepDelta = postToPre2.magSquared();
if (floor && postToPreMag < stepDelta) { if (floor && postToPreMag < stepDelta) {
useStepDown2 = std::max(0.0, useStepDown2 - 0.0005); useStepDown2 = std::max(0.0, useStepDown2 - 0.0005);
actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, useStepDown2)); actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, static_cast<float>(useStepDown2)));
physStateList.push_back(actor.GetPhysicsState()); physStateList.push_back(actor.GetPhysicsState());
stepDeltaList.push_back(stepDelta); stepDeltaList.push_back(stepDelta);
collisionInfoList.push_back(collisionInfo2); collisionInfoList.push_back(collisionInfo2);
@ -445,7 +464,7 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
} }
} }
if (physStateList.size() == 0) { if (physStateList.empty()) {
actor.SetPhysicsState(physStatePost); actor.SetPhysicsState(physStatePost);
material = material2; material = material2;
} else { } else {
@ -463,8 +482,9 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
if (CEntity* ent = mgr.ObjectById(uniqueIdList[maxIdx])) { if (CEntity* ent = mgr.ObjectById(uniqueIdList[maxIdx])) {
result.x0_id.emplace(uniqueIdList[maxIdx]); result.x0_id.emplace(uniqueIdList[maxIdx]);
result.x8_collision.emplace(collisionInfoList[maxIdx]); result.x8_collision.emplace(collisionInfoList[maxIdx]);
if (TCastToPtr<CScriptPlatform>(ent)) if (TCastToPtr<CScriptPlatform>(ent)) {
mgr.SendScriptMsg(ent, actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); mgr.SendScriptMsg(ent, actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider);
}
} }
CCollisionInfo& cInfo = collisionInfoList[maxIdx]; CCollisionInfo& cInfo = collisionInfoList[maxIdx];
@ -529,24 +549,27 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
xf.origin -= zeus::CVector3f(0.f, 0.f, zOffset); xf.origin -= zeus::CVector3f(0.f, 0.f, zOffset);
} }
if (collisionInfo.IsValid()) if (collisionInfo.IsValid()) {
player.x9c5_28_slidingOnWall = true; player.x9c5_28_slidingOnWall = true;
}
CheckFalling(actor, mgr, dt); CheckFalling(actor, mgr, dt);
player.SetLastFloorPlaneNormal({}); player.SetLastFloorPlaneNormal({});
} else { } else {
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor);
stepDown2 = std::max(0.0, stepDown2 - 0.0005); stepDown2 = std::max(0.0, stepDown2 - 0.0005);
actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, stepDown2)); actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, static_cast<float>(stepDown2)));
if (TCastToPtr<CScriptPlatform> plat = mgr.ObjectById(id)) if (TCastToPtr<CScriptPlatform> plat = mgr.ObjectById(id)) {
mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider);
}
CGameCollision::SendMaterialMessage(mgr, collisionInfo.GetMaterialLeft(), actor); CGameCollision::SendMaterialMessage(mgr, collisionInfo.GetMaterialLeft(), actor);
actor.SetLastFloorPlaneNormal({collisionInfo.GetNormalLeft()}); actor.SetLastFloorPlaneNormal({collisionInfo.GetNormalLeft()});
} }
} }
actor.ClearForcesAndTorques(); actor.ClearForcesAndTorques();
if (material.HasMaterial(EMaterialTypes::Wall)) if (material.HasMaterial(EMaterialTypes::Wall)) {
player.SetPlayerHitWallDuringMove(); player.SetPlayerHitWallDuringMove();
}
if (result.x0_id) { if (result.x0_id) {
CCollisionInfoList list; CCollisionInfoList list;
@ -562,12 +585,12 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
const CCollisionPrimitive* usePrim = actor.GetCollisionPrimitive(); const CCollisionPrimitive* usePrim = actor.GetCollisionPrimitive();
std::unique_ptr<CCollisionPrimitive> prim; std::unique_ptr<CCollisionPrimitive> prim;
if (usePrim->GetPrimType() == FOURCC('AABX')) { if (usePrim->GetPrimType() == FOURCC('AABX')) {
const CCollidableAABox& existingAABB = static_cast<const CCollidableAABox&>(*usePrim); const auto& existingAABB = static_cast<const CCollidableAABox&>(*usePrim);
prim = std::make_unique<CCollidableAABox>( prim = std::make_unique<CCollidableAABox>(
zeus::CAABox(existingAABB.GetBox().min + 0.0001f, existingAABB.GetBox().max - 0.0001f), usePrim->GetMaterial()); zeus::CAABox(existingAABB.GetBox().min + 0.0001f, existingAABB.GetBox().max - 0.0001f), usePrim->GetMaterial());
usePrim = prim.get(); usePrim = prim.get();
} else if (usePrim->GetPrimType() == FOURCC('SPHR')) { } else if (usePrim->GetPrimType() == FOURCC('SPHR')) {
const CCollidableSphere& existingSphere = static_cast<const CCollidableSphere&>(*usePrim); const auto& existingSphere = static_cast<const CCollidableSphere&>(*usePrim);
prim = std::make_unique<CCollidableSphere>( prim = std::make_unique<CCollidableSphere>(
zeus::CSphere(existingSphere.GetSphere().position, existingSphere.GetSphere().radius - 0.0001f), zeus::CSphere(existingSphere.GetSphere().position, existingSphere.GetSphere().radius - 0.0001f),
usePrim->GetMaterial()); usePrim->GetMaterial());
@ -580,14 +603,17 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, const zeus::CVector3f& b, zeus::CVector3f& c, bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, const zeus::CVector3f& b, zeus::CVector3f& c,
float& d) { float& d) {
float dot = a.dot(c); float dot = a.dot(c);
if (std::fabs(dot) > 0.99f) if (std::fabs(dot) > 0.99f) {
return false; return false;
}
float dot2 = b.dot(c); float dot2 = b.dot(c);
float dot3 = b.dot((c - a * dot).normalized()); float dot3 = b.dot((c - a * dot).normalized());
if (dot2 > 0.f && dot3 < 0.f) if (dot2 > 0.f && dot3 < 0.f) {
return false; return false;
if (std::fabs(dot2) > 0.01f && std::fabs(dot3 / dot2) > 4.f) }
if (std::fabs(dot2) > 0.01f && std::fabs(dot3 / dot2) > 4.f) {
return false; return false;
}
c -= dot * a; c -= dot * a;
d = dot; d = dot;
return true; return true;
@ -595,8 +621,9 @@ bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, const zeus
bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b) { bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b) {
float dot = a.dot(b); float dot = a.dot(b);
if (std::fabs(dot) > 0.99f) if (std::fabs(dot) > 0.99f) {
return false; return false;
}
b -= a * dot; b -= a * dot;
return true; return true;
} }
@ -617,7 +644,7 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
result.x6c_processedCollisions = 0; result.x6c_processedCollisions = 0;
CMaterialList ret; CMaterialList ret;
zeus::CVector3f floorPlaneNormal = opts.x3c_floorPlaneNormal ? *opts.x3c_floorPlaneNormal : zeus::skZero3f; zeus::CVector3f floorPlaneNormal = opts.x3c_floorPlaneNormal ? *opts.x3c_floorPlaneNormal : zeus::skZero3f;
bool floorCollision = opts.x3c_floorPlaneNormal.operator bool(); bool floorCollision = opts.x3c_floorPlaneNormal.has_value();
float remDt = dt; float remDt = dt;
for (size_t i = 0; remDt > 0.f; ++i) { for (size_t i = 0; remDt > 0.f; ++i) {
float collideDt = remDt; float collideDt = remDt;
@ -637,7 +664,7 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
result.x0_id.emplace(id); result.x0_id.emplace(id);
result.x8_collision.emplace(collisionInfo); result.x8_collision.emplace(collisionInfo);
} }
collideDt = mag / oldMag * remDt; collideDt = static_cast<float>(mag / oldMag * remDt);
} }
mag = std::max(0.f, float(mag) - opts.x20_minimumTranslationDelta); mag = std::max(0.f, float(mag) - opts.x20_minimumTranslationDelta);
@ -646,8 +673,9 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
bool floor = CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionNorm); bool floor = CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionNorm);
bool clipCollision = true; bool clipCollision = true;
if (!opts.x19_alwaysClip) { if (!opts.x19_alwaysClip) {
if (!opts.x1a_disableClipForFloorOnly || floor) if (!opts.x1a_disableClipForFloorOnly || floor) {
clipCollision = false; clipCollision = false;
}
} }
float collisionFloorDot = 0.f; float collisionFloorDot = 0.f;
@ -664,10 +692,11 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
if (clipCollision) { if (clipCollision) {
if (floorCollision) { if (floorCollision) {
if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, normTrans, collisionNorm, collisionFloorDot)) if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, normTrans, collisionNorm, collisionFloorDot)) {
RemovePositiveZComponentFromNormal(collisionNorm); RemovePositiveZComponentFromNormal(collisionNorm);
else } else {
collisionNorm.normalize(); collisionNorm.normalize();
}
} else { } else {
RemovePositiveZComponentFromNormal(collisionNorm); RemovePositiveZComponentFromNormal(collisionNorm);
} }
@ -676,7 +705,7 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
mState = actor.PredictMotion_Internal(collideDt); mState = actor.PredictMotion_Internal(collideDt);
} }
mState.x0_translation = normTrans * mag; mState.x0_translation = normTrans * static_cast<float>(mag);
actor.AddMotionState(mState); actor.AddMotionState(mState);
if (collisionInfo.IsValid()) { if (collisionInfo.IsValid()) {
@ -688,13 +717,17 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
float elasticForce = floor ? opts.x2c_floorElasticForce float elasticForce = floor ? opts.x2c_floorElasticForce
: opts.x34_wallElasticLinear * collisionFloorDot + opts.x30_wallElasticConstant; : opts.x34_wallElasticLinear * collisionFloorDot + opts.x30_wallElasticConstant;
float dot = collisionNorm.dot(vel); float dot = collisionNorm.dot(vel);
if (dot < elasticForce) if (dot < elasticForce) {
vel += (elasticForce - dot) * collisionNorm; vel += (elasticForce - dot) * collisionNorm;
if (clipCollision && floorCollision) }
if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, vel)) if (clipCollision && floorCollision) {
if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, vel)) {
vel.z() = 0.f; vel.z() = 0.f;
if (vel.z() > opts.x38_maxPositiveVerticalVelocity) }
}
if (vel.z() > opts.x38_maxPositiveVerticalVelocity) {
vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z()); vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z());
}
if (opts.x18_dampForceAndMomentum) { if (opts.x18_dampForceAndMomentum) {
if (actor.x15c_force.canBeNormalized()) { if (actor.x15c_force.canBeNormalized()) {
@ -709,8 +742,9 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
} }
if (opts.x0_setWaterLandingForce && !floor) { if (opts.x0_setWaterLandingForce && !floor) {
if (collisionInfo.GetNormalLeft().z() < -0.1f && vel.z() > 0.f) if (collisionInfo.GetNormalLeft().z() < -0.1f && vel.z() > 0.f) {
vel.z() *= 0.5f; vel.z() *= 0.5f;
}
float zNormAbs = std::fabs(collisionInfo.GetNormalLeft().z()); float zNormAbs = std::fabs(collisionInfo.GetNormalLeft().z());
if ((zNormAbs > opts.x10_downwardZThreshold && vel.z() < 0.f) || zNormAbs > opts.xc_anyZThreshold) { if ((zNormAbs > opts.x10_downwardZThreshold && vel.z() < 0.f) || zNormAbs > opts.xc_anyZThreshold) {
@ -725,8 +759,9 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
actor.SetVelocityWR(vel); actor.SetVelocityWR(vel);
} else { } else {
zeus::CVector3f vel = actor.x138_velocity; zeus::CVector3f vel = actor.x138_velocity;
if (actor.x138_velocity.z() > opts.x38_maxPositiveVerticalVelocity) if (actor.x138_velocity.z() > opts.x38_maxPositiveVerticalVelocity) {
vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z()); vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z());
}
actor.SetVelocityWR(vel); actor.SetVelocityWR(vel);
} }
@ -734,8 +769,9 @@ CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysics
actor.ClearImpulses(); actor.ClearImpulses();
remDt -= collideDt; remDt -= collideDt;
if (i >= opts.x1c_maxCollisionCycles) if (i >= opts.x1c_maxCollisionCycles) {
break; break;
}
} }
result.x70_processedDt = dt - remDt; result.x70_processedDt = dt - remDt;

View File

@ -19,13 +19,13 @@ class CCollisionInfo {
bool x31_hasExtents = false; bool x31_hasExtents = false;
CMaterialList x38_materialLeft; CMaterialList x38_materialLeft;
CMaterialList x40_materialRight; CMaterialList x40_materialRight;
zeus::CVector3f x48_normalLeft; zeus::CUnitVector3f x48_normalLeft;
zeus::CVector3f x54_normalRight; zeus::CUnitVector3f x54_normalRight;
public: public:
CCollisionInfo() = default; CCollisionInfo() = default;
CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2, CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2,
const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight) const zeus::CUnitVector3f& normalLeft, const zeus::CUnitVector3f& normalRight)
: x0_point(point) : x0_point(point)
, x30_valid(true) , x30_valid(true)
, x31_hasExtents(false) , x31_hasExtents(false)
@ -34,7 +34,7 @@ public:
, x48_normalLeft(normalLeft) , x48_normalLeft(normalLeft)
, x54_normalRight(normalRight) {} , x54_normalRight(normalRight) {}
CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2, CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2,
const zeus::CVector3f& normal) const zeus::CUnitVector3f& normal)
: x0_point(point) : x0_point(point)
, x30_valid(true) , x30_valid(true)
, x31_hasExtents(false) , x31_hasExtents(false)
@ -43,7 +43,7 @@ public:
, x48_normalLeft(normal) , x48_normalLeft(normal)
, x54_normalRight(-normal) {} , x54_normalRight(-normal) {}
CCollisionInfo(const zeus::CAABox& aabox, const CMaterialList& list1, const CMaterialList& list2, CCollisionInfo(const zeus::CAABox& aabox, const CMaterialList& list1, const CMaterialList& list2,
const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight) const zeus::CUnitVector3f& normalLeft, const zeus::CUnitVector3f& normalRight)
: x0_point(aabox.min) : x0_point(aabox.min)
, xc_extentX(aabox.max.x() - aabox.min.x(), 0.f, 0.f) , xc_extentX(aabox.max.x() - aabox.min.x(), 0.f, 0.f)
, x18_extentY(0.f, aabox.max.y() - aabox.min.y(), 0.f) , x18_extentY(0.f, aabox.max.y() - aabox.min.y(), 0.f)
@ -61,8 +61,8 @@ public:
const CMaterialList& GetMaterialRight() const { return x40_materialRight; } const CMaterialList& GetMaterialRight() const { return x40_materialRight; }
zeus::CVector3f GetExtreme() const; zeus::CVector3f GetExtreme() const;
void Swap(); void Swap();
const zeus::CVector3f& GetNormalLeft() const { return x48_normalLeft; } const zeus::CUnitVector3f& GetNormalLeft() const { return x48_normalLeft; }
const zeus::CVector3f& GetNormalRight() const { return x54_normalRight; } const zeus::CUnitVector3f& GetNormalRight() const { return x54_normalRight; }
const zeus::CVector3f& GetPoint() const { return x0_point; } const zeus::CVector3f& GetPoint() const { return x0_point; }
}; };

View File

@ -218,7 +218,7 @@ void CGameCollision::Move(CStateManager& mgr, CPhysicsActor& actor, float dt,
} }
} }
bool CGameCollision::CanBlock(const CMaterialList& mat, const zeus::CVector3f& v) { bool CGameCollision::CanBlock(const CMaterialList& mat, const zeus::CUnitVector3f& v) {
if ((mat.HasMaterial(EMaterialTypes::Character) && !mat.HasMaterial(EMaterialTypes::SolidCharacter)) || if ((mat.HasMaterial(EMaterialTypes::Character) && !mat.HasMaterial(EMaterialTypes::SolidCharacter)) ||
mat.HasMaterial(EMaterialTypes::NoPlayerCollision)) { mat.HasMaterial(EMaterialTypes::NoPlayerCollision)) {
return false; return false;
@ -231,7 +231,7 @@ bool CGameCollision::CanBlock(const CMaterialList& mat, const zeus::CVector3f& v
return (v.z() > 0.85f); return (v.z() > 0.85f);
} }
bool CGameCollision::IsFloor(const CMaterialList& mat, const zeus::CVector3f& v) { bool CGameCollision::IsFloor(const CMaterialList& mat, const zeus::CUnitVector3f& v) {
return mat.HasMaterial(EMaterialTypes::Floor) || v.z() > 0.85f; return mat.HasMaterial(EMaterialTypes::Floor) || v.z() > 0.85f;
} }

View File

@ -41,8 +41,8 @@ public:
static void Move(CStateManager& mgr, CPhysicsActor& actor, float dt, static void Move(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList); const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
static bool CanBlock(const CMaterialList&, const zeus::CVector3f&); static bool CanBlock(const CMaterialList&, const zeus::CUnitVector3f&);
static bool IsFloor(const CMaterialList&, const zeus::CVector3f&); static bool IsFloor(const CMaterialList&, const zeus::CUnitVector3f&);
static void SendMaterialMessage(CStateManager&, const CMaterialList&, CActor&); static void SendMaterialMessage(CStateManager&, const CMaterialList&, CActor&);
static CRayCastResult RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos, static CRayCastResult RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos,
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter); const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter);

View File

@ -29,8 +29,9 @@ void CPhysicsActor::Render(CStateManager& mgr) { CActor::Render(mgr); }
zeus::CVector3f CPhysicsActor::GetOrbitPosition(const CStateManager&) const { return GetBoundingBox().center(); } zeus::CVector3f CPhysicsActor::GetOrbitPosition(const CStateManager&) const { return GetBoundingBox().center(); }
zeus::CVector3f CPhysicsActor::GetAimPosition(const CStateManager&, float dt) const { zeus::CVector3f CPhysicsActor::GetAimPosition(const CStateManager&, float dt) const {
if (dt <= 0.0) if (dt <= 0.0) {
return GetBoundingBox().center(); return GetBoundingBox().center();
}
zeus::CVector3f trans = PredictMotion(dt).x0_translation; zeus::CVector3f trans = PredictMotion(dt).x0_translation;
return GetBoundingBox().center() + trans; return GetBoundingBox().center() + trans;
} }
@ -91,9 +92,9 @@ void CPhysicsActor::AddMotionState(const CMotionState& mst) {
zeus::CNUQuaternion q{x34_transform.buildMatrix3f()}; zeus::CNUQuaternion q{x34_transform.buildMatrix3f()};
q += mst.xc_orientation; q += mst.xc_orientation;
zeus::CQuaternion quat = zeus::CQuaternion::fromNUQuaternion(q); zeus::CQuaternion quat = zeus::CQuaternion::fromNUQuaternion(q);
// if (TCastToPtr<CPlayer>(this)) { // if (TCastToPtr<CPlayer>(this)) {
// fmt::print(FMT_STRING("ADD {}\n"), mst.x0_translation); // fmt::print(FMT_STRING("ADD {}\n"), mst.x0_translation);
// } // }
SetTransform(zeus::CTransform(quat, x34_transform.origin)); SetTransform(zeus::CTransform(quat, x34_transform.origin));
SetTranslation(x34_transform.origin + mst.x0_translation); SetTranslation(x34_transform.origin + mst.x0_translation);
@ -118,8 +119,9 @@ void CPhysicsActor::SetMotionState(const CMotionState& mst) {
} }
void CPhysicsActor::SetInertiaTensorScalar(float tensor) { void CPhysicsActor::SetInertiaTensorScalar(float tensor) {
if (tensor <= 0.0f) if (tensor <= 0.0f) {
tensor = 1.0f; tensor = 1.0f;
}
xf0_inertiaTensor = tensor; xf0_inertiaTensor = tensor;
xf4_inertiaTensorRecip = 1.0f / tensor; xf4_inertiaTensorRecip = 1.0f / tensor;
} }
@ -127,8 +129,9 @@ void CPhysicsActor::SetInertiaTensorScalar(float tensor) {
void CPhysicsActor::SetMass(float mass) { void CPhysicsActor::SetMass(float mass) {
xe8_mass = mass; xe8_mass = mass;
float tensor = 1.0f; float tensor = 1.0f;
if (mass > 0.0f) if (mass > 0.0f) {
tensor = 1.0f / mass; tensor = 1.0f / mass;
}
xec_massRecip = tensor; xec_massRecip = tensor;
SetInertiaTensorScalar(0.16666667f * mass); SetInertiaTensorScalar(0.16666667f * mass);
@ -185,8 +188,9 @@ void CPhysicsActor::MoveToWR(const zeus::CVector3f& trans, float d) {
} }
zeus::CAxisAngle CPhysicsActor::GetRotateToORAngularMomentumWR(const zeus::CQuaternion& q, float d) const { zeus::CAxisAngle CPhysicsActor::GetRotateToORAngularMomentumWR(const zeus::CQuaternion& q, float d) const {
if (q.w() > 0.99999976) if (q.w() > 0.99999976) {
return zeus::CAxisAngle(); return zeus::CAxisAngle();
}
return (xf0_inertiaTensor * return (xf0_inertiaTensor *
(((2.f * std::acos(q.w())) * (1.f / d)) * x34_transform.rotate(q.getImaginary()).normalized())); (((2.f * std::acos(q.w())) * (1.f / d)) * x34_transform.rotate(q.getImaginary()).normalized()));
} }
@ -250,8 +254,9 @@ CPhysicsState CPhysicsActor::GetPhysicsState() const {
} }
CMotionState CPhysicsActor::PredictMotion_Internal(float dt) const { CMotionState CPhysicsActor::PredictMotion_Internal(float dt) const {
if (xf8_25_angularEnabled) if (xf8_25_angularEnabled) {
return PredictLinearMotion(dt); return PredictLinearMotion(dt);
}
CMotionState msl = PredictLinearMotion(dt); CMotionState msl = PredictLinearMotion(dt);
CMotionState msa = PredictAngularMotion(dt); CMotionState msa = PredictAngularMotion(dt);