using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.Physics;
///
/// Represents a rigidbody component that simulates physics behavior such as force, velocity, and acceleration.
///
public class RigidbodyComponent : Engine.Scene.Component.Component
{
///
/// The mass of the rigidbody.
///
public float Mass { get; set; } = 1.0f;
///
/// The moment of inertia of the rigidbody.
/// For simplicity, this assumes a scalar value, suitable for symmetric objects.
///
public float MomentOfInertia { get; set; } = 1.0f;
///
/// Indicates whether the rigidbody is static and unaffected by forces.
///
public bool IsStatic { get; set; } = false;
///
/// The force currently applied to the rigidbody.
///
public Vector3 Force
{
get => _force;
set
{
if (IsStatic)
{
return;
}
_force = value;
}
}
///
/// The torque currently applied to the rigidbody.
///
public Vector3 Torque
{
get => _torque;
set
{
if (IsStatic)
{
return;
}
_torque = value;
}
}
///
/// The velocity of the rigidbody.
///
public Vector3 Velocity
{
get => _velocity;
set
{
if (IsStatic)
{
return;
}
_velocity = value;
}
}
///
/// The angular velocity of the rigidbody.
///
public Vector3 AngularVelocity
{
get => _angularVelocity;
set
{
if (IsStatic)
{
return;
}
_angularVelocity = value;
}
}
///
/// The force currently applied to the rigidbody.
///
private Vector3 _force = Vector3.Zero;
///
/// The acceleration of the rigidbody.
///
private Vector3 _acceleration = Vector3.Zero;
///
/// The velocity of the rigidbody.
///
private Vector3 _velocity = Vector3.Zero;
///
/// The torque currently applied to the rigidbody.
///
private Vector3 _torque = Vector3.Zero;
///
/// The angular acceleration of the rigidbody.
///
private Vector3 _angularAcceleration = Vector3.Zero;
///
/// The angular velocity of the rigidbody.
///
private Vector3 _angularVelocity = Vector3.Zero;
public override void PostUpdate(double parDeltaTime)
{
if (IsStatic)
{
return;
}
ApplyForce(parDeltaTime);
ApplyTorque(parDeltaTime);
}
///
/// Applies force to the rigidbody.
///
/// The time in seconds since the last update.
private void ApplyForce(double parDeltaTime)
{
_acceleration = Force / Mass;
Velocity += _acceleration * (float)parDeltaTime;
GameObject.Transform.Translation += Velocity * (float)parDeltaTime;
Force = Vector3.Zero;
}
///
/// Applies torque to the rigidbody.
///
/// The time in seconds since the last update.
private void ApplyTorque(double parDeltaTime)
{
_angularAcceleration = Torque / MomentOfInertia;
AngularVelocity += _angularAcceleration * (float)parDeltaTime;
GameObject.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitX, AngularVelocity.X * (float)parDeltaTime);
GameObject.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitY, AngularVelocity.Y * (float)parDeltaTime);
GameObject.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitZ, AngularVelocity.Z * (float)parDeltaTime);
Torque = Vector3.Zero;
}
}