advanced 3 vector collision

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
eyad
Posts: 42
Joined: December 5th, 2014, 9:34 am

advanced 3 vector collision

Post by eyad » July 7th, 2019, 12:08 pm

in advanced 3 (new series) when testing the circle collision with the "plank" i did the same code as chili but the distance (between point and line) gives different results than what chili does. i can't figure out why....

collision code found in Ball.h in functions
bool IsCollidingWithLine(const Vec2& p0, const Vec2& p1) const
and
void ProcessCollision(const Vec2& wall, const Vec2& p0, const Vec2& p1)

here is my code (branch "Advanced3")
https://github.com/xEyad/advmath/tree/Advanced3

thanks in advance for the help.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: advanced 3 vector collision

Post by albinopapa » July 8th, 2019, 9:07 am

There is a disconnect between the physics and the graphics. I can't seem to find the disconnect though. Also, there is an error in the way you are getting the wall normal. The normal of the plank should be facing away from the plank surface back toward the ball spawn point. The way you have it now, it's pointing from free -> anchor. To rotate the normal by 90 degrees, you an swap the X and Y components and negate the resulting X or Y.
Vec2 normal = Vec2{-(anchor.y - free.y), (anchor.x - free.x ) }.GetNormalized();
or
Vec2 normal = Vec2{(anchor.y - free.y), -(anchor.x - free.x ) }.GetNormalized();
Since you are working in a coordinate system with +Y is UP, the first one rotates anti-clockwise and the second one rotates clockwise if I remember correctly.

Here's the reflection formula for reference:
d - n * ( dot_product( n, d ) * 2.f )
d = vel
n = normal

With _Vec2::operator* overloaded, you could do

Code: Select all

// Variable named right because the current vector points to the right
auto const right = wall.GetNormalized();
auto const normal = Vec2( right.y, -right.x );
vel -= normal * ( ( normal * vel ) * 2.f ) )
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: advanced 3 vector collision

Post by albinopapa » July 12th, 2019, 3:12 am

Ok, so after a little bit of playing around I think I have an answer for you.

The vertices of the plank you generate each time you move the free side, and you base it on the free side's new position. Then you do your transformations on the vertices even though they have already been transformed when you create the new model. Basically, the vertices are being translated twice. The vertices should be offsets from the position, which makes things difficult because you based your position from the middle of the plank and this position doesn't move when the free side moves.

For the collision, you base the collision off of the free and anchor relation, but for drawing, you are basing the translation from the Entity::pos vector and the vertices are based on the free and anchor positions.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: advanced 3 vector collision

Post by albinopapa » July 12th, 2019, 6:53 am

Figured out a way to use a skew matrix to draw the plank and have the collisions work using the free and anchor points.

Code: Select all

	Drawable GetDrawable()const override
	{
		auto d = Drawable( GetModel(), GetColor() );
		d.GetTransform() =
			Mat3f::SkewY( ( anchor.y - free.y ) / length )*
			Mat3f::Scale( GetScale(), GetScale() ) *
			Mat3f::Translate( GetPos() );
		return d;
	}

Code: Select all

	static constexpr Matrix SkewY( T skew )noexcept
	{
		constexpr auto zero = T( 0 );
		constexpr auto one = T( 1 );
		return{
			 one, skew, zero,
			zero,   one, zero,
			zero,  zero, one
		};
	}

Code: Select all

	bool Ball::IsCollidingWithLine(const Vec2& p0, const Vec2& p1) const
	{
		auto sq = []( float a )constexpr { return a * a; };
		
		auto const& q = GetPos();
		auto u = q - p0;
		auto v = ( p1 - p0 ).Normalize();
		auto t = dot_product( u, n );
		auto p = p0 + ( v * t );
		auto distSq = ( q - p ).LenSq();
		auto radSq = sq( radius );
		return distSq <= radSq;
	}
	void Ball::ProcessCollision(const Vec2& wall, const Vec2& p0, const Vec2& p1)
	{
		if( IsCollidingWithLine( p0, p1 ) )
		{
			auto const normal = Vec2( wall.y, -wall.x ).Normalize();
			vel = reflect( normal, vel );
		}
	}

Code: Select all

constexpr Vec2 reflect( Vec2 const& n, Vec2 const& d )noexcept
{
	return d - n * ( dot_product( n, d ) * 2.f );
}
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply