Files
Physics-Engine/PhysicsEngine/Physics/Bodies/Body.cs
2026-09-03 17:27:52 +02:00

113 lines
3.5 KiB
C#

using System;
using System.Numerics;
using Raylib_cs;
namespace PhysicsEngine
{
public class Body
{
public Vector2 Position;
public Vector2 Velocity;
public Vector2 ForceAccumulator;
public Color BaseColor = Color.Blue;
public float Rotation;
public float AngularVelocity;
public float TorqueAccumulator;
public float Mass;
public float InverseMass => Mass > 0.0f ? 1.0f / Mass : 0.0f;
public float MomentOfInertia;
public float InverseInertia => MomentOfInertia > 0.0f ? 1.0f / MomentOfInertia : 0.0f;
public float Restitution = 0.5f;
public float Friction = 0.2f;
public float DragCoefficient = 0.0f; // Drag per m^2 (ignored if 0.0)
public bool IsStatic => Mass == 0.0f;
public void ApplyForce(Vector2 force)
{
if (IsStatic) return;
ForceAccumulator += force;
}
public void ApplyTorque(float torque)
{
if (IsStatic) return;
TorqueAccumulator += torque;
}
public void ApplyImpulse(Vector2 impulse)
{
if (IsStatic) return;
Velocity += impulse * InverseMass;
}
public void ApplyImpulseAtOffset(Vector2 impulse, Vector2 localOffset)
{
if (IsStatic) return;
Velocity += impulse * InverseMass;
float cos = MathF.Cos(Rotation);
float sin = MathF.Sin(Rotation);
Vector2 worldOffset = new Vector2(
localOffset.X * cos - localOffset.Y * sin,
localOffset.X * sin + localOffset.Y * cos
);
float torque = worldOffset.X * impulse.Y - worldOffset.Y * impulse.X;
AngularVelocity += torque * InverseInertia;
}
public void ApplyImpulseAtWorldPosition(Vector2 impulse, Vector2 worldPosition)
{
if (IsStatic) return;
Velocity += impulse * InverseMass;
Vector2 worldOffset = worldPosition - Position;
float torque = worldOffset.X * impulse.Y - worldOffset.Y * impulse.X;
AngularVelocity += torque * InverseInertia;
}
public void ApplyForceAtWorldPosition(Vector2 force, Vector2 worldPosition)
{
if (IsStatic) return;
ForceAccumulator += force;
Vector2 worldOffset = worldPosition - Position;
float torque = worldOffset.X * force.Y - worldOffset.Y * force.X;
TorqueAccumulator += torque;
}
public Vector2 GetWorldPointFromLocal(Vector2 localPoint)
{
float cos = MathF.Cos(Rotation);
float sin = MathF.Sin(Rotation);
Vector2 rotated = new Vector2(
localPoint.X * cos - localPoint.Y * sin,
localPoint.X * sin + localPoint.Y * cos
);
return Position + rotated;
}
public Vector2 GetLocalPointFromWorld(Vector2 worldPoint)
{
Vector2 delta = worldPoint - Position;
float cos = MathF.Cos(-Rotation);
float sin = MathF.Sin(-Rotation);
return new Vector2(
delta.X * cos - delta.Y * sin,
delta.X * sin + delta.Y * cos
);
}
public void ClearForces()
{
ForceAccumulator = Vector2.Zero;
TorqueAccumulator = 0.0f;
}
public virtual void Draw(float pixelsPerMeter = 100.0f) {}
public virtual void ApplyAerodynamicDrag(float dt) {}
}
}