-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPhysics.cs
103 lines (83 loc) · 3.86 KB
/
Physics.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using System;
using System.Diagnostics;
namespace SharpEngine
{
public class Physics
{
readonly Scene scene;
public Physics(Scene scene)
{
this.scene = scene;
}
public void Update(float deltaTime)
{
var gravitationalAcceleration = Vector.Down * 9.819649f * 0;
for (int i = 0; i < this.scene.shapes.Count; i++)
{
Circle shape = this.scene.shapes[i] as Circle;
// linear velocity:
shape.Transform.Position = shape.Transform.Position + shape.velocity * deltaTime;
// a = F/m (another version ∏of F = ma)
var acceleration = shape.linearForce * shape.MassInverse;
// add gravity to acceleration
acceleration += gravitationalAcceleration * shape.gravityScale;
// linear acceleration:
shape.Transform.Position = shape.Transform.Position + acceleration * deltaTime * deltaTime / 2;
shape.velocity = shape.velocity + acceleration * deltaTime;
// collision detection:
for (int j = i + 1; j < this.scene.shapes.Count; j++)
{
Circle other = this.scene.shapes[j] as Circle;
// check for collision
Vector deltaPosition = other.GetCenter() - shape.GetCenter();
bool collision = deltaPosition.GetSquareMagnitude() <= (shape.Radius + other.Radius) * (shape.Radius + other.Radius);
if (collision)
{
Vector collisionNormal = deltaPosition.Normalize();
Vector shapeVelocity = Vector.Dot(shape.velocity, collisionNormal) * collisionNormal;
Vector otherVelocity = Vector.Dot(other.velocity, collisionNormal) * collisionNormal;
float totalMass = other.Mass + shape.Mass;
Vector velocityChange = 2 * other.Mass / totalMass * (otherVelocity - shapeVelocity);
Vector otherVelocityChange = 2 * shape.Mass / totalMass * (shapeVelocity - otherVelocity); //-shape.Mass / other.Mass * velocityChange;
AssertPhysicalCorrectness(shape.Mass, shape.velocity, other.Mass, other.velocity, shape.Mass, shape.velocity + velocityChange, other.Mass, other.velocity + otherVelocityChange);
shape.velocity += velocityChange;
other.velocity += otherVelocityChange;
}
}
}
}
static Vector CalculateTotalMomentum(float m1, Vector v1, float m2, Vector v2)
{
return CalculateMomentum(m1, v1) + CalculateMomentum(m2, v2);
}
static Vector CalculateMomentum(float mass, Vector velocity)
{
return mass * velocity;
}
static float CalculateTotalKineticEnergy(float m1, Vector v1, float m2, Vector v2)
{
return CalculateKineticEnergy(m1, v1) + CalculateKineticEnergy(m2, v2);
}
static float CalculateKineticEnergy(float mass, Vector velocity)
{
return 0.5f * mass * velocity.GetSquareMagnitude();
}
static void AssertPhysicalCorrectness(float m1, Vector v1, float m2, Vector v2, float m1_, Vector v1_, float m2_, Vector v2_, float tolerance = 0.00001f)
{
AssertPreservationOfMomentum(m1, v1, m2, v2, m1_, v1_, m2_, v2_);
AssertPreservationOfKineticEnergy(m1, v1, m2, v2, m1_, v1_, m2_, v2_);
}
static void AssertPreservationOfKineticEnergy(float m1, Vector v1, float m2, Vector v2, float m1_, Vector v1_, float m2_, Vector v2_, float tolerance = 0.00001f)
{
float oldTotalKineticEnergy = CalculateTotalKineticEnergy(m1, v1, m2, v2);
float newTotalKineticEnergy = CalculateTotalKineticEnergy(m1_, v1_, m2_, v2_);
Debug.Assert(MathF.Abs(oldTotalKineticEnergy - newTotalKineticEnergy) < tolerance, $"Kinetic energy was not preserved. Old: {oldTotalKineticEnergy} New: {newTotalKineticEnergy}");
}
static void AssertPreservationOfMomentum(float m1, Vector v1, float m2, Vector v2, float m1_, Vector v1_, float m2_, Vector v2_, float tolerance = 0.00001f)
{
Vector oldMomentum = CalculateTotalMomentum(m1, v1, m2, v2);
Vector newMomentum = CalculateTotalMomentum(m1_, v1_, m2_, v2_);
Debug.Assert((oldMomentum - newMomentum).GetMagnitude() < tolerance, $"Momentum was not preserved. Old: {oldMomentum} New: {newMomentum}");
}
}
}