mirror of https://github.com/AxioDL/metaforce.git
Initial work on CGroundMovement
This commit is contained in:
parent
c854a45dfe
commit
d4a97861dc
|
@ -1499,27 +1499,27 @@ bool CStateManager::TestRayDamage(const zeus::CVector3f& pos, const CActor& dama
|
|||
return CGameCollision::RayDynamicIntersectionBool(*this, pos, dir, filter, nearList, &damagee, depth * origMag);
|
||||
}
|
||||
|
||||
bool CStateManager::RayCollideWorld(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
bool CStateManager::RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CMaterialFilter& filter, const CActor& damagee)
|
||||
{
|
||||
return RayCollideWorldInternal(pos, damageeCenter, filter, nearList, &damagee);
|
||||
return RayCollideWorldInternal(start, end, filter, nearList, &damagee);
|
||||
}
|
||||
|
||||
bool CStateManager::RayCollideWorldInternal(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
bool CStateManager::RayCollideWorldInternal(const zeus::CVector3f& start, const zeus::CVector3f& end,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CActor* damagee)
|
||||
{
|
||||
zeus::CVector3f vecToDamagee = damageeCenter - pos;
|
||||
if (!vecToDamagee.canBeNormalized())
|
||||
zeus::CVector3f delta = end - start;
|
||||
if (!delta.canBeNormalized())
|
||||
return true;
|
||||
|
||||
float mag = vecToDamagee.magnitude();
|
||||
zeus::CVector3f dir = vecToDamagee * (1.f / mag);
|
||||
if (!CGameCollision::RayStaticIntersectionBool(*this, pos, dir, mag, filter))
|
||||
float mag = delta.magnitude();
|
||||
zeus::CVector3f dir = delta * (1.f / mag);
|
||||
if (!CGameCollision::RayStaticIntersectionBool(*this, start, dir, mag, filter))
|
||||
return false;
|
||||
return CGameCollision::RayDynamicIntersectionBool(*this, pos, dir, filter, nearList, damagee, mag);
|
||||
return CGameCollision::RayDynamicIntersectionBool(*this, start, dir, filter, nearList, damagee, mag);
|
||||
}
|
||||
|
||||
bool CStateManager::MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter)
|
||||
|
|
|
@ -332,10 +332,10 @@ public:
|
|||
const CDamageInfo& info);
|
||||
bool TestRayDamage(const zeus::CVector3f& pos, const CActor& damagee,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
|
||||
bool RayCollideWorld(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
bool RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CMaterialFilter& filter, const CActor& damagee);
|
||||
bool RayCollideWorldInternal(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
bool RayCollideWorldInternal(const zeus::CVector3f& start, const zeus::CVector3f& end,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CActor* damagee);
|
||||
|
|
|
@ -0,0 +1,619 @@
|
|||
#include "CGroundMovement.hpp"
|
||||
#include "World/CPhysicsActor.hpp"
|
||||
#include "Collision/CGameCollision.hpp"
|
||||
#include "Collision/CCollisionInfoList.hpp"
|
||||
#include "Collision/CollisionUtil.hpp"
|
||||
#include "Collision/CAABoxFilter.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
#include "TCastTo.hpp"
|
||||
#include "World/CScriptPlatform.hpp"
|
||||
#include "World/CWorld.hpp"
|
||||
#include "World/CPlayer.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
void CGroundMovement::CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float)
|
||||
{
|
||||
bool oob = true;
|
||||
for (const CGameArea& area : *mgr.GetWorld())
|
||||
{
|
||||
if (area.GetAABB().intersects(*actor.GetTouchBounds()))
|
||||
{
|
||||
oob = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!oob)
|
||||
{
|
||||
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling);
|
||||
}
|
||||
else
|
||||
{
|
||||
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor);
|
||||
actor.SetAngularVelocityWR(actor.GetAngularVelocityWR() * 0.98f);
|
||||
zeus::CVector3f vel = actor.GetTransform().transposeRotate(actor.GetVelocity());
|
||||
vel.z = 0.f;
|
||||
actor.SetVelocityOR(vel);
|
||||
actor.SetMomentumWR(zeus::CVector3f::skZero);
|
||||
}
|
||||
}
|
||||
|
||||
void CGroundMovement::MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* nearList)
|
||||
{
|
||||
CMotionState oldState = actor.GetMotionState();
|
||||
CMotionState newState = actor.PredictMotion_Internal(dt);
|
||||
float deltaMag = newState.x0_translation.magnitude();
|
||||
TUniqueId idDetect = kInvalidUniqueId;
|
||||
CCollisionInfoList collisionList;
|
||||
zeus::CAABox motionVol = actor.GetMotionVolume(dt);
|
||||
rstl::reserved_vector<TUniqueId, 1024> useColliderList;
|
||||
if (nearList)
|
||||
useColliderList = *nearList;
|
||||
mgr.BuildColliderList(useColliderList, actor, motionVol);
|
||||
CAreaCollisionCache cache(motionVol);
|
||||
float collideDt = dt;
|
||||
if (actor.GetCollisionPrimitive()->GetPrimType() == FOURCC('OBTG'))
|
||||
{
|
||||
CGameCollision::BuildAreaCollisionCache(mgr, cache);
|
||||
if (deltaMag > 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive()))
|
||||
{
|
||||
zeus::CVector3f point =
|
||||
actor.GetCollisionPrimitive()->CalculateAABox(actor.GetPrimitiveTransform()).center();
|
||||
TUniqueId intersectId = kInvalidUniqueId;
|
||||
CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid});
|
||||
CRayCastResult result =
|
||||
mgr.RayWorldIntersection(intersectId, point, newState.x0_translation.normalized(), deltaMag,
|
||||
filter, useColliderList);
|
||||
if (result.IsValid())
|
||||
{
|
||||
collideDt = dt * (result.GetT() / deltaMag);
|
||||
newState = actor.PredictMotion_Internal(collideDt);
|
||||
}
|
||||
actor.MoveCollisionPrimitive(newState.x0_translation);
|
||||
if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||
actor.GetPrimitiveTransform(), actor.GetMaterialFilter(),
|
||||
useColliderList, idDetect, collisionList))
|
||||
{
|
||||
actor.AddMotionState(newState);
|
||||
float resolved = 0.f;
|
||||
if (ResolveUpDown(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList,
|
||||
actor.GetStepUpHeight(), 0.f, resolved, collisionList))
|
||||
{
|
||||
actor.SetMotionState(oldState);
|
||||
MoveGroundColliderXY(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, collideDt);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
actor.AddMotionState(newState);
|
||||
}
|
||||
|
||||
float stepDown = actor.GetStepDownHeight();
|
||||
float resolved = 0.f;
|
||||
collisionList.Clear();
|
||||
TUniqueId stepZId = kInvalidUniqueId;
|
||||
if (stepDown >= 0.f)
|
||||
{
|
||||
if (MoveGroundColliderZ(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList,
|
||||
-stepDown, resolved, collisionList, stepZId))
|
||||
{
|
||||
if (collisionList.GetCount() > 0)
|
||||
{
|
||||
CCollisionInfoList filteredList;
|
||||
CollisionUtil::FilterByClosestNormal(zeus::CVector3f{0.f, 0.f, 1.f}, collisionList, filteredList);
|
||||
if (filteredList.GetCount() > 0)
|
||||
{
|
||||
if (CGameCollision::IsFloor(filteredList.Front().GetMaterialLeft(),
|
||||
filteredList.Front().GetNormalLeft()))
|
||||
{
|
||||
if (TCastToPtr<CScriptPlatform> plat = mgr.ObjectById(stepZId))
|
||||
mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(),
|
||||
EScriptObjectMessage::AddPlatformRider);
|
||||
CGameCollision::SendMaterialMessage(mgr, filteredList.Front().GetMaterialLeft(), actor);
|
||||
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckFalling(actor, mgr, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckFalling(actor, mgr, dt);
|
||||
}
|
||||
|
||||
actor.ClearForcesAndTorques();
|
||||
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
||||
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Player))
|
||||
{
|
||||
CGameCollision::CollisionFailsafe(mgr, cache, actor, *actor.GetCollisionPrimitive(),
|
||||
useColliderList, 0.f, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CGroundMovement::ResolveUpDown(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
||||
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
float stepUp, float stepDown, float& fOut, CCollisionInfoList& list)
|
||||
{
|
||||
float zextent = stepDown;
|
||||
if (list.GetCount() <= 0)
|
||||
return true;
|
||||
|
||||
zeus::CAABox aabb = zeus::CAABox::skInvertedBox;
|
||||
zeus::CVector3f normAccum = zeus::CVector3f::skZero;
|
||||
for (CCollisionInfo& info : list)
|
||||
{
|
||||
if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft()))
|
||||
{
|
||||
aabb.accumulateBounds(info.GetPoint());
|
||||
aabb.accumulateBounds(info.GetExtreme());
|
||||
normAccum += info.GetNormalLeft();
|
||||
}
|
||||
}
|
||||
|
||||
if (normAccum.canBeNormalized())
|
||||
normAccum.normalize();
|
||||
else
|
||||
return true;
|
||||
|
||||
zeus::CAABox actorAABB = actor.GetBoundingBox();
|
||||
if (normAccum.z >= 0.f)
|
||||
{
|
||||
zextent = aabb.max.z - actorAABB.min.z + 0.02f;
|
||||
if (zextent > stepUp)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
zextent = aabb.min.z - actorAABB.max.z - 0.02f;
|
||||
if (zextent < -stepDown)
|
||||
return true;
|
||||
}
|
||||
|
||||
actor.MoveCollisionPrimitive({0.f, 0.f, zextent});
|
||||
|
||||
if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||
actor.GetPrimitiveTransform(), filter, nearList))
|
||||
{
|
||||
fOut = zextent;
|
||||
actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, zextent));
|
||||
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
||||
|
||||
bool floor = false;
|
||||
for (CCollisionInfo& info : list)
|
||||
{
|
||||
if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft()))
|
||||
{
|
||||
floor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!floor)
|
||||
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGroundMovement::MoveGroundColliderZ(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
||||
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
float amt, float&, CCollisionInfoList& list, TUniqueId& idOut)
|
||||
{
|
||||
actor.MoveCollisionPrimitive({0.f, 0.f, amt});
|
||||
|
||||
zeus::CAABox aabb = zeus::CAABox::skInvertedBox;
|
||||
if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||
actor.GetPrimitiveTransform(), filter, nearList, idOut, list))
|
||||
{
|
||||
for (CCollisionInfo& info : list)
|
||||
{
|
||||
aabb.accumulateBounds(info.GetPoint());
|
||||
aabb.accumulateBounds(info.GetExtreme());
|
||||
}
|
||||
|
||||
zeus::CAABox actorAABB = actor.GetBoundingBox();
|
||||
float zextent;
|
||||
if (amt > 0.f)
|
||||
zextent = aabb.min.z - actorAABB.max.z - 0.02f + amt;
|
||||
else
|
||||
zextent = aabb.max.z - actorAABB.min.z + 0.02f + amt;
|
||||
|
||||
actor.MoveCollisionPrimitive({0.f, 0.f, zextent});
|
||||
|
||||
if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||
actor.GetPrimitiveTransform(), filter, nearList))
|
||||
{
|
||||
actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, zextent));
|
||||
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
||||
}
|
||||
|
||||
bool floor = false;
|
||||
for (CCollisionInfo& info : list)
|
||||
{
|
||||
if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft()))
|
||||
{
|
||||
floor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!floor)
|
||||
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor);
|
||||
|
||||
CCollisionInfoList filteredList;
|
||||
if (amt > 0.f)
|
||||
CollisionUtil::FilterByClosestNormal({0.f, 0.f, -1.f}, list, filteredList);
|
||||
else
|
||||
CollisionUtil::FilterByClosestNormal({0.f, 0.f, 1.f}, list, filteredList);
|
||||
|
||||
if (filteredList.GetCount() > 0)
|
||||
CGameCollision::MakeCollisionCallbacks(mgr, actor, idOut, filteredList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGroundMovement::MoveGroundColliderXY(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
||||
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
float dt)
|
||||
{
|
||||
bool didCollide = false;
|
||||
bool isPlayer = actor.GetMaterialList().HasMaterial(EMaterialTypes::Player);
|
||||
float remDt = dt;
|
||||
float originalDt = dt;
|
||||
TCastToPtr<CPhysicsActor> otherActor;
|
||||
CCollisionInfoList collisionList;
|
||||
CMotionState newMState = actor.PredictMotion_Internal(dt);
|
||||
float transMag = newMState.x0_translation.magnitude();
|
||||
float divMag;
|
||||
if (isPlayer)
|
||||
divMag = std::max(transMag / 5.f, 0.005f);
|
||||
else
|
||||
divMag = std::max(transMag / 3.f, 0.02f);
|
||||
|
||||
float minExtent = 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive());
|
||||
if (transMag > minExtent)
|
||||
{
|
||||
dt = minExtent * (dt / transMag);
|
||||
originalDt = dt;
|
||||
newMState = actor.PredictMotion_Internal(dt);
|
||||
divMag = std::min(divMag, minExtent);
|
||||
}
|
||||
|
||||
float nonCollideDt = dt;
|
||||
do
|
||||
{
|
||||
actor.MoveCollisionPrimitive(newMState.x0_translation);
|
||||
collisionList.Clear();
|
||||
TUniqueId otherId = kInvalidUniqueId;
|
||||
bool collided = CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||
actor.GetPrimitiveTransform(), filter, nearList,
|
||||
otherId, collisionList);
|
||||
if (collided)
|
||||
otherActor = mgr.ObjectById(otherId);
|
||||
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
||||
if (collided)
|
||||
{
|
||||
didCollide = true;
|
||||
if (newMState.x0_translation.magnitude() < divMag)
|
||||
{
|
||||
CCollisionInfoList backfaceFilteredList, floorFilteredList;
|
||||
zeus::CVector3f deltaVel = actor.GetVelocity();
|
||||
if (otherActor)
|
||||
deltaVel -= otherActor->GetVelocity();
|
||||
CollisionUtil::FilterOutBackfaces(deltaVel, collisionList, backfaceFilteredList);
|
||||
CAABoxFilter::FilterBoxFloorCollisions(backfaceFilteredList, floorFilteredList);
|
||||
CGameCollision::MakeCollisionCallbacks(mgr, actor, otherId, floorFilteredList);
|
||||
if (floorFilteredList.GetCount() == 0 && isPlayer)
|
||||
{
|
||||
CMotionState lastNonCollideState = actor.GetLastNonCollidingState();
|
||||
lastNonCollideState.x1c_velocity *= 0.5f;
|
||||
lastNonCollideState.x28_angularMomentum *= 0.5f;
|
||||
actor.SetMotionState(lastNonCollideState);
|
||||
}
|
||||
for (const CCollisionInfo& info : floorFilteredList)
|
||||
{
|
||||
CCollisionInfo infoCopy = info;
|
||||
float restitution = CGameCollision::GetCoefficientOfRestitution(infoCopy) +
|
||||
actor.GetCoefficientOfRestitutionModifier();
|
||||
if (otherActor)
|
||||
CGameCollision::CollideWithDynamicBodyNoRot(actor, *otherActor, infoCopy, restitution, true);
|
||||
else
|
||||
CGameCollision::CollideWithStaticBodyNoRot(actor, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(),
|
||||
infoCopy.GetNormalLeft(), restitution, true);
|
||||
}
|
||||
remDt -= dt;
|
||||
nonCollideDt = std::min(originalDt, remDt);
|
||||
dt = nonCollideDt;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonCollideDt *= 0.5f;
|
||||
dt *= 0.5f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
actor.AddMotionState(newMState);
|
||||
remDt -= dt;
|
||||
dt = nonCollideDt;
|
||||
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
||||
}
|
||||
|
||||
newMState = actor.PredictMotion_Internal(dt);
|
||||
} while (remDt > 0.f);
|
||||
|
||||
if (!didCollide && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider))
|
||||
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling);
|
||||
|
||||
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
||||
}
|
||||
|
||||
void CGroundMovement::CollisionDamping(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
float, float)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* nearList)
|
||||
{
|
||||
zeus::CAABox motionVol = actor.GetMotionVolume(dt);
|
||||
rstl::reserved_vector<TUniqueId, 1024> useNearList;
|
||||
if (nearList)
|
||||
useNearList = *nearList;
|
||||
else
|
||||
mgr.BuildColliderList(useNearList, actor, motionVol);
|
||||
|
||||
CAreaCollisionCache cache(motionVol);
|
||||
CGameCollision::BuildAreaCollisionCache(mgr, cache);
|
||||
CPlayer& player = static_cast<CPlayer&>(actor);
|
||||
player.x9c5_28_slidingOnWall = false;
|
||||
bool startingJump = player.x258_movementState == CPlayer::EPlayerMovementState::StartingJump;
|
||||
bool dampUnderwater = false;
|
||||
if (player.x9c4_31_dampUnderwaterMotion)
|
||||
{
|
||||
if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit))
|
||||
dampUnderwater = true;
|
||||
}
|
||||
|
||||
bool noJump = (player.x258_movementState != CPlayer::EPlayerMovementState::StartingJump &&
|
||||
player.x258_movementState != CPlayer::EPlayerMovementState::Jump);
|
||||
|
||||
float stepDown = player.GetStepDownHeight();
|
||||
float stepUp = player.GetStepUpHeight();
|
||||
|
||||
bool x108 = true;
|
||||
CMaterialList material(EMaterialTypes::Unknown);
|
||||
SMoveObjectResult result;
|
||||
|
||||
if (!startingJump)
|
||||
{
|
||||
SMovementOptions opts;
|
||||
opts.x0_ = false;
|
||||
opts.x4_ = 0.f;
|
||||
opts.x8_ = 0.f;
|
||||
opts.xc_ = 0.37f;
|
||||
opts.x10_ = 0.25f;
|
||||
opts.x14_ = 0.f;
|
||||
opts.x18_ = true;
|
||||
opts.x19_ = false;
|
||||
opts.x1a_ = noJump;
|
||||
opts.x1c_ = 4;
|
||||
opts.x20_ = 0.002f;
|
||||
opts.x24_ = 0.f;
|
||||
opts.x28_ = 1.f;
|
||||
opts.x2c_ = 0.f;
|
||||
opts.x30_ = 0.02f;
|
||||
opts.x3c_ = player.GetLastFloorPlaneNormal();
|
||||
opts.x34_ = 0.2f;
|
||||
opts.x38_ = player.GetMaximumPlayerPositiveVerticalVelocity(mgr);
|
||||
|
||||
if (noJump)
|
||||
{
|
||||
zeus::CVector3f vel = player.GetVelocity();
|
||||
vel.z = 0.f;
|
||||
actor.SetVelocityWR(vel);
|
||||
actor.x15c_force.z = 0.f;
|
||||
actor.x150_momentum.z = 0.f;
|
||||
actor.x168_impulse.z = 0.f;
|
||||
}
|
||||
|
||||
CPhysicsState physStatePre = actor.GetPhysicsState();
|
||||
CMaterialList material = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result);
|
||||
CPhysicsState physStatePost = actor.GetPhysicsState();
|
||||
|
||||
if (material.XOR({EMaterialTypes::Unknown}))
|
||||
{
|
||||
SMovementOptions optsCopy = opts;
|
||||
zeus::CVector3f postToPre = physStatePre.GetTranslation() - physStatePost.GetTranslation();
|
||||
float f27 = postToPre.magSquared();
|
||||
optsCopy.x19_ = noJump;
|
||||
float quarterStepUp = 0.25f * stepUp;
|
||||
rstl::reserved_vector<CPhysicsState, 2> physStateList;
|
||||
rstl::reserved_vector<float, 2> floatList;
|
||||
rstl::reserved_vector<CCollisionInfo, 2> collisionInfoList;
|
||||
rstl::reserved_vector<TUniqueId, 2> uniqueIdList;
|
||||
rstl::reserved_vector<CMaterialList, 2> materialListList;
|
||||
bool done = false;
|
||||
for (int i=0 ; i < 2 && !done ; ++i)
|
||||
{
|
||||
double useStepUp = (i == 0) ? quarterStepUp : stepUp;
|
||||
actor.SetPhysicsState(physStatePre);
|
||||
CCollisionInfo collisionInfo;
|
||||
TUniqueId id = kInvalidUniqueId;
|
||||
CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||
actor.GetTransform(), actor.GetMaterialFilter(),
|
||||
useNearList, {0.f, 0.f, 1.f}, id, collisionInfo,
|
||||
useStepUp);
|
||||
if (collisionInfo.IsValid())
|
||||
{
|
||||
useStepUp = std::max(0.0, useStepUp - optsCopy.x20_);
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (useStepUp > 0.0005)
|
||||
{
|
||||
actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, useStepUp));
|
||||
|
||||
SMoveObjectResult result;
|
||||
CMaterialList material = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, optsCopy, result);
|
||||
CCollisionInfo collisionInfo;
|
||||
double useStepDown = useStepUp + stepDown;
|
||||
TUniqueId id = kInvalidUniqueId;
|
||||
if (useStepDown > 0.0)
|
||||
{
|
||||
CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||
actor.GetTransform(), actor.GetMaterialFilter(),
|
||||
useNearList, {0.f, 0.f, -1.f}, id, collisionInfo,
|
||||
useStepDown);
|
||||
}
|
||||
else
|
||||
{
|
||||
useStepDown = 0.0;
|
||||
}
|
||||
|
||||
float minStep = std::min(useStepUp, useStepDown);
|
||||
zeus::CVector3f offsetStep = actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, minStep);
|
||||
bool canBlock = (collisionInfo.IsValid() &&
|
||||
CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionInfo.GetNormalLeft()));
|
||||
zeus::CVector3f postToPre = physStatePre.GetTranslation() - offsetStep;
|
||||
float f26 = postToPre.magSquared();
|
||||
if (canBlock && f27 < f26)
|
||||
{
|
||||
useStepDown = std::max(0.0, useStepDown - 0.0005);
|
||||
actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, useStepDown));
|
||||
physStateList.push_back(actor.GetPhysicsState());
|
||||
floatList.push_back(f26);
|
||||
collisionInfoList.push_back(collisionInfo);
|
||||
uniqueIdList.push_back(id);
|
||||
materialListList.push_back(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (physStateList.size() == 0)
|
||||
{
|
||||
actor.SetPhysicsState(physStatePost);
|
||||
}
|
||||
else
|
||||
{
|
||||
float maxFloat = -1.0e10f;
|
||||
int maxIdx = -1;
|
||||
for (int i=0 ; i<physStateList.size() ; ++i)
|
||||
{
|
||||
if (maxFloat < floatList[i])
|
||||
{
|
||||
maxFloat = floatList[i];
|
||||
maxIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
actor.SetPhysicsState(physStateList[maxIdx]);
|
||||
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor);
|
||||
if (CEntity* ent = mgr.ObjectById(uniqueIdList[maxIdx]))
|
||||
{
|
||||
result.x0_id.emplace(uniqueIdList[maxIdx]);
|
||||
result.x8_collision.emplace(collisionInfoList[maxIdx]);
|
||||
if (TCastToPtr<CScriptPlatform> plat = ent)
|
||||
mgr.SendScriptMsg(ent, actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider);
|
||||
}
|
||||
|
||||
CCollisionInfo& cInfo = collisionInfoList[maxIdx];
|
||||
CGameCollision::SendMaterialMessage(mgr, cInfo.GetMaterialLeft(), actor);
|
||||
x108 = false;
|
||||
actor.SetLastFloorPlaneNormal({cInfo.GetNormalLeft()});
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SMovementOptions opts;
|
||||
opts.x0_ = true;
|
||||
opts.x4_ = dampUnderwater ? 35.f : 1.f;
|
||||
opts.x8_ = dampUnderwater ? 5.f : 0.f;
|
||||
opts.xc_ = dampUnderwater ? 0.05f : 0.37f;
|
||||
opts.x10_ = dampUnderwater ? 0.01f : 0.25f;
|
||||
opts.x14_ = dampUnderwater ? 0.2f : 0.f;
|
||||
opts.x18_ = false;
|
||||
opts.x19_ = false;
|
||||
opts.x1a_ = false;
|
||||
opts.x1c_ = 4;
|
||||
opts.x20_ = 0.002f;
|
||||
opts.x24_ = 0.f;
|
||||
opts.x28_ = 1.f;
|
||||
opts.x2c_ = 0.1f;
|
||||
opts.x30_ = dampUnderwater ? 0.2f : 0.2f;
|
||||
opts.x3c_ = player.GetLastFloorPlaneNormal();
|
||||
opts.x38_ = player.GetMaximumPlayerPositiveVerticalVelocity(mgr);
|
||||
|
||||
material = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result);
|
||||
}
|
||||
|
||||
if (x108)
|
||||
{
|
||||
// TODO: Finish
|
||||
}
|
||||
|
||||
actor.ClearForcesAndTorques();
|
||||
if (material.HasMaterial(EMaterialTypes::Wall))
|
||||
player.SetPlayerHitWallDuringMove();
|
||||
|
||||
if (result.x0_id)
|
||||
{
|
||||
CCollisionInfoList list;
|
||||
list.Add(*result.x8_collision, false);
|
||||
CGameCollision::MakeCollisionCallbacks(mgr, actor, *result.x0_id, list);
|
||||
}
|
||||
|
||||
CMotionState mState = actor.GetMotionState();
|
||||
mState.x0_translation = actor.GetLastNonCollidingState().x0_translation;
|
||||
mState.x1c_velocity = actor.GetLastNonCollidingState().x1c_velocity;
|
||||
actor.SetLastNonCollidingState(mState);
|
||||
|
||||
const CCollisionPrimitive* prim = actor.GetCollisionPrimitive();
|
||||
if (prim->GetPrimType() == FOURCC('AABX'))
|
||||
{
|
||||
// TODO: Finish
|
||||
}
|
||||
else if (prim->GetPrimType() == FOURCC('SPHR'))
|
||||
{
|
||||
// TODO: Finish
|
||||
}
|
||||
|
||||
CGameCollision::CollisionFailsafe(mgr, cache, actor, *prim, useNearList, 0.f, 1);
|
||||
}
|
||||
|
||||
void CGroundMovement::RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&, float&)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CGroundMovement::RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float,
|
||||
rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
CAreaCollisionCache& cache, const SMovementOptions& opts,
|
||||
SMoveObjectResult& result)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef __URDE_CGROUNDMOVEMENT_HPP__
|
||||
#define __URDE_CGROUNDMOVEMENT_HPP__
|
||||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "Collision/CCollisionInfo.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
class CPhysicsActor;
|
||||
class CStateManager;
|
||||
class CAreaCollisionCache;
|
||||
class CMaterialFilter;
|
||||
class CCollisionInfoList;
|
||||
|
||||
class CGroundMovement
|
||||
{
|
||||
public:
|
||||
struct SMovementOptions
|
||||
{
|
||||
bool x0_;
|
||||
float x4_;
|
||||
float x8_;
|
||||
float xc_;
|
||||
float x10_;
|
||||
float x14_;
|
||||
bool x18_;
|
||||
bool x19_;
|
||||
bool x1a_;
|
||||
u32 x1c_;
|
||||
float x20_;
|
||||
float x24_;
|
||||
float x28_;
|
||||
float x2c_;
|
||||
float x30_;
|
||||
float x34_;
|
||||
float x38_;
|
||||
std::experimental::optional<zeus::CVector3f> x3c_;
|
||||
};
|
||||
|
||||
struct SMoveObjectResult
|
||||
{
|
||||
std::experimental::optional<TUniqueId> x0_id;
|
||||
std::experimental::optional<CCollisionInfo> x8_collision;
|
||||
u32 x6c_;
|
||||
float x70_;
|
||||
};
|
||||
|
||||
static void CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float);
|
||||
static void MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* nearList);
|
||||
static bool ResolveUpDown(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
||||
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
float, float, float&, CCollisionInfoList& list);
|
||||
static bool MoveGroundColliderZ(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
||||
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
float, float&, CCollisionInfoList& list, TUniqueId& idOut);
|
||||
static void MoveGroundColliderXY(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
||||
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
float);
|
||||
static void CollisionDamping(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
float, float);
|
||||
static void MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* nearList);
|
||||
static void RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&, float&);
|
||||
static void RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&);
|
||||
static CMaterialList MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float,
|
||||
rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
CAreaCollisionCache& cache, const SMovementOptions& opts,
|
||||
SMoveObjectResult& result);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __URDE_CGROUNDMOVEMENT_HPP__
|
|
@ -88,6 +88,7 @@ set(CHARACTER_SOURCES
|
|||
CAnimSysContext.hpp
|
||||
CBodyState.hpp CBodyState.cpp
|
||||
CBodyStateCmdMgr.hpp CBodyStateCmdMgr.cpp
|
||||
CBodyController.hpp CBodyController.cpp)
|
||||
CBodyController.hpp CBodyController.cpp
|
||||
CGroundMovement.hpp CGroundMovement.cpp)
|
||||
|
||||
runtime_add_list(Character CHARACTER_SOURCES)
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
x0_list.push_back(info.GetSwapped());
|
||||
}
|
||||
void Clear() { x0_list.clear(); }
|
||||
const CCollisionInfo& Front() const { return x0_list.front(); }
|
||||
const CCollisionInfo& GetItem(int i) const { return x0_list[i]; }
|
||||
rstl::reserved_vector<CCollisionInfo, 32>::iterator end() { return x0_list.end(); }
|
||||
rstl::reserved_vector<CCollisionInfo, 32>::const_iterator end() const { return x0_list.end(); }
|
||||
rstl::reserved_vector<CCollisionInfo, 32>::iterator begin() { return x0_list.begin(); }
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "CollisionUtil.hpp"
|
||||
#include "World/CScriptPlatform.hpp"
|
||||
#include "CCollidableSphere.hpp"
|
||||
#include "Character/CGroundMovement.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -21,9 +22,9 @@ static float CollisionImpulseFiniteVsInfinite(float mass, float velNormDot, floa
|
|||
return mass * ((1.f / restitution) * velNormDot);
|
||||
}
|
||||
|
||||
static float CollisionImpulseFiniteVsFinite(float mass, float velNormDot, float restitution, float f4)
|
||||
static float CollisionImpulseFiniteVsFinite(float mass0, float mass1, float velNormDot, float restitution)
|
||||
{
|
||||
return (-(1.f + f4) * restitution) / ((1.f / mass) + (1.f / velNormDot));
|
||||
return (-(1.f + restitution) * velNormDot) / ((1.f / mass0) + (1.f / mass1));
|
||||
}
|
||||
|
||||
void CGameCollision::InitCollision()
|
||||
|
@ -68,36 +69,13 @@ void CGameCollision::MovePlayer(CStateManager& mgr, CPhysicsActor& actor, float
|
|||
else
|
||||
{
|
||||
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider))
|
||||
MoveGroundCollider_New(mgr, actor, dt, colliderList);
|
||||
CGroundMovement::MoveGroundCollider_New(mgr, actor, dt, colliderList);
|
||||
else
|
||||
MoveAndCollide(mgr, actor, dt, CBallFilter(actor), colliderList);
|
||||
}
|
||||
actor.SetAngularEnabled(false);
|
||||
}
|
||||
|
||||
void CGameCollision::MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
|
||||
{
|
||||
CMotionState oldState = actor.GetMotionState();
|
||||
CMotionState newState = actor.PredictMotion_Internal(dt);
|
||||
newState.x0_translation.magnitude();
|
||||
actor.GetMaterialFilter();
|
||||
zeus::CAABox motionVol = actor.GetMotionVolume(dt);
|
||||
rstl::reserved_vector<TUniqueId, 1024> augmentedColliderList;
|
||||
if (colliderList)
|
||||
augmentedColliderList = *colliderList;
|
||||
mgr.BuildColliderList(augmentedColliderList, actor, motionVol);
|
||||
CAreaCollisionCache cache(motionVol);
|
||||
actor.GetCollisionPrimitive()->GetPrimType();
|
||||
// TODO: finish
|
||||
}
|
||||
|
||||
void CGameCollision::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
|
||||
{
|
||||
// TODO: finish
|
||||
}
|
||||
|
||||
void CGameCollision::MoveAndCollide(CStateManager& mgr, CPhysicsActor& actor, float dt, const ICollisionFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
|
||||
{
|
||||
|
@ -246,7 +224,7 @@ void CGameCollision::Move(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
|||
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Player))
|
||||
MovePlayer(mgr, actor, dt, colliderList);
|
||||
else if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider))
|
||||
MoveGroundCollider(mgr, actor, dt, colliderList);
|
||||
CGroundMovement::MoveGroundCollider(mgr, actor, dt, colliderList);
|
||||
else
|
||||
MoveAndCollide(mgr, actor, dt, CAABoxFilter(actor), colliderList);
|
||||
}
|
||||
|
@ -587,6 +565,17 @@ bool CGameCollision::DetectCollision_Cached(CStateManager& mgr, CAreaCollisionCa
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool CGameCollision::DetectCollision_Cached_Moving(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const zeus::CVector3f& vec,
|
||||
TUniqueId& idOut, CCollisionInfo& infoOut, double&)
|
||||
{
|
||||
// TODO: Finish
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CGameCollision::DetectStaticCollision(CStateManager& mgr, const CCollisionPrimitive& prim,
|
||||
const zeus::CTransform& xf, const CMaterialFilter& filter,
|
||||
CCollisionInfoList& list)
|
||||
|
@ -777,16 +766,80 @@ void CGameCollision::ResolveCollisions(CPhysicsActor& a0, CPhysicsActor* a1, con
|
|||
}
|
||||
|
||||
void CGameCollision::CollideWithDynamicBodyNoRot(CPhysicsActor& a0, CPhysicsActor& a1,
|
||||
const CCollisionInfo& info, float restitution, bool)
|
||||
const CCollisionInfo& info, float restitution, bool zeroZ)
|
||||
{
|
||||
/* TODO: Finish */
|
||||
zeus::CVector3f normal = info.GetNormalLeft();
|
||||
if (zeroZ)
|
||||
normal.z = 0.f;
|
||||
|
||||
zeus::CVector3f relVel = GetActorRelativeVelocities(a0, &a1);
|
||||
float velNormDot = relVel.dot(normal);
|
||||
|
||||
float a0MaxCollisionVel = std::max(a0.GetVelocity().magnitude(), a0.GetMaximumCollisionVelocity());
|
||||
float a1MaxCollisionVel = std::max(a1.GetVelocity().magnitude(), a1.GetMaximumCollisionVelocity());
|
||||
|
||||
bool a0Move = !a0.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && a0.GetMass() != 0.f;
|
||||
bool a1Move = !a1.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && a1.GetMass() != 0.f;
|
||||
|
||||
if (velNormDot < -0.0001f)
|
||||
{
|
||||
if (a0Move)
|
||||
{
|
||||
if (a1Move)
|
||||
{
|
||||
float impulse = CollisionImpulseFiniteVsFinite(a0.GetMass(), a1.GetMass(), velNormDot, restitution);
|
||||
a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity);
|
||||
a1.ApplyImpulseWR(normal * -impulse, zeus::CAxisAngle::sIdentity);
|
||||
}
|
||||
else
|
||||
{
|
||||
float impulse = CollisionImpulseFiniteVsInfinite(a0.GetMass(), velNormDot, restitution);
|
||||
a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a1Move)
|
||||
{
|
||||
float impulse = CollisionImpulseFiniteVsInfinite(a1.GetMass(), velNormDot, restitution);
|
||||
a1.ApplyImpulseWR(normal * -impulse, zeus::CAxisAngle::sIdentity);
|
||||
}
|
||||
else
|
||||
{
|
||||
a0.SetVelocityWR(zeus::CVector3f::skZero);
|
||||
a1.SetVelocityWR(zeus::CVector3f::skZero);
|
||||
}
|
||||
}
|
||||
a0.UseCollisionImpulses();
|
||||
a1.UseCollisionImpulses();
|
||||
}
|
||||
else if (velNormDot < 0.1f)
|
||||
{
|
||||
if (a0Move)
|
||||
{
|
||||
float impulse = 0.05f * a0.GetMass();
|
||||
a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity);
|
||||
a0.UseCollisionImpulses();
|
||||
}
|
||||
if (a1Move)
|
||||
{
|
||||
float impulse = -0.05f * a1.GetMass();
|
||||
a1.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity);
|
||||
a1.UseCollisionImpulses();
|
||||
}
|
||||
}
|
||||
|
||||
if (a0.GetVelocity().magnitude() > a0MaxCollisionVel)
|
||||
a0.SetVelocityWR(a0.GetVelocity().normalized() * a0MaxCollisionVel);
|
||||
if (a1.GetVelocity().magnitude() > a1MaxCollisionVel)
|
||||
a1.SetVelocityWR(a1.GetVelocity().normalized() * a1MaxCollisionVel);
|
||||
}
|
||||
|
||||
void CGameCollision::CollideWithStaticBodyNoRot(CPhysicsActor& a0, const CMaterialList& m0, const CMaterialList& m1,
|
||||
const zeus::CUnitVector3f& normal, float restitution, bool b)
|
||||
const zeus::CUnitVector3f& normal, float restitution, bool zeroZ)
|
||||
{
|
||||
zeus::CUnitVector3f useNorm = normal;
|
||||
if (b && m0.HasMaterial(EMaterialTypes::Player) && !m1.HasMaterial(EMaterialTypes::Floor))
|
||||
if (zeroZ && m0.HasMaterial(EMaterialTypes::Player) && !m1.HasMaterial(EMaterialTypes::Floor))
|
||||
useNorm.z = 0.f;
|
||||
|
||||
if (useNorm.canBeNormalized())
|
||||
|
@ -825,7 +878,37 @@ void CGameCollision::CollisionFailsafe(CStateManager& mgr, CAreaCollisionCache&
|
|||
actor.SetNumTicksStuck(actor.GetNumTicksStuck() + 1);
|
||||
if (actor.GetNumTicksStuck() < failsafeTicks)
|
||||
return;
|
||||
/* TODO: Finish */
|
||||
|
||||
CMotionState oldMState = actor.GetMotionState();
|
||||
CMotionState lastNonCollide = actor.GetLastNonCollidingState();
|
||||
actor.SetMotionState(lastNonCollide);
|
||||
if (!DetectCollisionBoolean_Cached(mgr, cache, prim, actor.GetPrimitiveTransform(),
|
||||
actor.GetMaterialFilter(), nearList))
|
||||
{
|
||||
lastNonCollide.x1c_velocity *= 0.5f;
|
||||
lastNonCollide.x28_angularMomentum *= 0.5f;
|
||||
actor.SetLastNonCollidingState(lastNonCollide);
|
||||
//++gDebugPrintCount;
|
||||
actor.SetNumTicksStuck(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
actor.SetMotionState(oldMState);
|
||||
if (auto nonIntersectVec = FindNonIntersectingVector(mgr, cache, actor, prim, nearList))
|
||||
{
|
||||
oldMState.x0_translation += *nonIntersectVec;
|
||||
actor.SetMotionState(oldMState);
|
||||
actor.SetLastNonCollidingState(actor.GetMotionState());
|
||||
//++gDebugPrintCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
//++gDebugPrintCount;
|
||||
lastNonCollide.x1c_velocity *= 0.5f;
|
||||
lastNonCollide.x28_angularMomentum *= 0.5f;
|
||||
actor.SetLastNonCollidingState(lastNonCollide);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -833,4 +916,117 @@ void CGameCollision::CollisionFailsafe(CStateManager& mgr, CAreaCollisionCache&
|
|||
actor.SetNumTicksStuck(0);
|
||||
}
|
||||
}
|
||||
|
||||
std::experimental::optional<zeus::CVector3f>
|
||||
CGameCollision::FindNonIntersectingVector(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||
CPhysicsActor& actor, const CCollisionPrimitive& prim,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList)
|
||||
{
|
||||
zeus::CTransform xf = actor.GetPrimitiveTransform();
|
||||
zeus::CVector3f center = prim.CalculateAABox(xf).center();
|
||||
for (int i=2 ; i<1000 ; i+=(i/2))
|
||||
{
|
||||
float pos = i * 0.005f;
|
||||
float neg = -pos;
|
||||
for (int j=0 ; j<26 ; ++j)
|
||||
{
|
||||
zeus::CVector3f vec;
|
||||
switch (j)
|
||||
{
|
||||
case 0:
|
||||
vec = {0.f, pos, 0.f};
|
||||
break;
|
||||
case 1:
|
||||
vec = {0.f, neg, 0.f};
|
||||
break;
|
||||
case 2:
|
||||
vec = {pos, 0.f, 0.f};
|
||||
break;
|
||||
case 3:
|
||||
vec = {neg, 0.f, 0.f};
|
||||
break;
|
||||
case 4:
|
||||
vec = {0.f, 0.f, pos};
|
||||
break;
|
||||
case 5:
|
||||
vec = {0.f, 0.f, neg};
|
||||
break;
|
||||
case 6:
|
||||
vec = {0.f, pos, pos};
|
||||
break;
|
||||
case 7:
|
||||
vec = {0.f, neg, neg};
|
||||
break;
|
||||
case 8:
|
||||
vec = {0.f, neg, pos};
|
||||
break;
|
||||
case 9:
|
||||
vec = {0.f, pos, neg};
|
||||
break;
|
||||
case 10:
|
||||
vec = {pos, 0.f, pos};
|
||||
break;
|
||||
case 11:
|
||||
vec = {neg, 0.f, neg};
|
||||
break;
|
||||
case 12:
|
||||
vec = {neg, 0.f, pos};
|
||||
break;
|
||||
case 13:
|
||||
vec = {pos, 0.f, neg};
|
||||
break;
|
||||
case 14:
|
||||
vec = {pos, pos, 0.f};
|
||||
break;
|
||||
case 15:
|
||||
vec = {neg, neg, 0.f};
|
||||
break;
|
||||
case 16:
|
||||
vec = {neg, pos, 0.f};
|
||||
break;
|
||||
case 17:
|
||||
vec = {pos, neg, 0.f};
|
||||
break;
|
||||
case 18:
|
||||
vec = {pos, pos, pos};
|
||||
break;
|
||||
case 19:
|
||||
vec = {neg, pos, pos};
|
||||
break;
|
||||
case 20:
|
||||
vec = {pos, neg, pos};
|
||||
break;
|
||||
case 21:
|
||||
vec = {neg, neg, pos};
|
||||
break;
|
||||
case 22:
|
||||
vec = {pos, pos, neg};
|
||||
break;
|
||||
case 23:
|
||||
vec = {neg, pos, neg};
|
||||
break;
|
||||
case 24:
|
||||
vec = {pos, neg, neg};
|
||||
break;
|
||||
case 25:
|
||||
vec = {neg, neg, neg};
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
zeus::CVector3f worldPoint = vec + xf.origin;
|
||||
if (mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId())->GetAABB().pointInside(worldPoint))
|
||||
{
|
||||
if (mgr.RayCollideWorld(center, center + vec, nearList,
|
||||
CMaterialFilter::skPassEverything, actor))
|
||||
{
|
||||
if (!DetectCollisionBoolean_Cached(mgr, cache, prim, xf, actor.GetMaterialFilter(), nearList))
|
||||
return {vec};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,6 @@ class CGameCollision
|
|||
{
|
||||
static void MovePlayer(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
|
||||
static void MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
|
||||
static void MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
|
||||
static void MoveAndCollide(CStateManager& mgr, CPhysicsActor& actor, float dt, const ICollisionFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
|
||||
static zeus::CVector3f GetActorRelativeVelocities(const CPhysicsActor& act0, const CPhysicsActor* act1);
|
||||
|
@ -84,6 +80,12 @@ public:
|
|||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
TUniqueId& idOut, CCollisionInfoList& infoList);
|
||||
static bool DetectCollision_Cached_Moving(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const zeus::CVector3f& vec,
|
||||
TUniqueId& idOut, CCollisionInfo& infoOut, double&);
|
||||
static bool DetectStaticCollision(CStateManager& mgr, const CCollisionPrimitive& prim,
|
||||
const zeus::CTransform& xf, const CMaterialFilter& filter,
|
||||
CCollisionInfoList& list);
|
||||
|
@ -105,6 +107,10 @@ public:
|
|||
CPhysicsActor& actor, const CCollisionPrimitive& prim,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
float, u32 failsafeTicks);
|
||||
static std::experimental::optional<zeus::CVector3f>
|
||||
FindNonIntersectingVector(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||
CPhysicsActor& actor, const CCollisionPrimitive& prim,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,11 @@ public:
|
|||
{
|
||||
return other.x0_list & x0_list;
|
||||
}
|
||||
|
||||
u64 XOR(const CMaterialList& other) const
|
||||
{
|
||||
return x0_list ^ other.x0_list;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -63,6 +63,26 @@ void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in
|
|||
}
|
||||
}
|
||||
|
||||
void FilterByClosestNormal(const zeus::CVector3f& norm, const CCollisionInfoList& in, CCollisionInfoList& out)
|
||||
{
|
||||
float maxDot = -1.1f;
|
||||
int idx = -1;
|
||||
int i=0;
|
||||
for (const CCollisionInfo& info : in)
|
||||
{
|
||||
float dot = info.GetNormalLeft().dot(norm);
|
||||
if (dot > maxDot)
|
||||
{
|
||||
maxDot = dot;
|
||||
idx = i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (idx != -1)
|
||||
out.Add(in.GetItem(i), false);
|
||||
}
|
||||
|
||||
static const zeus::CVector3f AABBNormalTable[] =
|
||||
{
|
||||
{-1.f, 0.f, 0.f},
|
||||
|
|
|
@ -16,6 +16,7 @@ u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f&, c
|
|||
bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir,
|
||||
float mag, float& T, zeus::CVector3f& point);
|
||||
void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out);
|
||||
void FilterByClosestNormal(const zeus::CVector3f& norm, const CCollisionInfoList& in, CCollisionInfoList& out);
|
||||
bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0,
|
||||
const zeus::CAABox& aabb1, const CMaterialList& list1,
|
||||
CCollisionInfoList& infoList);
|
||||
|
|
|
@ -114,6 +114,7 @@ class TCastToPtr : public IVisitor
|
|||
protected:
|
||||
T* ptr = nullptr;
|
||||
public:
|
||||
TCastToPtr() = default;
|
||||
TCastToPtr(CEntity* p);
|
||||
TCastToPtr(CEntity& p);
|
||||
|
||||
|
@ -134,6 +135,7 @@ template <class T>
|
|||
class TCastToConstPtr : TCastToPtr<T>
|
||||
{
|
||||
public:
|
||||
TCastToConstPtr() = default;
|
||||
TCastToConstPtr(const CEntity* p) : TCastToPtr<T>(const_cast<CEntity*>(p)) {}
|
||||
TCastToConstPtr(const CEntity& p) : TCastToPtr<T>(const_cast<CEntity&>(p)) {}
|
||||
const T* GetPtr() const { return TCastToPtr<T>::ptr; }
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
|
||||
class CPhysicsActor : public CActor
|
||||
{
|
||||
friend class CGroundMovement;
|
||||
protected:
|
||||
float xe8_mass;
|
||||
float xec_massRecip;
|
||||
|
@ -108,7 +109,7 @@ protected:
|
|||
CCollidableAABox x1c0_collisionPrimitive;
|
||||
zeus::CVector3f x1e8_primitiveOffset;
|
||||
CMotionState x1f4_lastNonCollidingState;
|
||||
bool x234_ = false;
|
||||
std::experimental::optional<zeus::CVector3f> x228_lastFloorPlaneNormal;
|
||||
float x238_maximumCollisionVelocity = 1000000.0f;
|
||||
float x23c_stepUpHeight;
|
||||
float x240_stepDownHeight;
|
||||
|
@ -138,7 +139,7 @@ public:
|
|||
zeus::CVector3f GetPrimitiveOffset();
|
||||
void MoveCollisionPrimitive(const zeus::CVector3f& offset);
|
||||
void SetBoundingBox(const zeus::CAABox& box);
|
||||
zeus::CAABox GetMotionVolume(float f31) const;
|
||||
zeus::CAABox GetMotionVolume(float dt) const;
|
||||
zeus::CVector3f CalculateNewVelocityWR_UsingImpulses() const;
|
||||
zeus::CAABox GetBoundingBox() const;
|
||||
const zeus::CAABox& GetBaseBoundingBox() const;
|
||||
|
@ -153,9 +154,12 @@ public:
|
|||
void SetMass(float mass);
|
||||
void SetAngularVelocityOR(const zeus::CAxisAngle& angVel);
|
||||
zeus::CAxisAngle GetAngularVelocityOR() const;
|
||||
const zeus::CAxisAngle& GetAngularVelocityWR() const { return x144_angularVelocity; }
|
||||
void SetAngularVelocityWR(const zeus::CAxisAngle& angVel);
|
||||
void SetVelocityWR(const zeus::CVector3f& vel);
|
||||
void SetVelocityOR(const zeus::CVector3f& vel);
|
||||
void SetMomentumWR(const zeus::CVector3f& m) { x150_momentum = m; }
|
||||
const zeus::CVector3f& GetMomentum() const { return x150_momentum; }
|
||||
const zeus::CVector3f& GetVelocity() const { return x138_velocity; }
|
||||
zeus::CVector3f GetTotalForcesWR() const;
|
||||
void RotateInOneFrameOR(const zeus::CQuaternion& q, float d);
|
||||
|
@ -186,6 +190,8 @@ public:
|
|||
void SetNumTicksPartialUpdate(u32 t) { x250_numTicksPartialUpdate = t; }
|
||||
u32 GetNumTicksStuck() const { return x24c_numTicksStuck; }
|
||||
void SetNumTicksStuck(u32 t) { x24c_numTicksStuck = t; }
|
||||
const std::experimental::optional<zeus::CVector3f>& GetLastFloorPlaneNormal() const { return x228_lastFloorPlaneNormal; }
|
||||
void SetLastFloorPlaneNormal(const std::experimental::optional<zeus::CVector3f>& n) { x228_lastFloorPlaneNormal = n; }
|
||||
|
||||
CMotionState PredictMotion_Internal(float) const;
|
||||
CMotionState PredictMotion(float dt) const;
|
||||
|
|
|
@ -947,6 +947,12 @@ bool CPlayer::ObjectInScanningRange(TUniqueId id, const CStateManager& mgr) cons
|
|||
return false;
|
||||
}
|
||||
|
||||
void CPlayer::SetPlayerHitWallDuringMove()
|
||||
{
|
||||
x9c5_29_hitWall = true;
|
||||
x2d0_ = 1;
|
||||
}
|
||||
|
||||
void CPlayer::Touch() {}
|
||||
|
||||
void CPlayer::CVisorSteam::SetSteam(float a, float b, float c, ResId d, bool e)
|
||||
|
|
|
@ -27,6 +27,7 @@ class CPlayer : public CPhysicsActor
|
|||
friend class CFirstPersonCamera;
|
||||
friend class CPlayerCameraBob;
|
||||
friend class CMorphBall;
|
||||
friend class CGroundMovement;
|
||||
|
||||
public:
|
||||
enum class EPlayerScanState
|
||||
|
@ -318,13 +319,13 @@ private:
|
|||
bool x9c4_28_ : 1;
|
||||
bool x9c4_29_ : 1;
|
||||
bool x9c4_30_ : 1;
|
||||
bool x9c4_31_ : 1;
|
||||
bool x9c4_31_dampUnderwaterMotion : 1;
|
||||
bool x9c5_24_ : 1;
|
||||
bool x9c5_25_splashUpdated : 1;
|
||||
bool x9c5_26_ : 1;
|
||||
bool x9c5_27_ : 1;
|
||||
bool x9c5_28_ : 1;
|
||||
bool x9c5_29_ : 1;
|
||||
bool x9c5_28_slidingOnWall : 1;
|
||||
bool x9c5_29_hitWall : 1;
|
||||
bool x9c5_30_ : 1;
|
||||
bool x9c5_31_ : 1;
|
||||
bool x9c6_24_ : 1;
|
||||
|
@ -543,6 +544,7 @@ public:
|
|||
const std::vector<TUniqueId>& GetNearbyOrbitObjects() const { return x344_nearbyOrbitObjects; }
|
||||
const std::vector<TUniqueId>& GetOnScreenOrbitObjects() const { return x354_onScreenOrbitObjects; }
|
||||
const std::vector<TUniqueId>& GetOffScreenOrbitObjects() const { return x364_offScreenOrbitObjects; }
|
||||
void SetPlayerHitWallDuringMove();
|
||||
|
||||
void Touch();
|
||||
|
||||
|
|
Loading…
Reference in New Issue