metaforce/Runtime/World/CPhysicsActor.cpp

357 lines
12 KiB
C++
Raw Normal View History

2016-04-19 00:17:49 +00:00
#include "CPhysicsActor.hpp"
namespace urde
{
2017-11-13 06:19:18 +00:00
CPhysicsActor::CPhysicsActor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info,
2016-04-22 20:22:45 +00:00
const zeus::CTransform& xf, CModelData&& mData, const CMaterialList& matList,
2016-04-19 00:17:49 +00:00
const zeus::CAABox& box, const SMoverData& moverData, const CActorParameters& actorParms,
2016-09-01 09:31:18 +00:00
float stepUp, float stepDown)
: CActor(uid, active, name, info, xf, std::move(mData), matList, actorParms, kInvalidUniqueId)
, xe8_mass(moverData.x30_mass)
, xec_massRecip(moverData.x30_mass <= 0.f ? 1.f : 1.f / moverData.x30_mass)
2017-03-01 03:42:06 +00:00
, x150_momentum(moverData.x18_momentum)
2017-11-26 03:04:25 +00:00
, x1a4_baseBoundingBox(box)
, x1c0_collisionPrimitive(box, matList)
, x1f4_lastNonCollidingState(xf.origin, xf.buildMatrix3f())
, x23c_stepUpHeight(stepUp)
, x240_stepDownHeight(stepDown)
2016-09-01 09:31:18 +00:00
{
xf8_24_movable = true;
2016-09-01 09:31:18 +00:00
SetMass(moverData.x30_mass);
MoveCollisionPrimitive(zeus::CVector3f::skZero);
SetVelocityOR(moverData.x0_velocity);
SetAngularVelocityOR(moverData.xc_angularVelocity);
ComputeDerivedQuantities();
2016-04-19 00:17:49 +00:00
}
void CPhysicsActor::Render(const CStateManager& mgr) const { CActor::Render(mgr); }
zeus::CVector3f CPhysicsActor::GetOrbitPosition(const CStateManager&) const { return GetBoundingBox().center(); }
2016-09-01 09:31:18 +00:00
zeus::CVector3f CPhysicsActor::GetAimPosition(const CStateManager&, float dt) const
{
2016-09-01 09:31:18 +00:00
if (dt <= 0.0)
return GetBoundingBox().center();
2016-09-01 09:31:18 +00:00
zeus::CVector3f trans = PredictMotion(dt).x0_translation;
return GetBoundingBox().center() + trans;
}
void CPhysicsActor::CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&) {}
2017-03-03 22:13:23 +00:00
const CCollisionPrimitive* CPhysicsActor::GetCollisionPrimitive() const { return &x1c0_collisionPrimitive; }
2016-09-01 04:10:08 +00:00
zeus::CTransform CPhysicsActor::GetPrimitiveTransform() const
{
2016-09-01 04:10:08 +00:00
return zeus::CTransform::Translate(x34_transform.origin + x1e8_primitiveOffset);
}
float CPhysicsActor::GetStepUpHeight() const { return x23c_stepUpHeight; }
float CPhysicsActor::GetStepDownHeight() const { return x240_stepDownHeight; }
float CPhysicsActor::GetWeight() const { return 24.525002f * xe8_mass; }
void CPhysicsActor::SetPrimitiveOffset(const zeus::CVector2f& offset) { x1e8_primitiveOffset = offset; }
2018-06-24 02:39:53 +00:00
zeus::CVector3f CPhysicsActor::GetPrimitiveOffset() const { return x1e8_primitiveOffset; }
void CPhysicsActor::MoveCollisionPrimitive(const zeus::CVector3f& offset) { x1e8_primitiveOffset = offset; }
void CPhysicsActor::SetBoundingBox(const zeus::CAABox& box)
{
x1a4_baseBoundingBox = box;
MoveCollisionPrimitive(zeus::CVector3f::skZero);
}
2016-09-01 04:10:08 +00:00
zeus::CAABox CPhysicsActor::GetMotionVolume(float dt) const
{
2017-03-03 22:13:23 +00:00
zeus::CAABox aabox = GetCollisionPrimitive()->CalculateAABox(GetPrimitiveTransform());
2016-09-01 04:10:08 +00:00
zeus::CVector3f velocity = CalculateNewVelocityWR_UsingImpulses();
const zeus::CVector3f dv = (dt * velocity);
aabox.accumulateBounds(aabox.max + dv);
aabox.accumulateBounds(aabox.min + dv);
float up = GetStepUpHeight();
up = zeus::max(up, 0.f);
2018-02-08 06:18:27 +00:00
aabox.accumulateBounds(aabox.max + zeus::CVector3f(0.5f, 0.5f, up + 1.f));
2016-09-01 04:10:08 +00:00
float down = GetStepDownHeight();
down = zeus::max(down, 0.f);
2018-02-08 06:18:27 +00:00
aabox.accumulateBounds(aabox.min - zeus::CVector3f(0.5f, 0.5f, down + 1.5f));
2016-09-01 04:10:08 +00:00
return aabox;
}
zeus::CVector3f CPhysicsActor::CalculateNewVelocityWR_UsingImpulses() const
{
2017-09-07 03:55:31 +00:00
return x138_velocity + (xec_massRecip * (x168_impulse + x18c_moveImpulse));
}
2016-09-01 09:31:18 +00:00
zeus::CAABox CPhysicsActor::GetBoundingBox() const
2016-04-22 20:22:45 +00:00
{
return {x1a4_baseBoundingBox.min + x1e8_primitiveOffset + x34_transform.origin,
x1a4_baseBoundingBox.max + x1e8_primitiveOffset + x34_transform.origin};
2016-04-22 20:22:45 +00:00
}
const zeus::CAABox& CPhysicsActor::GetBaseBoundingBox() const { return x1a4_baseBoundingBox; }
2016-09-01 04:10:08 +00:00
void CPhysicsActor::AddMotionState(const CMotionState& mst)
{
zeus::CNUQuaternion q{x34_transform.buildMatrix3f()};
2017-06-12 04:23:34 +00:00
q += mst.xc_orientation;
2017-11-30 01:22:46 +00:00
zeus::CQuaternion quat = zeus::CQuaternion::fromNUQuaternion(q);
SetTransform(zeus::CTransform(quat, x34_transform.origin));
2016-09-01 04:10:08 +00:00
2016-09-01 09:31:18 +00:00
SetTranslation(x34_transform.origin + mst.x0_translation);
2016-09-01 04:10:08 +00:00
xfc_constantForce += mst.x1c_velocity;
2017-11-28 10:06:40 +00:00
x108_angularMomentum += mst.x28_angularMomentum;
2016-09-01 04:10:08 +00:00
ComputeDerivedQuantities();
}
CMotionState CPhysicsActor::GetMotionState() const
{
2016-09-01 09:31:18 +00:00
return {x34_transform.origin, {x34_transform.buildMatrix3f()}, xfc_constantForce, x108_angularMomentum};
}
void CPhysicsActor::SetMotionState(const CMotionState& mst)
2016-09-01 09:31:18 +00:00
{
2017-11-12 05:14:57 +00:00
SetTransform(zeus::CTransform(zeus::CQuaternion::fromNUQuaternion(mst.xc_orientation), x34_transform.origin));
2016-09-01 09:31:18 +00:00
SetTranslation(mst.x0_translation);
xfc_constantForce = mst.x1c_velocity;
x108_angularMomentum = mst.x28_angularMomentum;
2016-09-01 09:31:18 +00:00
ComputeDerivedQuantities();
2016-09-01 04:10:08 +00:00
}
void CPhysicsActor::SetInertiaTensorScalar(float tensor)
{
if (tensor <= 0.0f)
tensor = 1.0f;
2016-09-01 04:10:08 +00:00
xf0_inertiaTensor = tensor;
xf4_inertiaTensorRecip = 1.0f / tensor;
}
void CPhysicsActor::SetMass(float mass)
{
xe8_mass = mass;
float tensor = 1.0f;
if (mass > 0.0f)
tensor = 1.0f / mass;
xec_massRecip = tensor;
2018-05-27 04:22:38 +00:00
SetInertiaTensorScalar(mass / 6.f);
}
2016-09-01 04:10:08 +00:00
void CPhysicsActor::SetAngularVelocityOR(const zeus::CAxisAngle& angVel)
{
x144_angularVelocity = x34_transform.rotate(angVel);
2016-09-01 09:31:18 +00:00
x108_angularMomentum = xf0_inertiaTensor * x144_angularVelocity;
2016-09-01 04:10:08 +00:00
}
zeus::CAxisAngle CPhysicsActor::GetAngularVelocityOR() const
{
return x34_transform.transposeRotate(x144_angularVelocity);
}
void CPhysicsActor::SetAngularVelocityWR(const zeus::CAxisAngle& angVel)
{
x144_angularVelocity = angVel;
2016-09-01 09:31:18 +00:00
x108_angularMomentum = xf0_inertiaTensor * x144_angularVelocity;
2016-09-01 04:10:08 +00:00
}
void CPhysicsActor::SetVelocityWR(const zeus::CVector3f& vel)
2016-09-01 04:10:08 +00:00
{
x138_velocity = vel;
2016-09-01 09:31:18 +00:00
xfc_constantForce = xe8_mass * x138_velocity;
2016-09-01 04:10:08 +00:00
}
void CPhysicsActor::SetVelocityOR(const zeus::CVector3f& vel) { SetVelocityWR(x34_transform.rotate(vel)); }
2016-09-01 04:10:08 +00:00
zeus::CVector3f CPhysicsActor::GetTotalForcesWR() const { return x15c_force + x150_momentum; }
2016-09-01 04:10:08 +00:00
void CPhysicsActor::RotateInOneFrameOR(const zeus::CQuaternion& q, float d)
2016-09-01 04:10:08 +00:00
{
2017-09-07 03:55:31 +00:00
x198_moveAngularImpulse += GetRotateToORAngularMomentumWR(q, d);
2016-09-01 04:10:08 +00:00
}
2017-09-07 03:55:31 +00:00
void CPhysicsActor::MoveInOneFrameOR(const zeus::CVector3f& trans, float d)
{
x18c_moveImpulse += GetMoveToORImpulseWR(trans, d);
}
2016-09-01 09:31:18 +00:00
void CPhysicsActor::RotateToOR(const zeus::CQuaternion& q, float d)
{
x108_angularMomentum = GetRotateToORAngularMomentumWR(q, d);
ComputeDerivedQuantities();
}
void CPhysicsActor::MoveToOR(const zeus::CVector3f& trans, float d)
{
xfc_constantForce = GetMoveToORImpulseWR(trans, d);
ComputeDerivedQuantities();
}
2018-02-08 06:18:27 +00:00
void CPhysicsActor::MoveToInOneFrameWR(const zeus::CVector3f& trans, float d)
2016-09-01 09:31:18 +00:00
{
2017-09-07 03:55:31 +00:00
x18c_moveImpulse += xe8_mass * (trans - x34_transform.origin) * (1.f / d);
2016-09-01 09:31:18 +00:00
}
void CPhysicsActor::MoveToWR(const zeus::CVector3f& trans, float d)
{
xfc_constantForce = xe8_mass * (trans - x34_transform.origin) * (1.f / d);
ComputeDerivedQuantities();
}
zeus::CAxisAngle CPhysicsActor::GetRotateToORAngularMomentumWR(const zeus::CQuaternion& q, float d) const
2016-09-01 04:10:08 +00:00
{
if (q.w > 0.99999976)
2016-09-01 09:31:18 +00:00
return zeus::CAxisAngle::skZero;
return (xf0_inertiaTensor *
(((2.f * std::acos(q.w)) * (1.f / d)) * x34_transform.rotate({q.x, q.y, q.z}).normalized()));
2016-09-01 04:10:08 +00:00
}
zeus::CVector3f CPhysicsActor::GetMoveToORImpulseWR(const zeus::CVector3f& trans, float d) const
2016-09-01 09:31:18 +00:00
{
return (xe8_mass * x34_transform.rotate(trans)) * (1.f / d);
}
2016-09-01 04:10:08 +00:00
void CPhysicsActor::ClearImpulses()
{
2017-09-07 03:55:31 +00:00
x18c_moveImpulse = x168_impulse = zeus::CVector3f::skZero;
x198_moveAngularImpulse = x180_angularImpulse = zeus::CAxisAngle::skZero;
2016-09-01 04:10:08 +00:00
}
void CPhysicsActor::ClearForcesAndTorques()
{
2017-09-07 03:55:31 +00:00
x18c_moveImpulse = x168_impulse = x15c_force = zeus::CVector3f::skZero;
x198_moveAngularImpulse = x180_angularImpulse = x174_torque = zeus::CAxisAngle::skZero;
2016-09-01 04:10:08 +00:00
}
void CPhysicsActor::Stop()
{
ClearForcesAndTorques();
2016-09-01 09:31:18 +00:00
xfc_constantForce = zeus::CVector3f::skZero;
x108_angularMomentum = zeus::CAxisAngle::skZero;
2016-09-01 04:10:08 +00:00
ComputeDerivedQuantities();
}
void CPhysicsActor::ComputeDerivedQuantities()
{
2016-09-01 09:31:18 +00:00
x138_velocity = xec_massRecip * xfc_constantForce;
2016-09-01 04:10:08 +00:00
x114_ = x34_transform.buildMatrix3f();
2017-11-30 01:22:46 +00:00
x144_angularVelocity = xf4_inertiaTensorRecip * x108_angularMomentum;
2016-09-01 04:10:08 +00:00
}
bool CPhysicsActor::WillMove(const CStateManager&)
{
if (!zeus::close_enough(zeus::CVector3f::skZero, x138_velocity) ||
!zeus::close_enough(zeus::CVector3f::skZero, x168_impulse) ||
!zeus::close_enough(zeus::CVector3f::skZero, x174_torque) ||
2017-09-07 03:55:31 +00:00
!zeus::close_enough(zeus::CVector3f::skZero, x18c_moveImpulse) ||
!zeus::close_enough(zeus::CVector3f::skZero, x144_angularVelocity) ||
!zeus::close_enough(zeus::CVector3f::skZero, x180_angularImpulse) ||
2017-09-07 03:55:31 +00:00
!zeus::close_enough(zeus::CVector3f::skZero, x198_moveAngularImpulse) ||
!zeus::close_enough(zeus::CVector3f::skZero, GetTotalForcesWR()))
2016-09-01 04:10:08 +00:00
return true;
return false;
}
void CPhysicsActor::SetPhysicsState(const CPhysicsState& state)
2016-09-01 09:31:18 +00:00
{
SetTranslation(state.GetTranslation());
2017-08-18 01:30:15 +00:00
SetTransform(zeus::CTransform(state.GetOrientation(), x34_transform.origin));
2016-09-01 09:31:18 +00:00
xfc_constantForce = state.GetConstantForceWR();
x108_angularMomentum = state.GetAngularMomentumWR();
2016-09-01 09:31:18 +00:00
x150_momentum = state.GetMomentumWR();
x15c_force = state.GetForceWR();
x168_impulse = state.GetImpulseWR();
x174_torque = state.GetTorque();
x180_angularImpulse = state.GetAngularImpulseWR();
ComputeDerivedQuantities();
}
CPhysicsState CPhysicsActor::GetPhysicsState() const
{
return {x34_transform.origin, {x34_transform.buildMatrix3f()},
xfc_constantForce, x108_angularMomentum,
x150_momentum, x15c_force,
x168_impulse, x174_torque,
x180_angularImpulse};
2016-09-01 09:31:18 +00:00
}
CMotionState CPhysicsActor::PredictMotion_Internal(float dt) const
{
if (xf8_25_angularEnabled)
2017-12-12 02:06:19 +00:00
return PredictLinearMotion(dt);
2016-09-01 09:31:18 +00:00
CMotionState msl = PredictLinearMotion(dt);
CMotionState msa = PredictAngularMotion(dt);
return {msl.x0_translation, msa.xc_orientation, msl.x1c_velocity, msa.x28_angularMomentum};
2016-09-01 09:31:18 +00:00
}
CMotionState CPhysicsActor::PredictMotion(float dt) const
{
CMotionState msl = PredictLinearMotion(dt);
CMotionState msa = PredictAngularMotion(dt);
return {msl.x0_translation, msa.xc_orientation, msl.x1c_velocity, msa.x28_angularMomentum};
2016-09-01 09:31:18 +00:00
}
CMotionState CPhysicsActor::PredictLinearMotion(float dt) const
{
zeus::CVector3f velocity = CalculateNewVelocityWR_UsingImpulses();
2017-11-12 05:14:57 +00:00
return {velocity * dt, {0.f, zeus::CVector3f::skZero}, ((x15c_force + x150_momentum) * dt) + x168_impulse,
zeus::CAxisAngle::skZero};
2016-09-01 09:31:18 +00:00
}
CMotionState CPhysicsActor::PredictAngularMotion(float dt) const
{
2017-09-07 03:55:31 +00:00
const zeus::CVector3f v1 = xf4_inertiaTensorRecip * (x180_angularImpulse + x198_moveAngularImpulse);
2017-11-30 01:22:46 +00:00
zeus::CNUQuaternion q = 0.5f * zeus::CNUQuaternion(0.f, x144_angularVelocity.getVector() + v1);
2017-12-12 02:06:19 +00:00
CMotionState ret = {zeus::CVector3f::skZero, (q * zeus::CNUQuaternion(x34_transform.buildMatrix3f())) * dt,
zeus::CVector3f::skZero, (x174_torque * dt) + x180_angularImpulse};
2017-11-12 05:14:57 +00:00
return ret;
2016-09-01 09:31:18 +00:00
}
void CPhysicsActor::ApplyForceOR(const zeus::CVector3f& force, const zeus::CAxisAngle& torque)
{
x15c_force += x34_transform.rotate(force);
x174_torque += x34_transform.rotate(torque);
}
void CPhysicsActor::ApplyForceWR(const zeus::CVector3f& force, const zeus::CAxisAngle& torque)
2016-09-01 09:31:18 +00:00
{
x15c_force += force;
x174_torque += torque;
}
void CPhysicsActor::ApplyImpulseOR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angle)
2016-09-01 09:31:18 +00:00
{
x168_impulse += x34_transform.rotate(impulse);
x180_angularImpulse += x34_transform.rotate(angle);
}
void CPhysicsActor::ApplyImpulseWR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angleImp)
2016-09-01 09:31:18 +00:00
{
x168_impulse += impulse;
x180_angularImpulse += angleImp;
}
void CPhysicsActor::ApplyTorqueWR(const zeus::CVector3f& torque) { x174_torque += torque; }
2016-09-01 09:31:18 +00:00
void CPhysicsActor::UseCollisionImpulses()
{
xfc_constantForce += x168_impulse;
x108_angularMomentum += x180_angularImpulse;
x168_impulse = zeus::CVector3f::skZero;
x180_angularImpulse = zeus::CAxisAngle::skZero;
ComputeDerivedQuantities();
}
2016-04-19 00:17:49 +00:00
}