Sign in to follow this  
GamerPuss

2D vector projection question

Recommended Posts

GamerPuss    100
Hi,

I'm currently playing around withe 2D vector graphics (using C# and XNA) for the first time, where I have two vertical walls (each backed by a Vector2D instance) and a projectile launcher in the middle. The launcher can launch a projectile in any direction at any angle. The main aim being to detect collision between a projectile (an arrow, backed by a Vector2D instance) and either wall, and then resolve the collision using a vector projection technique to modify the velocity vector of the projectile so that it bounces off the wall at the correct angle.

The collision detection, I've got working fine. It's the velocity vector calculations that don't seem to be working as planned. Here's my code for that part:

[font="Courier New"] Vector2 v1 = vectorProjectileVelocity;
Vector2 v2 = wall.VectorWall;
Vector2 v2Normal = new Vector2(v2.Y, -v2.X);
Vector2 v2Normalized = Vector2.Normalize(v2);

// dot product between movement vector (v1) and wall vector (v2)
float dp1 = Vector2.Dot(v1, v2);

// projection of movement vector onto wall
Vector2 proj1 = dp1 * v2Normalized;

// dot product between movement vector and wall normal
float dp2 = Vector2.Dot(v1, v2Normal);

// projection of movement vector on wall normal
Vector2 proj2 = dp2 * Vector2.Normalize(v2Normal);
proj2 *= -1;

Vector2 velocityNew = proj1 + proj2;
vectorProjectileVelocity = velocityNew;

[/font]This code is based on a tutorial I found: [url="http://www.tonypa.pri.ee/vectors/tut06.html"]Vector Tutorial[/url]

When I added some debug out in there I can see that velocityNew is completely wrong:
[font="Courier New"]v1 : {X:188.0582 Y:8.220284E-06}
v2 : {X:0 Y:400}
v2Normal : {X:400 Y:0}
v2Normalized : {X:0 Y:1}
dp1 : 0.003288114
proj1 : {X:0 Y:0.003288114}
dp2 : 75223.27
proj2 : {X:-75223.27 Y:0}
vectorProjectileVelocity: {X:188.0582 Y:8.220284E-06}
velocityNew: {X:-75223.27 Y:0.003288114}[/font]

Any ideas why this doesn't work? I know that there are other ways to achieve this, but this seems to be the easiest way to give me the option of applying friction and bounce.

Any help with this is much appreciated.

Cheers

GP

Share this post


Link to post
Share on other sites
RDragon1    1205
[color=#1C2837]
[color=#1C2837]What is this meant to calculate?[/color]
[color=#1C2837]
[/color]// dot product between movement vector and wall normal
float dp2 = Vector2.Dot(v1, v2Normal); [/color]
[color=#1C2837]
[/color]
[color=#1C2837]If you meant to project v1 onto v2Normal (I think you did), you should normalize v2Normal (which isn't normalized)[/color]

Share this post


Link to post
Share on other sites
GamerPuss    100
[quote name='rdragon1' timestamp='1310981102' post='4836735']
[color="#1c2837"]
[color="#1c2837"]What is this meant to calculate?[/color]
[color="#1c2837"]
[/color]// dot product between movement vector and wall normal
float dp2 = Vector2.Dot(v1, v2Normal); [/color]
[color="#1c2837"]
[/color]
[color="#1c2837"]If you meant to project v1 onto v2Normal (I think you did), you should normalize v2Normal (which isn't normalized)[/color]
[/quote]

Hi, thanks for the reply. To be honest, I'm new to this and have just tried to convert the flash code from the linked tutorial to C#. It's possible that I've made an error, but I've just had another look and it appears to be correct, so maybe the tutorial has a typo? Further down the code, this happens:

[font="Courier New"]// projection of movement vector on wall normal
Vector2 proj2 = dp2 * Vector2.Normalize(v2Normal); [/font]

I thought that that had the same effect? i.e. the dot prodoct is found between the two vecotors and then the projection if found my multiplying the dot product by the normalized vector.

Like I say, it's all new to me, so please correct me if I'm wrong.

Cheers

GP

Share this post


Link to post
Share on other sites
RDragon1    1205
It looks like v2Normal is meant to be a normal (of a wall?)

It probably should be normalized all the way up here:

[color=#1C2837]Vector2 v2Normal = new Vector2(v2.Y, -v2.X); [/color]
[color=#1C2837]
[/color]
[color=#1C2837]
[/color]
To answer your question, dot(A, B) * normalize(B) is not the same as dot(A, normalize(B)) * normalize(B) (assuming B wasn't normalized already) - verify this yourself by manually doing the math

Share this post


Link to post
Share on other sites
GamerPuss    100
[quote name='rdragon1' timestamp='1310990228' post='4836764']
It looks like v2Normal is meant to be a normal (of a wall?)

It probably should be normalized all the way up here:

[color="#1c2837"]Vector2 v2Normal = new Vector2(v2.Y, -v2.X); [/color]
[/quote]

Thanks for your help rdragon1, you were spot on. Here's some updated code which actually works, just in case someone else finds it useful.

[font="Courier New"] Vector2 v1 = vectorProjectileVelocity;
Vector2 v2 = wall.VectorWall;[/font]

[font="Courier New"] Vector2 v2NormalNormalized = Vector2.Normalize(new Vector2(v2.Y, -v2.X));
Vector2 v2Normalized = Vector2.Normalize(v2);[/font]

[font="Courier New"] // dot product between movement vector (v1) and normalized wall vector (v2)
// This gives us the length of v1 projected in the wall direction (x component)
float dp1 = Vector2.Dot(v2Normalized, v1);[/font]

[font="Courier New"] // Multiply dp by the normalized wall vector to get a new vector of the
// same length as the v1 but in the wall direction
Vector2 proj1 = dp1 * v2Normalized;

// dot product between movement vector (v1) and wall normal
// This gives us the length of v1 projected in the wall's normal direction (y component)
float dp2 = Vector2.Dot(v2NormalNormalized, v1);[/font]

[font="Courier New"] // Multiply dp by the normalized wall normal vector to get a new vector of the
// same length as the v1 but in the wall's normal direction
Vector2 proj2 = dp2 * v2NormalNormalized;

// Invert the projection on the normal
proj2 *= -1;

Vector2 velocityNew = proj1 + proj2;
vectorProjectileVelocity = velocityNew;


[/font]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this