Math - resolving a elastic 2D collision

What it says on the tin. I detect the collision with the SAT, and while I'm doing that I also calculate a projection vector and the normal of the surface the collision took place on. I project my object then out of the collision.

By the way - this isn't supposed to be physically correct. I am assuming only one movable object and a bunch of static ones right now (this is for an arkanoid clone).

To get the bounce, I then calculate a vector perpendicular (clockwise) to the normal vector -let's call the normal n, the perpendicular vector p, and the velocity vector v - and then calculate the new velocity vector v like this:
u[1] = -v.n
u[2] = v.p

I don't quite get the results I expected though:

if the normal is {-1,0}, {0,1} or {0,-1} u[1] is always positive. I am testing this with AABB's right now, that's why the normals are like that.

My code for the collision resolution is here:
1
2
3
4
5
6
7
8
9
10
11
Intersection in = this->boundingBox.intersectsWith(*it);
		if(in.intersects)
		{
			this->boundingBox.move(in.projection);
			Vector2D p = in.normal.getNormalCW();
			float horizontalFactor = -Vector2D::dot(this->speed, in.normal);
			float verticalFactor = Vector2D::dot(this->speed, p);
			this->speed = Vector2D{horizontalFactor,
			                       verticalFactor};

		}


should anyone need it I can also upload my full project.

I hope someone can help me with this, to be honest my math skills aren't exactly up to shape right now and this is really driving me nuts.
Last edited on
I don't understand your math...
Shouldn't you reflect with respect to the line spanned by the normal p vector?
Something like, [Edit:] oops I confused n and p, now it should be fine:
v= v- 2((v.p)/(p.p))p,
v= v- 2((v.n)/(n.n))n,
where a.b denotes the scalar product, i.e., in your notation, Vector2D::dot(a, b)

In more detail
1
2
v[0]=v[0] -2* (v[0]*n[0]+v[1]*n[1])/(n[0]*n[0]+n[1]*n[1])*n[0]
v[1]=v[1] -2 *(v[0]*n[0]+v[1]*n[1])/(n[0]*n[0]+n[1]*n[1])*n[1]


?

If your vector n has length one, then you don't need to divide.


Maybe code like this:
1
2
3
4
/*...*/
float changeFactorAlongN=2*Vector2D::dot(this->speed, in.normal)/Vector2D::dot(in.normal,in.normal);
Vector2D speedChangeAlongN=in.normal*changeFactorAlongN;
this->speed-= speedChangeAlongN;

[Edit]: I have assumed common-sense operator overloading with common-sense semantics (this is a very wrong assumption if you are working, for example, with wxWidgets, so it should be made with caution).
Last edited on
I have the following operators available for Vector2D:
1
2
3
4
5
6
7
8
9
10
Vector2D operator*(float);
Vector2D operator/(float);
Vector2D operator+(const Vector2D&);
Vector2D operator-(const Vector2D&);
Vector2D operator+=(const Vector2D&);
Vector2D operator-=(const Vector2D&);
Vector2D& operator*=(float);
Vector2D& operator/=(float);
Vector2D operator-();
Vector2D& operator=(const Vector2D&);


I have written the vector class myself and tried to stay as close to common-sense math as possible with it. I decided to use a static method instead of operator* for the dot product cause it would get confusing next to the float overload, and since I want to expand this utility to 3D where I would also have to provide a method for the cross product it would get even more confusing.

Intersection::normal is guaranteed to be normalized btw - except if Intersection::intersects is false.

EDIT: Your solution works like a charm. You're a life saver ^-^
Last edited on
Topic archived. No new replies allowed.