4 * Created on: Apr 25, 2012
10 #include "../app/Timer.h"
11 #include "../geometry/constants.h"
16 using std::numeric_limits;
21 void Entity::Update(const app::Timer &timer) {
22 translation += linearVelocity * timer.DeltaT();
23 rotation += angularVelocity * timer.DeltaT();
24 if (rotation > 2.0 * PI) {
26 } else if (rotation < -(2.0 * PI)) {
29 shape->Translate(linearVelocity * timer.DeltaT());
30 shape->Rotate(angularVelocity * timer.DeltaT());
33 bool Entity::CheckCollision(const Entity &other, Ray &ray) {
34 return shape->CheckCollision(*other.shape, ray);
38 Entity::Vector Entity::VelocityAt(const Vector &p) const {
39 if (angularVelocity == 0 || p == translation) return linearVelocity;
41 Vector v(linearVelocity);
42 Vector pRelative(p - translation);
43 v += pRelative.Rotate90() * angularVelocity;
48 void Entity::Rotate(Scalar d) {
53 void Entity::Translate(const Vector &d) {
58 void Entity::Accelerate(const Vector &dvl, Scalar dva) {
59 linearVelocity += dvl;
60 angularVelocity += dva;
64 void Entity::CollisionResponse(Entity &a, const Ray &na, Entity &b) {
65 if (a.mass == numeric_limits<Scalar>::infinity()
66 && b.mass == numeric_limits<Scalar>::infinity()) {
67 // special case: collision of two infinitely heavy entities
68 InfInfCollisionResponse(a, na, b);
74 const Vector normal(na.Direction());
76 const Vector va(a.LinearVelocity());
77 const Vector vb(b.LinearVelocity());
78 const Scalar wa(a.AngularVelocity());
79 const Scalar wb(b.AngularVelocity());
81 const Vector vap(a.VelocityAt(na.Origin()));
82 const Vector vbp(b.VelocityAt(na.Origin()));
83 const Vector vab = vap - vbp;
85 const Vector restitutionVAB((-(1 + e)) * vab);
87 const Vector rap90((na.Origin() - a.Origin()).Rotate90());
88 const Vector rbp90((na.Origin() - b.Origin()).Rotate90());
90 const Scalar ia(a.Mass()); // inertia equals mass? probably not
91 const Scalar ib(b.Mass());
93 const Scalar aInverseMass(1.0 / a.Mass());
94 const Scalar bInverseMass(1.0 / b.Mass());
96 const Scalar rap90dotN(rap90.Dot(na.Direction()));
97 const Scalar rbp90dotN(rbp90.Dot(na.Direction()));
99 const Scalar aRotationalPart((rap90dotN * rap90dotN) / ia);
100 const Scalar bRotationalPart((rbp90dotN * rbp90dotN) / ib);
103 restitutionVAB.Dot(normal)
104 / (normal.Dot(normal * (aInverseMass + bInverseMass))
106 + bRotationalPart ));
108 const Vector va2(va + (j / a.Mass()) * normal);
109 const Vector vb2(vb - (j / b.Mass()) * normal);
110 const Scalar wa2(wa + rap90.Dot(j * normal) / ia);
111 const Scalar wb2(wb - rbp90.Dot(j * normal) / ib);
113 a.linearVelocity = va2;
114 a.angularVelocity = wa2;
115 b.linearVelocity = vb2;
116 b.angularVelocity = wb2;
119 void Entity::InfInfCollisionResponse(Entity &a, const Ray &na, Entity &b) {
120 // If both elements are standing still or both are moving, move them away
121 // from each other. Otherwise, move the moving one.
122 // This will keep the paddle from bouncing off the wall at infinite velocity.
123 if ((a.linearVelocity == Vector() && b.linearVelocity == Vector())
124 || (a.linearVelocity != Vector() && b.linearVelocity != Vector())) {
125 a.Translate(na.Direction());
126 b.Translate(-na.Direction());
128 while (a.shape->CheckCollision(*b.shape, n)) {
129 a.Translate(n.Direction());
130 b.Translate(-n.Direction());
132 } else if (a.linearVelocity == Vector()) {
133 b.Translate(-na.Direction());
135 while (b.shape->CheckCollision(*a.shape, n)) {
136 b.Translate(n.Direction());
139 a.Translate(na.Direction());
141 while (a.shape->CheckCollision(*b.shape, n)) {
142 a.Translate(n.Direction());