BREAKING CHANGE: New ICollider

This commit is contained in:
Syntriax 2024-01-24 19:21:53 +03:00
parent 350ef030ac
commit ed15238dcd
11 changed files with 123 additions and 77 deletions

View File

@ -0,0 +1,9 @@
using Syntriax.Engine.Physics2D.Primitives;
namespace Syntriax.Engine.Physics2D.Abstract;
public interface ICircleCollider2D : ICollider2D
{
Circle CircleLocal { get; set; }
Circle CircleWorld { get; }
}

View File

@ -1,6 +1,4 @@
using System; using System;
using System.Collections.Generic;
using Syntriax.Engine.Core; using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract; using Syntriax.Engine.Core.Abstract;
@ -9,11 +7,9 @@ namespace Syntriax.Engine.Physics2D.Abstract;
public interface ICollider2D : IBehaviour, IAssignableTransform public interface ICollider2D : IBehaviour, IAssignableTransform
{ {
Action<ICollider2D, ICollider2D>? OnCollisionPreResolve { get; set; } Action<ICollider2D, ICollider2D>? OnCollisionPreResolve { get; set; }
Action<ICollider2D, ICollider2D>? OnCollisionResolved { get; set; }
IRigidBody2D? RigidBody2D { get; } IRigidBody2D? RigidBody2D { get; }
IList<Vector2D> Vertices { get; }
bool CheckCollision(Vector2D point);
void Recalculate(); void Recalculate();
} }

View File

@ -11,4 +11,5 @@ public interface IRigidBody2D : IBehaviour, IAssignableTransform
float AngularVelocity { get; set; } float AngularVelocity { get; set; }
float Mass { get; set; } float Mass { get; set; }
bool IsStatic { get; set; }
} }

View File

@ -0,0 +1,9 @@
using Syntriax.Engine.Physics2D.Primitives;
namespace Syntriax.Engine.Physics2D.Abstract;
public interface IShapeCollider2D : ICollider2D
{
Shape ShapeLocal { get; set; }
Shape ShapeWorld { get; }
}

View File

@ -1,67 +0,0 @@
using System;
using System.Collections.Generic;
using Engine.Physics2D;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
using Syntriax.Engine.Physics2D.Primitives;
namespace Syntriax.Engine.Physics2D;
public class Collider2DAABBBehaviour : BehaviourOverride, ICollider2D
{
public AABB AABBLocal { get; set; } = null!;
public AABB AABBWorld { get; private set; } = null!;
private IRigidBody2D? _rigidBody2D = null;
private List<Vector2D> _vertices = new List<Vector2D>(4);
public IRigidBody2D? RigidBody2D
{
get
{
if (_rigidBody2D is null)
BehaviourController.TryGetBehaviour(out _rigidBody2D);
return _rigidBody2D;
}
}
public Action<ICollider2D, ICollider2D>? OnCollisionPreResolve { get; set; } = null;
public Action<IAssignableTransform>? OnTransformAssigned { get => GameObject.OnTransformAssigned; set => GameObject.OnTransformAssigned = value; }
ITransform IAssignableTransform.Transform => Transform;
public bool Assign(ITransform transform) => GameObject.Assign(transform);
public IList<Vector2D> Vertices => _vertices;
public bool CheckCollision(Vector2D point)
{
return AABBWorld.Overlaps(point);
}
public void Recalculate()
{
AABBWorld = new AABB(
AABBLocal.LowerBoundary.Scale(Transform.Scale) + Transform.Position,
AABBLocal.UpperBoundary.Scale(Transform.Scale) + Transform.Position
);
Vertices.Clear();
Vertices.Add(AABBWorld.LowerBoundary);
Vertices.Add(new Vector2D(AABBWorld.LowerBoundary.X, AABBWorld.UpperBoundary.Y));
Vertices.Add(AABBWorld.UpperBoundary);
Vertices.Add(new Vector2D(AABBWorld.UpperBoundary.X, AABBWorld.LowerBoundary.Y));
}
public Collider2DAABBBehaviour(Vector2D lowerBoundary, Vector2D upperBoundary)
{
AABBLocal = new AABB(lowerBoundary, upperBoundary);
AABBWorld = new AABB(lowerBoundary, upperBoundary);
}
public Collider2DAABBBehaviour()
{
AABBLocal = new(Vector2D.Zero, Vector2D.Zero);
AABBWorld = new(Vector2D.Zero, Vector2D.Zero);
}
}

View File

@ -0,0 +1,28 @@
using System;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
using Syntriax.Engine.Physics2D.Primitives;
namespace Syntriax.Engine.Physics2D;
public class Collider2DCircleBehaviour : BehaviourOverride, ICircleCollider2D
{
public Action<ICollider2D, ICollider2D>? OnCollisionPreResolve { get; set; } = null;
public Action<ICollider2D, ICollider2D>? OnCollisionResolved { get; set; } = null;
public Action<IAssignableTransform>? OnTransformAssigned { get; set; } = null;
public Circle CircleWorld { get; protected set; } = new(Vector2D.Zero, 1f);
public Circle CircleLocal { get; set; } = new(Vector2D.Zero, 1f);
public IRigidBody2D? RigidBody2D { get; set; } = null;
ITransform IAssignableTransform.Transform => GameObject.Transform;
public bool Assign(ITransform transform) => GameObject.Assign(transform);
public virtual void Recalculate() => CircleWorld = Transform.TransformCircle(CircleLocal).Displace(Transform.Position);
}

View File

@ -0,0 +1,29 @@
using System;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
using Syntriax.Engine.Physics2D.Primitives;
namespace Syntriax.Engine.Physics2D;
public class Collider2DShapeBehaviour : BehaviourOverride, IShapeCollider2D
{
public Action<ICollider2D, ICollider2D>? OnCollisionPreResolve { get; set; } = null;
public Action<ICollider2D, ICollider2D>? OnCollisionResolved { get; set; } = null;
public Action<IAssignableTransform>? OnTransformAssigned { get; set; } = null;
public Shape ShapeWorld => _shapeWorld;
public Shape ShapeLocal { get; set; } = new([new(1f, 1f), new(-1f, 1f), new(-1f, -1f), new(1f, -1f)]);
public IRigidBody2D? RigidBody2D { get; set; } = null;
protected Shape _shapeWorld = new([new(1f, 1f), new(-1f, 1f), new(-1f, -1f), new(1f, -1f)]);
ITransform IAssignableTransform.Transform => GameObject.Transform;
public bool Assign(ITransform transform) => GameObject.Assign(transform);
public virtual void Recalculate() => Transform.TransformShape(ShapeLocal, ref _shapeWorld);
}

View File

@ -10,7 +10,7 @@ public static partial class Physics2D
{ {
public static bool Overlaps(this Circle left, Circle right) public static bool Overlaps(this Circle left, Circle right)
{ {
float distanceSquared = left.Position.FromTo(right.Position).LengthSquared(); float distanceSquared = left.Center.FromTo(right.Center).LengthSquared();
float radiusSumSquared = left.RadiusSquared + right.RadiusSquared; float radiusSumSquared = left.RadiusSquared + right.RadiusSquared;
return distanceSquared < radiusSumSquared; return distanceSquared < radiusSumSquared;
@ -18,7 +18,7 @@ public static partial class Physics2D
public static bool Overlaps(this Circle left, Circle right, out Vector2D normal, out float depth) public static bool Overlaps(this Circle left, Circle right, out Vector2D normal, out float depth)
{ {
Vector2D distanceVector = left.Position.FromTo(right.Position); Vector2D distanceVector = left.Center.FromTo(right.Center);
float distanceSquared = distanceVector.LengthSquared(); float distanceSquared = distanceVector.LengthSquared();
float radiusSumSquared = left.RadiusSquared + right.RadiusSquared; float radiusSumSquared = left.RadiusSquared + right.RadiusSquared;
bool isOverlapping = distanceSquared < radiusSumSquared; bool isOverlapping = distanceSquared < radiusSumSquared;
@ -32,10 +32,10 @@ public static partial class Physics2D
return isOverlapping; return isOverlapping;
} }
public static bool Overlaps(this Circle circle, Vector2D point) => circle.Position.FromTo(point).LengthSquared() <= circle.RadiusSquared; public static bool Overlaps(this Circle circle, Vector2D point) => circle.Center.FromTo(point).LengthSquared() <= circle.RadiusSquared;
public static bool Overlaps(this Circle circle, Vector2D point, out Vector2D normal, out float depth) public static bool Overlaps(this Circle circle, Vector2D point, out Vector2D normal, out float depth)
{ {
Vector2D distanceVector = circle.Position.FromTo(point); Vector2D distanceVector = circle.Center.FromTo(point);
float distanceSquared = distanceVector.LengthSquared(); float distanceSquared = distanceVector.LengthSquared();
float radiusSquared = circle.RadiusSquared; float radiusSquared = circle.RadiusSquared;
bool isOverlapping = distanceSquared < radiusSquared; bool isOverlapping = distanceSquared < radiusSquared;

View File

@ -1,4 +1,5 @@
using Syntriax.Engine.Core; using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Physics2D.Primitives; namespace Syntriax.Engine.Physics2D.Primitives;
@ -7,11 +8,26 @@ public record Circle(Vector2D Center, float Radius)
public float RadiusSquared => Radius * Radius; public float RadiusSquared => Radius * Radius;
public float Diameter => 2f * Radius; public float Diameter => 2f * Radius;
public static Circle SetCenter(Circle circle, Vector2D center) => new(center, circle.Radius);
public static Circle SetRadius(Circle circle, float radius) => new(circle.Center, radius);
public static Circle Displace(Circle circle, Vector2D displaceVector) => new(circle.Center + displaceVector, circle.Radius);
public static Circle TransformCircle(ITransform transform, Circle circle)
=> new(transform.TransformVector2D(circle.Center), circle.Radius * transform.Scale.Magnitude);
public static bool ApproximatelyEquals(Circle left, Circle right) public static bool ApproximatelyEquals(Circle left, Circle right)
=> left.Center.ApproximatelyEquals(right.Center) && left.Radius.ApproximatelyEquals(right.Radius); => left.Center.ApproximatelyEquals(right.Center) && left.Radius.ApproximatelyEquals(right.Radius);
} }
public static class CircleExtensions public static class CircleExtensions
{ {
public static Circle SetCenter(this Circle circle, Vector2D center) => Circle.SetCenter(circle, center);
public static Circle SetRadius(this Circle circle, float radius) => Circle.SetRadius(circle, radius);
public static Circle Displace(this Circle circle, Vector2D displaceVector) => Circle.Displace(circle, displaceVector);
public static Circle TransformCircle(this ITransform transform, Circle circle) => TransformCircle(transform, circle);
public static bool ApproximatelyEquals(this Circle left, Circle right) => Circle.ApproximatelyEquals(left, right); public static bool ApproximatelyEquals(this Circle left, Circle right) => Circle.ApproximatelyEquals(left, right);
} }

View File

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Syntriax.Engine.Core; using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Physics2D.Primitives; namespace Syntriax.Engine.Physics2D.Primitives;
@ -51,6 +52,26 @@ public record Shape(IList<Vector2D> Vertices) : IEnumerable<Vector2D>
return lines; return lines;
} }
public static Shape TransformShape(Shape shape, ITransform transform)
{
List<Vector2D> vertices = new(shape.Vertices.Count);
int count = shape.Vertices.Count;
for (int i = 0; i < count; i++)
vertices.Add(transform.TransformVector2D(shape[i]));
return new Shape(vertices);
}
public static void TransformShape(Shape from, ITransform transform, ref Shape to)
{
to.Vertices.Clear();
int count = from.Vertices.Count;
for (int i = 0; i < count; i++)
to.Vertices.Add(transform.TransformVector2D(from[i]));
}
public static bool ApproximatelyEquals(Shape left, Shape right) public static bool ApproximatelyEquals(Shape left, Shape right)
{ {
if (left.Vertices.Count != right.Vertices.Count) if (left.Vertices.Count != right.Vertices.Count)
@ -73,5 +94,8 @@ public static class ShapeExtensions
public static void ToLines(this Shape shape, IList<Line> lines) => Shape.GetLines(shape, lines); public static void ToLines(this Shape shape, IList<Line> lines) => Shape.GetLines(shape, lines);
public static List<Line> ToLines(this Shape shape) => Shape.GetLines(shape); public static List<Line> ToLines(this Shape shape) => Shape.GetLines(shape);
public static Shape TransformShape(this ITransform transform, Shape shape) => Shape.TransformShape(shape, transform);
public static void TransformShape(this ITransform transform, Shape from, ref Shape to) => Shape.TransformShape(from, transform, ref to);
public static bool ApproximatelyEquals(this Shape left, Shape right) => Shape.ApproximatelyEquals(left, right); public static bool ApproximatelyEquals(this Shape left, Shape right) => Shape.ApproximatelyEquals(left, right);
} }

View File

@ -15,7 +15,8 @@ public class RigidBody2D : BehaviourOverride, IRigidBody2D
public Vector2D Velocity { get; set; } = Vector2D.Zero; public Vector2D Velocity { get; set; } = Vector2D.Zero;
public float AngularVelocity { get; set; } = 0f; public float AngularVelocity { get; set; } = 0f;
public float Mass { get; set; } = 0f; public float Mass { get; set; } = 1f;
public bool IsStatic { get; set; } = false;
ITransform IAssignableTransform.Transform => Transform; ITransform IAssignableTransform.Transform => Transform;