mirror of https://github.com/AxioDL/metaforce.git
Finish CGroundMovement
This commit is contained in:
parent
d4a97861dc
commit
59771cf630
|
@ -363,10 +363,12 @@ void CGroundMovement::MoveGroundColliderXY(CAreaCollisionCache& cache, CStateMan
|
||||||
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGroundMovement::CollisionDamping(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&,
|
zeus::CVector3f CGroundMovement::CollisionDamping(const zeus::CVector3f& vel, const zeus::CVector3f& dir,
|
||||||
float, float)
|
const zeus::CVector3f& cNorm, float normCoeff, float deltaCoeff)
|
||||||
{
|
{
|
||||||
|
zeus::CVector3f dampedDir = (cNorm * -2.f * cNorm.dot(dir) + dir).normalized();
|
||||||
|
zeus::CVector3f dampedNorm = cNorm * cNorm.dot(dampedDir);
|
||||||
|
return (dampedDir - dampedNorm) * vel.magnitude() * deltaCoeff + normCoeff * vel.magnitude() * dampedNorm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||||
|
@ -386,10 +388,8 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
bool startingJump = player.x258_movementState == CPlayer::EPlayerMovementState::StartingJump;
|
bool startingJump = player.x258_movementState == CPlayer::EPlayerMovementState::StartingJump;
|
||||||
bool dampUnderwater = false;
|
bool dampUnderwater = false;
|
||||||
if (player.x9c4_31_dampUnderwaterMotion)
|
if (player.x9c4_31_dampUnderwaterMotion)
|
||||||
{
|
|
||||||
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::StartingJump &&
|
bool noJump = (player.x258_movementState != CPlayer::EPlayerMovementState::StartingJump &&
|
||||||
player.x258_movementState != CPlayer::EPlayerMovementState::Jump);
|
player.x258_movementState != CPlayer::EPlayerMovementState::Jump);
|
||||||
|
@ -397,31 +397,31 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
float stepDown = player.GetStepDownHeight();
|
float stepDown = player.GetStepDownHeight();
|
||||||
float stepUp = player.GetStepUpHeight();
|
float stepUp = player.GetStepUpHeight();
|
||||||
|
|
||||||
bool x108 = true;
|
bool doStepDown = true;
|
||||||
CMaterialList material(EMaterialTypes::Unknown);
|
CMaterialList material(EMaterialTypes::Unknown);
|
||||||
SMoveObjectResult result;
|
SMoveObjectResult result;
|
||||||
|
|
||||||
if (!startingJump)
|
if (!startingJump)
|
||||||
{
|
{
|
||||||
SMovementOptions opts;
|
SMovementOptions opts;
|
||||||
opts.x0_ = false;
|
opts.x0_setWaterLandingForce = false;
|
||||||
opts.x4_ = 0.f;
|
opts.x4_waterLandingForceCoefficient = 0.f;
|
||||||
opts.x8_ = 0.f;
|
opts.x8_minimumWaterLandingForce = 0.f;
|
||||||
opts.xc_ = 0.37f;
|
opts.xc_anyZThreshold = 0.37f;
|
||||||
opts.x10_ = 0.25f;
|
opts.x10_downwardZThreshold = 0.25f;
|
||||||
opts.x14_ = 0.f;
|
opts.x14_waterLandingVelocityReduction = 0.f;
|
||||||
opts.x18_ = true;
|
opts.x18_dampForceAndMomentum = true;
|
||||||
opts.x19_ = false;
|
opts.x19_alwaysClip = false;
|
||||||
opts.x1a_ = noJump;
|
opts.x1a_disableClipForFloorOnly = noJump;
|
||||||
opts.x1c_ = 4;
|
opts.x1c_maxCollisionCycles = 4;
|
||||||
opts.x20_ = 0.002f;
|
opts.x20_minimumTranslationDelta = 0.002f;
|
||||||
opts.x24_ = 0.f;
|
opts.x24_dampedNormalCoefficient = 0.f;
|
||||||
opts.x28_ = 1.f;
|
opts.x28_dampedDeltaCoefficient = 1.f;
|
||||||
opts.x2c_ = 0.f;
|
opts.x2c_floorElasticForce = 0.f;
|
||||||
opts.x30_ = 0.02f;
|
opts.x30_wallElasticConstant = 0.02f;
|
||||||
opts.x3c_ = player.GetLastFloorPlaneNormal();
|
opts.x3c_floorPlaneNormal = player.GetLastFloorPlaneNormal();
|
||||||
opts.x34_ = 0.2f;
|
opts.x34_wallElasticLinear = 0.2f;
|
||||||
opts.x38_ = player.GetMaximumPlayerPositiveVerticalVelocity(mgr);
|
opts.x38_maxPositiveVerticalVelocity = player.GetMaximumPlayerPositiveVerticalVelocity(mgr);
|
||||||
|
|
||||||
if (noJump)
|
if (noJump)
|
||||||
{
|
{
|
||||||
|
@ -441,11 +441,11 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
{
|
{
|
||||||
SMovementOptions optsCopy = opts;
|
SMovementOptions optsCopy = opts;
|
||||||
zeus::CVector3f postToPre = physStatePre.GetTranslation() - physStatePost.GetTranslation();
|
zeus::CVector3f postToPre = physStatePre.GetTranslation() - physStatePost.GetTranslation();
|
||||||
float f27 = postToPre.magSquared();
|
float postToPreMag = postToPre.magSquared();
|
||||||
optsCopy.x19_ = noJump;
|
optsCopy.x19_alwaysClip = noJump;
|
||||||
float quarterStepUp = 0.25f * stepUp;
|
float quarterStepUp = 0.25f * stepUp;
|
||||||
rstl::reserved_vector<CPhysicsState, 2> physStateList;
|
rstl::reserved_vector<CPhysicsState, 2> physStateList;
|
||||||
rstl::reserved_vector<float, 2> floatList;
|
rstl::reserved_vector<float, 2> stepDeltaList;
|
||||||
rstl::reserved_vector<CCollisionInfo, 2> collisionInfoList;
|
rstl::reserved_vector<CCollisionInfo, 2> collisionInfoList;
|
||||||
rstl::reserved_vector<TUniqueId, 2> uniqueIdList;
|
rstl::reserved_vector<TUniqueId, 2> uniqueIdList;
|
||||||
rstl::reserved_vector<CMaterialList, 2> materialListList;
|
rstl::reserved_vector<CMaterialList, 2> materialListList;
|
||||||
|
@ -462,7 +462,7 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
useStepUp);
|
useStepUp);
|
||||||
if (collisionInfo.IsValid())
|
if (collisionInfo.IsValid())
|
||||||
{
|
{
|
||||||
useStepUp = std::max(0.0, useStepUp - optsCopy.x20_);
|
useStepUp = std::max(0.0, useStepUp - optsCopy.x20_minimumTranslationDelta);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,16 +489,16 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
|
|
||||||
float minStep = std::min(useStepUp, useStepDown);
|
float minStep = std::min(useStepUp, useStepDown);
|
||||||
zeus::CVector3f offsetStep = actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, minStep);
|
zeus::CVector3f offsetStep = actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, minStep);
|
||||||
bool canBlock = (collisionInfo.IsValid() &&
|
bool floor = (collisionInfo.IsValid() &&
|
||||||
CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionInfo.GetNormalLeft()));
|
CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionInfo.GetNormalLeft()));
|
||||||
zeus::CVector3f postToPre = physStatePre.GetTranslation() - offsetStep;
|
zeus::CVector3f postToPre = physStatePre.GetTranslation() - offsetStep;
|
||||||
float f26 = postToPre.magSquared();
|
float stepDelta = postToPre.magSquared();
|
||||||
if (canBlock && f27 < f26)
|
if (floor && postToPreMag < stepDelta)
|
||||||
{
|
{
|
||||||
useStepDown = std::max(0.0, useStepDown - 0.0005);
|
useStepDown = std::max(0.0, useStepDown - 0.0005);
|
||||||
actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, useStepDown));
|
actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, useStepDown));
|
||||||
physStateList.push_back(actor.GetPhysicsState());
|
physStateList.push_back(actor.GetPhysicsState());
|
||||||
floatList.push_back(f26);
|
stepDeltaList.push_back(stepDelta);
|
||||||
collisionInfoList.push_back(collisionInfo);
|
collisionInfoList.push_back(collisionInfo);
|
||||||
uniqueIdList.push_back(id);
|
uniqueIdList.push_back(id);
|
||||||
materialListList.push_back(material);
|
materialListList.push_back(material);
|
||||||
|
@ -516,9 +516,9 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
int maxIdx = -1;
|
int maxIdx = -1;
|
||||||
for (int i=0 ; i<physStateList.size() ; ++i)
|
for (int i=0 ; i<physStateList.size() ; ++i)
|
||||||
{
|
{
|
||||||
if (maxFloat < floatList[i])
|
if (maxFloat < stepDeltaList[i])
|
||||||
{
|
{
|
||||||
maxFloat = floatList[i];
|
maxFloat = stepDeltaList[i];
|
||||||
maxIdx = i;
|
maxIdx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -529,13 +529,13 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
{
|
{
|
||||||
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> plat = 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];
|
||||||
CGameCollision::SendMaterialMessage(mgr, cInfo.GetMaterialLeft(), actor);
|
CGameCollision::SendMaterialMessage(mgr, cInfo.GetMaterialLeft(), actor);
|
||||||
x108 = false;
|
doStepDown = false;
|
||||||
actor.SetLastFloorPlaneNormal({cInfo.GetNormalLeft()});
|
actor.SetLastFloorPlaneNormal({cInfo.GetNormalLeft()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,30 +543,81 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SMovementOptions opts;
|
SMovementOptions opts;
|
||||||
opts.x0_ = true;
|
opts.x0_setWaterLandingForce = true;
|
||||||
opts.x4_ = dampUnderwater ? 35.f : 1.f;
|
opts.x4_waterLandingForceCoefficient = dampUnderwater ? 35.f : 1.f;
|
||||||
opts.x8_ = dampUnderwater ? 5.f : 0.f;
|
opts.x8_minimumWaterLandingForce = dampUnderwater ? 5.f : 0.f;
|
||||||
opts.xc_ = dampUnderwater ? 0.05f : 0.37f;
|
opts.xc_anyZThreshold = dampUnderwater ? 0.05f : 0.37f;
|
||||||
opts.x10_ = dampUnderwater ? 0.01f : 0.25f;
|
opts.x10_downwardZThreshold = dampUnderwater ? 0.01f : 0.25f;
|
||||||
opts.x14_ = dampUnderwater ? 0.2f : 0.f;
|
opts.x14_waterLandingVelocityReduction = dampUnderwater ? 0.2f : 0.f;
|
||||||
opts.x18_ = false;
|
opts.x18_dampForceAndMomentum = false;
|
||||||
opts.x19_ = false;
|
opts.x19_alwaysClip = false;
|
||||||
opts.x1a_ = false;
|
opts.x1a_disableClipForFloorOnly = false;
|
||||||
opts.x1c_ = 4;
|
opts.x1c_maxCollisionCycles = 4;
|
||||||
opts.x20_ = 0.002f;
|
opts.x20_minimumTranslationDelta = 0.002f;
|
||||||
opts.x24_ = 0.f;
|
opts.x24_dampedNormalCoefficient = 0.f;
|
||||||
opts.x28_ = 1.f;
|
opts.x28_dampedDeltaCoefficient = 1.f;
|
||||||
opts.x2c_ = 0.1f;
|
opts.x2c_floorElasticForce = 0.1f;
|
||||||
opts.x30_ = dampUnderwater ? 0.2f : 0.2f;
|
opts.x30_wallElasticConstant = dampUnderwater ? 0.2f : 0.2f;
|
||||||
opts.x3c_ = player.GetLastFloorPlaneNormal();
|
opts.x3c_floorPlaneNormal = player.GetLastFloorPlaneNormal();
|
||||||
opts.x38_ = player.GetMaximumPlayerPositiveVerticalVelocity(mgr);
|
opts.x38_maxPositiveVerticalVelocity = player.GetMaximumPlayerPositiveVerticalVelocity(mgr);
|
||||||
|
|
||||||
material = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result);
|
material = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x108)
|
if (doStepDown)
|
||||||
{
|
{
|
||||||
// TODO: Finish
|
CCollisionInfo collisionInfo;
|
||||||
|
double stepDown = actor.GetStepDownHeight();
|
||||||
|
float zOffset = 0.f;
|
||||||
|
TUniqueId id = kInvalidUniqueId;
|
||||||
|
if (stepDown > FLT_EPSILON)
|
||||||
|
{
|
||||||
|
zeus::CTransform xf = actor.GetTransform();
|
||||||
|
xf.origin += zeus::CVector3f(0.f, 0.f, 0.0005f);
|
||||||
|
if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||||
|
xf, actor.GetMaterialFilter(), useNearList))
|
||||||
|
{
|
||||||
|
actor.SetTranslation(xf.origin);
|
||||||
|
zOffset = 0.0005f;
|
||||||
|
stepDown += 0.0005;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||||
|
actor.GetTransform(), actor.GetMaterialFilter(),
|
||||||
|
useNearList, {0.f, 0.f, -1.f}, id, collisionInfo,
|
||||||
|
stepDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id != kInvalidUniqueId)
|
||||||
|
{
|
||||||
|
result.x0_id.emplace(id);
|
||||||
|
result.x8_collision.emplace(collisionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.x8_collision->IsValid() ||
|
||||||
|
!CGameCollision::CanBlock(result.x8_collision->GetMaterialLeft(), result.x8_collision->GetNormalLeft()))
|
||||||
|
{
|
||||||
|
if (zOffset > 0.f)
|
||||||
|
{
|
||||||
|
zeus::CTransform xf = actor.GetTransform();
|
||||||
|
xf.origin -= zeus::CVector3f(0.f, 0.f, zOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.x8_collision->IsValid())
|
||||||
|
player.x9c5_28_slidingOnWall = true;
|
||||||
|
CheckFalling(actor, mgr, dt);
|
||||||
|
player.SetLastFloorPlaneNormal({});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor);
|
||||||
|
stepDown = std::max(0.0, stepDown - 0.0005);
|
||||||
|
actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, stepDown));
|
||||||
|
if (TCastToPtr<CScriptPlatform> plat = mgr.ObjectById(id))
|
||||||
|
mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider);
|
||||||
|
CGameCollision::SendMaterialMessage(mgr, result.x8_collision->GetMaterialLeft(), actor);
|
||||||
|
actor.SetLastFloorPlaneNormal({result.x8_collision->GetNormalLeft()});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.ClearForcesAndTorques();
|
actor.ClearForcesAndTorques();
|
||||||
|
@ -585,35 +636,218 @@ void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor&
|
||||||
mState.x1c_velocity = actor.GetLastNonCollidingState().x1c_velocity;
|
mState.x1c_velocity = actor.GetLastNonCollidingState().x1c_velocity;
|
||||||
actor.SetLastNonCollidingState(mState);
|
actor.SetLastNonCollidingState(mState);
|
||||||
|
|
||||||
const CCollisionPrimitive* prim = actor.GetCollisionPrimitive();
|
const CCollisionPrimitive* usePrim = actor.GetCollisionPrimitive();
|
||||||
if (prim->GetPrimType() == FOURCC('AABX'))
|
std::unique_ptr<CCollisionPrimitive> prim;
|
||||||
|
if (usePrim->GetPrimType() == FOURCC('AABX'))
|
||||||
{
|
{
|
||||||
// TODO: Finish
|
const CCollidableAABox& existingAABB = static_cast<const CCollidableAABox&>(*usePrim);
|
||||||
|
prim.reset(new CCollidableAABox(zeus::CAABox(existingAABB.GetAABB().min + 0.0001f,
|
||||||
|
existingAABB.GetAABB().max - 0.0001f),
|
||||||
|
usePrim->GetMaterial()));
|
||||||
|
usePrim = prim.get();
|
||||||
}
|
}
|
||||||
else if (prim->GetPrimType() == FOURCC('SPHR'))
|
else if (usePrim->GetPrimType() == FOURCC('SPHR'))
|
||||||
{
|
{
|
||||||
// TODO: Finish
|
const CCollidableSphere& existingSphere = static_cast<const CCollidableSphere&>(*usePrim);
|
||||||
|
prim.reset(new CCollidableSphere(zeus::CSphere(existingSphere.GetSphere().position,
|
||||||
|
existingSphere.GetSphere().radius - 0.0001f),
|
||||||
|
usePrim->GetMaterial()));
|
||||||
|
usePrim = prim.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
CGameCollision::CollisionFailsafe(mgr, cache, actor, *prim, useNearList, 0.f, 1);
|
CGameCollision::CollisionFailsafe(mgr, cache, actor, *usePrim, useNearList, 0.f, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGroundMovement::RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&, float&)
|
bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, const zeus::CVector3f& b,
|
||||||
|
zeus::CVector3f& c, float& d)
|
||||||
{
|
{
|
||||||
|
float dot = a.dot(c);
|
||||||
|
if (std::fabs(dot) > 0.99f)
|
||||||
|
return false;
|
||||||
|
float dot2 = b.dot(c);
|
||||||
|
float dot3 = b.dot((c - a * dot).normalized());
|
||||||
|
if (dot2 > 0.f && dot3 < 0.f)
|
||||||
|
return false;
|
||||||
|
if (std::fabs(dot2) > 0.01f && std::fabs(dot3 / dot2) > 4.f)
|
||||||
|
return false;
|
||||||
|
c -= dot * a;
|
||||||
|
d = dot;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGroundMovement::RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&)
|
bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b)
|
||||||
{
|
{
|
||||||
|
float dot = a.dot(b);
|
||||||
|
if (std::fabs(dot) > 0.99f)
|
||||||
|
return false;
|
||||||
|
b -= a * dot;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float,
|
static bool RemovePositiveZComponentFromNormal(zeus::CVector3f& vec)
|
||||||
|
{
|
||||||
|
if (vec.z > 0.f && vec.z < 0.99f)
|
||||||
|
{
|
||||||
|
vec.z = 0.f;
|
||||||
|
vec.normalize();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float dt,
|
||||||
rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
CAreaCollisionCache& cache, const SMovementOptions& opts,
|
CAreaCollisionCache& cache, const SMovementOptions& opts,
|
||||||
SMoveObjectResult& result)
|
SMoveObjectResult& result)
|
||||||
{
|
{
|
||||||
return {};
|
result.x6c_processedCollisions = 0;
|
||||||
|
CMaterialList ret;
|
||||||
|
zeus::CVector3f floorPlaneNormal = opts.x3c_floorPlaneNormal ?
|
||||||
|
*opts.x3c_floorPlaneNormal : zeus::CVector3f::skZero;
|
||||||
|
bool floorCollision = opts.x3c_floorPlaneNormal.operator bool();
|
||||||
|
float remDt = dt;
|
||||||
|
for (int i=0 ; remDt > 0.f ; ++i)
|
||||||
|
{
|
||||||
|
float collideDt = remDt;
|
||||||
|
|
||||||
|
CMotionState mState = actor.PredictMotion_Internal(remDt);
|
||||||
|
double mag = mState.x0_translation.magnitude();
|
||||||
|
zeus::CVector3f normTrans = (1.f / ((float(mag) > FLT_EPSILON) ? float(mag) : 1.f)) * mState.x0_translation;
|
||||||
|
TUniqueId id = kInvalidUniqueId;
|
||||||
|
CCollisionInfo collisionInfo;
|
||||||
|
|
||||||
|
if (mag > opts.x20_minimumTranslationDelta)
|
||||||
|
{
|
||||||
|
double oldMag = mag;
|
||||||
|
CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(),
|
||||||
|
actor.GetPrimitiveTransform(), actor.GetMaterialFilter(),
|
||||||
|
nearList, normTrans, id, collisionInfo, mag);
|
||||||
|
if (id != kInvalidUniqueId)
|
||||||
|
{
|
||||||
|
result.x0_id.emplace(id);
|
||||||
|
result.x8_collision.emplace(collisionInfo);
|
||||||
|
}
|
||||||
|
collideDt = mag / oldMag * remDt;
|
||||||
|
}
|
||||||
|
|
||||||
|
mag = std::max(0.f, float(mag) - opts.x20_minimumTranslationDelta);
|
||||||
|
|
||||||
|
zeus::CVector3f collisionNorm = collisionInfo.GetNormalLeft();
|
||||||
|
bool floor = CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionNorm);
|
||||||
|
bool clipCollision = true;
|
||||||
|
if (!opts.x19_alwaysClip)
|
||||||
|
{
|
||||||
|
if (!opts.x1a_disableClipForFloorOnly || floor)
|
||||||
|
clipCollision = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float collisionFloorDot = 0.f;
|
||||||
|
|
||||||
|
if (collisionInfo.IsValid())
|
||||||
|
{
|
||||||
|
result.x6c_processedCollisions += 1;
|
||||||
|
if (floor)
|
||||||
|
{
|
||||||
|
ret.Add(EMaterialTypes::Floor);
|
||||||
|
floorPlaneNormal = collisionInfo.GetNormalLeft();
|
||||||
|
floorCollision = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret.Add(EMaterialTypes::Wall);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clipCollision)
|
||||||
|
{
|
||||||
|
if (floorCollision)
|
||||||
|
{
|
||||||
|
if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, normTrans,
|
||||||
|
collisionNorm, collisionFloorDot))
|
||||||
|
RemovePositiveZComponentFromNormal(collisionNorm);
|
||||||
|
else
|
||||||
|
collisionNorm.normalize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemovePositiveZComponentFromNormal(collisionNorm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mState = actor.PredictMotion_Internal(collideDt);
|
||||||
|
}
|
||||||
|
|
||||||
|
mState.x0_translation = normTrans * mag;
|
||||||
|
actor.AddMotionState(mState);
|
||||||
|
|
||||||
|
if (collisionInfo.IsValid())
|
||||||
|
{
|
||||||
|
zeus::CVector3f vel = actor.GetVelocity().canBeNormalized() ?
|
||||||
|
CGroundMovement::CollisionDamping(actor.GetVelocity(), actor.GetVelocity().normalized(),
|
||||||
|
collisionNorm, opts.x24_dampedNormalCoefficient,
|
||||||
|
opts.x28_dampedDeltaCoefficient) :
|
||||||
|
zeus::CVector3f::skZero;
|
||||||
|
float elasticForce = floor ? opts.x2c_floorElasticForce :
|
||||||
|
opts.x34_wallElasticLinear * collisionFloorDot + opts.x30_wallElasticConstant;
|
||||||
|
float dot = collisionNorm.dot(vel);
|
||||||
|
if (dot < elasticForce)
|
||||||
|
vel += (elasticForce - dot) * collisionNorm;
|
||||||
|
if (clipCollision && floorCollision)
|
||||||
|
if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, vel))
|
||||||
|
vel.z = 0.f;
|
||||||
|
if (vel.z > opts.x38_maxPositiveVerticalVelocity)
|
||||||
|
vel *= (opts.x38_maxPositiveVerticalVelocity / vel.z);
|
||||||
|
|
||||||
|
if (opts.x18_dampForceAndMomentum)
|
||||||
|
{
|
||||||
|
if (actor.x15c_force.canBeNormalized())
|
||||||
|
{
|
||||||
|
actor.x15c_force = CGroundMovement::CollisionDamping(actor.x15c_force,
|
||||||
|
actor.x15c_force.normalized(),
|
||||||
|
collisionNorm, 0.f, 1.f);
|
||||||
|
}
|
||||||
|
if (actor.x150_momentum.canBeNormalized())
|
||||||
|
{
|
||||||
|
actor.x150_momentum = CGroundMovement::CollisionDamping(actor.x150_momentum,
|
||||||
|
actor.x150_momentum.normalized(),
|
||||||
|
collisionNorm, 0.f, 1.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.x0_setWaterLandingForce && !floor)
|
||||||
|
{
|
||||||
|
if (collisionInfo.GetNormalLeft().z < -0.1f && vel.z > 0.f)
|
||||||
|
vel.z *= 0.5f;
|
||||||
|
|
||||||
|
float zNormAbs = std::fabs(collisionInfo.GetNormalLeft().z);
|
||||||
|
if ((zNormAbs > opts.x10_downwardZThreshold && vel.z < 0.f) || zNormAbs > opts.xc_anyZThreshold)
|
||||||
|
{
|
||||||
|
actor.x15c_force = zeus::CVector3f(0.f, 0.f,
|
||||||
|
-(1.f + std::max(opts.x4_waterLandingForceCoefficient * zNormAbs,
|
||||||
|
opts.x8_minimumWaterLandingForce)) * actor.GetWeight());
|
||||||
|
vel *= (1.f - opts.x14_waterLandingVelocityReduction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actor.SetVelocityWR(vel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zeus::CVector3f vel = actor.x138_velocity;
|
||||||
|
if (actor.x138_velocity.z > opts.x38_maxPositiveVerticalVelocity)
|
||||||
|
vel *= (opts.x38_maxPositiveVerticalVelocity / vel.z);
|
||||||
|
|
||||||
|
actor.SetVelocityWR(vel);
|
||||||
|
}
|
||||||
|
|
||||||
|
actor.ClearImpulses();
|
||||||
|
|
||||||
|
remDt -= collideDt;
|
||||||
|
if (i >= opts.x1c_maxCollisionCycles)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.x70_processedDt = dt - remDt;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,32 +17,32 @@ class CGroundMovement
|
||||||
public:
|
public:
|
||||||
struct SMovementOptions
|
struct SMovementOptions
|
||||||
{
|
{
|
||||||
bool x0_;
|
bool x0_setWaterLandingForce;
|
||||||
float x4_;
|
float x4_waterLandingForceCoefficient;
|
||||||
float x8_;
|
float x8_minimumWaterLandingForce;
|
||||||
float xc_;
|
float xc_anyZThreshold;
|
||||||
float x10_;
|
float x10_downwardZThreshold;
|
||||||
float x14_;
|
float x14_waterLandingVelocityReduction;
|
||||||
bool x18_;
|
bool x18_dampForceAndMomentum;
|
||||||
bool x19_;
|
bool x19_alwaysClip;
|
||||||
bool x1a_;
|
bool x1a_disableClipForFloorOnly;
|
||||||
u32 x1c_;
|
u32 x1c_maxCollisionCycles;
|
||||||
float x20_;
|
float x20_minimumTranslationDelta;
|
||||||
float x24_;
|
float x24_dampedNormalCoefficient;
|
||||||
float x28_;
|
float x28_dampedDeltaCoefficient;
|
||||||
float x2c_;
|
float x2c_floorElasticForce;
|
||||||
float x30_;
|
float x30_wallElasticConstant;
|
||||||
float x34_;
|
float x34_wallElasticLinear;
|
||||||
float x38_;
|
float x38_maxPositiveVerticalVelocity;
|
||||||
std::experimental::optional<zeus::CVector3f> x3c_;
|
std::experimental::optional<zeus::CVector3f> x3c_floorPlaneNormal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMoveObjectResult
|
struct SMoveObjectResult
|
||||||
{
|
{
|
||||||
std::experimental::optional<TUniqueId> x0_id;
|
std::experimental::optional<TUniqueId> x0_id;
|
||||||
std::experimental::optional<CCollisionInfo> x8_collision;
|
std::experimental::optional<CCollisionInfo> x8_collision;
|
||||||
u32 x6c_;
|
u32 x6c_processedCollisions;
|
||||||
float x70_;
|
float x70_processedDt;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float);
|
static void CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float);
|
||||||
|
@ -57,12 +57,12 @@ public:
|
||||||
static void MoveGroundColliderXY(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
static void MoveGroundColliderXY(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor,
|
||||||
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
const CMaterialFilter& filter, rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
float);
|
float);
|
||||||
static void CollisionDamping(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&,
|
static zeus::CVector3f CollisionDamping(const zeus::CVector3f& a, const zeus::CVector3f& b,
|
||||||
float, float);
|
const zeus::CVector3f& c, float d, float e);
|
||||||
static void MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float,
|
static void MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float,
|
||||||
const rstl::reserved_vector<TUniqueId, 1024>* nearList);
|
const rstl::reserved_vector<TUniqueId, 1024>* nearList);
|
||||||
static void RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&, float&);
|
static bool RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&, zeus::CVector3f&, float&);
|
||||||
static void RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&);
|
static bool RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b);
|
||||||
static CMaterialList MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float,
|
static CMaterialList MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float,
|
||||||
rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
CAreaCollisionCache& cache, const SMovementOptions& opts,
|
CAreaCollisionCache& cache, const SMovementOptions& opts,
|
||||||
|
|
|
@ -239,11 +239,11 @@ 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::CVector3f& v)
|
||||||
{
|
{
|
||||||
if ((mat.HasMaterial(EMaterialTypes::Character) && !mat.HasMaterial(EMaterialTypes::Scannable)) ||
|
if ((mat.HasMaterial(EMaterialTypes::Character) && !mat.HasMaterial(EMaterialTypes::SolidCharacter)) ||
|
||||||
mat.HasMaterial(EMaterialTypes::Occluder))
|
mat.HasMaterial(EMaterialTypes::NoPlayerCollision))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (mat.HasMaterial(EMaterialTypes::Occluder) || mat.HasMaterial(EMaterialTypes::Floor))
|
if (mat.HasMaterial(EMaterialTypes::Floor))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return (v.z > 0.85f);
|
return (v.z > 0.85f);
|
||||||
|
@ -550,6 +550,7 @@ bool CGameCollision::DetectCollision_Cached(CStateManager& mgr, CAreaCollisionCa
|
||||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
TUniqueId& idOut, CCollisionInfoList& infoList)
|
TUniqueId& idOut, CCollisionInfoList& infoList)
|
||||||
{
|
{
|
||||||
|
idOut = kInvalidUniqueId;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::ThirtyEight))
|
if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::ThirtyEight))
|
||||||
if (DetectStaticCollision_Cached(mgr, cache, prim, xf, filter, infoList))
|
if (DetectStaticCollision_Cached(mgr, cache, prim, xf, filter, infoList))
|
||||||
|
@ -570,10 +571,16 @@ bool CGameCollision::DetectCollision_Cached_Moving(CStateManager& mgr, CAreaColl
|
||||||
const CMaterialFilter& filter,
|
const CMaterialFilter& filter,
|
||||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
const zeus::CVector3f& vec,
|
const zeus::CVector3f& vec,
|
||||||
TUniqueId& idOut, CCollisionInfo& infoOut, double&)
|
TUniqueId& idOut, CCollisionInfo& infoOut, double& d)
|
||||||
{
|
{
|
||||||
// TODO: Finish
|
idOut = kInvalidUniqueId;
|
||||||
return false;
|
if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::ThirtyEight))
|
||||||
|
{
|
||||||
|
if (CGameCollision::DetectStaticCollision_Cached_Moving(mgr, cache, prim, xf, filter, vec, infoOut, d))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CGameCollision::DetectDynamicCollisionMoving(prim, xf, nearList, vec, idOut, infoOut, d, mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameCollision::DetectStaticCollision(CStateManager& mgr, const CCollisionPrimitive& prim,
|
bool CGameCollision::DetectStaticCollision(CStateManager& mgr, const CCollisionPrimitive& prim,
|
||||||
|
@ -658,6 +665,15 @@ bool CGameCollision::DetectStaticCollision_Cached(CStateManager& mgr, CAreaColli
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGameCollision::DetectStaticCollision_Cached_Moving(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||||
|
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||||
|
const CMaterialFilter& filter, const zeus::CVector3f& vec,
|
||||||
|
CCollisionInfo& infoOut, double d)
|
||||||
|
{
|
||||||
|
// TODO: Finish
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CGameCollision::DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
bool CGameCollision::DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
TUniqueId& idOut, CCollisionInfoList& list, CStateManager& mgr)
|
TUniqueId& idOut, CCollisionInfoList& list, CStateManager& mgr)
|
||||||
|
@ -681,6 +697,15 @@ bool CGameCollision::DetectDynamicCollision(const CCollisionPrimitive& prim, con
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGameCollision::DetectDynamicCollisionMoving(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||||
|
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
|
const zeus::CVector3f& vec, TUniqueId& idOut,
|
||||||
|
CCollisionInfo& infoOut, double& d, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
// TODO: Finish
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CGameCollision::MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor,
|
void CGameCollision::MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor,
|
||||||
TUniqueId id, const CCollisionInfoList& list)
|
TUniqueId id, const CCollisionInfoList& list)
|
||||||
{
|
{
|
||||||
|
|
|
@ -92,9 +92,17 @@ public:
|
||||||
static bool DetectStaticCollision_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
|
static bool DetectStaticCollision_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||||
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||||
const CMaterialFilter& filter, CCollisionInfoList& list);
|
const CMaterialFilter& filter, CCollisionInfoList& list);
|
||||||
|
static bool DetectStaticCollision_Cached_Moving(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||||
|
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||||
|
const CMaterialFilter& filter, const zeus::CVector3f& vec,
|
||||||
|
CCollisionInfo& infoOut, double d);
|
||||||
static bool DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
static bool DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
TUniqueId& idOut, CCollisionInfoList& list, CStateManager& mgr);
|
TUniqueId& idOut, CCollisionInfoList& list, CStateManager& mgr);
|
||||||
|
static bool DetectDynamicCollisionMoving(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||||
|
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||||
|
const zeus::CVector3f& vec, TUniqueId& idOut,
|
||||||
|
CCollisionInfo& infoOut, double& d, CStateManager& mgr);
|
||||||
static void MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor, TUniqueId id,
|
static void MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor, TUniqueId id,
|
||||||
const CCollisionInfoList& list);
|
const CCollisionInfoList& list);
|
||||||
static void SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list);
|
static void SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list);
|
||||||
|
|
|
@ -61,9 +61,10 @@ enum class EMaterialTypes
|
||||||
RadarObject = 51,
|
RadarObject = 51,
|
||||||
PlatformSlave = 52,
|
PlatformSlave = 52,
|
||||||
Unknown54 = 54,
|
Unknown54 = 54,
|
||||||
Unknown55 = 55,
|
SolidCharacter = 55,
|
||||||
ExcludeFromLineOfSightTest = 56,
|
ExcludeFromLineOfSightTest = 56,
|
||||||
ExcludeFromRadar = 57,
|
ExcludeFromRadar = 57,
|
||||||
|
NoPlayerCollision = 58,
|
||||||
SixtyThree = 63
|
SixtyThree = 63
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue