feat(physics): IRigidbody Intertia and Inverse Mass & Intertia fields added
This commit is contained in:
@@ -27,6 +27,21 @@ public interface IRigidBody2D : IBehaviour2D
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
float Mass { get; set; }
|
float Mass { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The inverse mass (1 / Mass) of the <see cref="IRigidBody2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
float InverseMass { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Invertia of the <see cref="IRigidBody2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
float Inertia { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The inverse Invertia (1 / Invertia) of the <see cref="IRigidBody2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
float InverseInertia { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The value indicating whether the <see cref="IRigidBody2D"/> is static/immovable.
|
/// The value indicating whether the <see cref="IRigidBody2D"/> is static/immovable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,16 +1,75 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Engine.Core;
|
using Engine.Core;
|
||||||
|
|
||||||
namespace Engine.Physics2D;
|
namespace Engine.Physics2D;
|
||||||
|
|
||||||
public class RigidBody2D : Behaviour2D, IRigidBody2D
|
public class RigidBody2D : Behaviour2D, IRigidBody2D, IFirstFrameUpdate, ILastFrameUpdate
|
||||||
{
|
{
|
||||||
private const float LOWEST_ALLOWED_MASS = 0.00001f;
|
private const float LOWEST_ALLOWED_MASS = 0.00001f;
|
||||||
|
|
||||||
public IPhysicsMaterial2D Material { get; set; } = ReadOnlyPhysicsMaterial2D.Default;
|
public IPhysicsMaterial2D Material { get; set; } = new PhysicsMaterial2D(0f, 0f);
|
||||||
|
|
||||||
public Vector2D Velocity { get; set; } = Vector2D.Zero;
|
public Vector2D Velocity { get => IsStatic ? Vector2D.Zero : field; set => field = IsStatic ? Vector2D.Zero : value; } = Vector2D.Zero;
|
||||||
public float AngularVelocity { get; set; } = 0f;
|
public float AngularVelocity { get; set; } = 0f;
|
||||||
public bool IsStatic { get; set; } = false;
|
public bool IsStatic { get; set; } = false;
|
||||||
|
|
||||||
public float Mass { get; set => field = Math.Max(value, LOWEST_ALLOWED_MASS); } = 1f;
|
public float Mass { get; set { field = Math.Max(value, LOWEST_ALLOWED_MASS); } } = 1f;
|
||||||
|
public float InverseMass { get; protected set; } = 1f;
|
||||||
|
|
||||||
|
public float Inertia { get; protected set; } = 1f;
|
||||||
|
public float InverseInertia { get; protected set; } = 1f;
|
||||||
|
|
||||||
|
private readonly List<ICollider2D> childColliders = [];
|
||||||
|
|
||||||
|
public void LastActiveFrame() => DisconnectColliders();
|
||||||
|
public void FirstActiveFrame()
|
||||||
|
{
|
||||||
|
ReconnectColliders();
|
||||||
|
UpdateValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReconnectColliders()
|
||||||
|
{
|
||||||
|
DisconnectColliders();
|
||||||
|
|
||||||
|
BehaviourController.GetBehavioursInChildren(childColliders);
|
||||||
|
|
||||||
|
foreach (ICollider2D collider in childColliders)
|
||||||
|
collider.OnRecalculated.AddListener(RecalculateCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisconnectColliders()
|
||||||
|
{
|
||||||
|
foreach (ICollider2D collider in childColliders)
|
||||||
|
collider.OnRecalculated.RemoveListener(RecalculateCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecalculateCallback(ICollider2D _) => UpdateValues();
|
||||||
|
private void UpdateValues()
|
||||||
|
{
|
||||||
|
InverseMass = Mass.OneOver();
|
||||||
|
|
||||||
|
Vector2D center = Transform.Position;
|
||||||
|
Inertia = 0f;
|
||||||
|
|
||||||
|
float totalColliderArea = 0f;
|
||||||
|
|
||||||
|
foreach (ICollider2D collider in childColliders)
|
||||||
|
totalColliderArea += collider.Area;
|
||||||
|
|
||||||
|
foreach (ICollider2D collider in childColliders)
|
||||||
|
{
|
||||||
|
float colliderMass = Mass * (collider.Area / totalColliderArea);
|
||||||
|
float colliderInertia = collider.GeometricInertia * colliderMass;
|
||||||
|
float distanceSquared = center.FromTo(collider.Transform.Position).MagnitudeSquared;
|
||||||
|
|
||||||
|
Inertia += colliderInertia + colliderMass * distanceSquared;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childColliders.Count == 0)
|
||||||
|
Inertia = 1f;
|
||||||
|
|
||||||
|
InverseInertia = Inertia.OneOver();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user