Sign in to follow this  
JoakimNordstrandStien

Vector transformation

Recommended Posts

Greetings, GameDev community!

I'm currently working with Box2D, and I'm implementing an explosion-effect.

Therefore, I'm in need of a direction vector to be multiplied by the force (which is based on distance).

In order to make it appear as seamless as possile, I need to first transform the vector so that the highest value of the vector is 1. Let me show you;

A vector of (15, 10) would be (1, 6.67). As would a vector (30,15) be (1, 0.5).

Has anyone done this before and have a code snippet to share? The general theory / principle behind it would be sufficient as well.

Thanks in advance :)

//pimms

Share this post


Link to post
Share on other sites
Hassanbasil    195
i think you're looking for [url="http://www.fundza.com/vectors/normalize/index.html"]vector normalization[/url] to have a unit vector that is the direction? (the link is 3d, just remove any z from calculation and it's fine)

Share this post


Link to post
Share on other sites
Thanks for the quick replies, guys. Appreciate it a lot :)

[b]@alvaro[/b]
I'm not 100% sure of what you mean - what I've tried (without much success) is to first find the ratio between X and Y, based on the highest value.

If the highest value is > 1.0, I divide X and Y by the highest value. This produces some funny results, though.

If the highest value is < 1.0, I find the ratio by dividing 1 by the highest. Then X and Y is divided by ratio.

The current (faulty) code:
[source]
if ( vector.x > vector.y ) {
for (;;) {
if ( high < 1.0f ) {
ratio = 1.f / high;
x = high * ratio;
y = low * ratio;
break;
}
if ( high > 1.0f ) {
ratio = high / high;
x = high / ratio;
y = low / ratio;
break;
}
}
}
[/source]


[b]@Hassanbasil[/b]
I've looked into normalizing the vector, but that would be quite the workaround for me, as I'm calculating the force to be applied as so;

[source]
body->ApplyForce( (hitVector*distance)*force, body->GetWorldCenter() );
[/source]

Where hitVector is the vector I'm trying to calculate.

Share this post


Link to post
Share on other sites
I came up with something that works somewhat decent, thought I'd share it as it might be of help to someone out there :) It's messy as shit, and could use a rewrite, but I'm satisfied considering it's 2:45 AM.

As mentioned, this function returns a vector scaled down to 1.

[source]
inline b2Vec2 scaleVecTo1( b2Vec2 vector ) {
//flag for reversing them to negative before return
bool invX=NO, invY=NO;

float x=0.f, y=0.f;
float ratio;

invX = vector.x < 0.f ? YES : NO;
invY = vector.y < 0.f ? YES : NO;
vector.x *= vector.x < 0.f ? -1.f : 1.f;
vector.y *= vector.y < 0.f ? -1.f : 1.f;

if ( vector.x > vector.y ) {
for (;;) {
if ( vector.x < 1.0f ) {
ratio = 1.f / vector.x;
x = vector.x * ratio;
y = vector.y * ratio;
break;
}
if ( vector.x > 1.0f ) {
ratio = vector.x / vector.x;
x = vector.x / ratio;
y = vector.y / ratio;
break;
}
}
}

if ( vector.x <= vector.y ) {
for (;;) {
if ( vector.y < 1.0f ) {
ratio = 1.f / vector.y;
y = vector.y * ratio;
x = vector.x * ratio;
break;
}
if ( vector.y > 1.0f ) {
ratio = vector.y / vector.y;
y = vector.y / ratio;
x = vector.x / ratio;
break;
}
}
}

x *= invX ? -1.f : 1.f;
y *= invY ? -1.f : 1.f;

return b2Vec2(x,y);
}
[/source]

Share this post


Link to post
Share on other sites
alvaro    21246
[quote name='Admiral Pimms' timestamp='1312850112' post='4846456']
[b]@alvaro[/b]
I'm not 100% sure of what you mean - what I've tried (without much success) is to first find the ratio between X and Y, based on the highest value.
[/quote]


I mean this:
[code]inline b2Vec2 scaleVecTo1( b2Vec2 vector ) {
float m = std::max(std::abs(vector.x), std::abs(vector.y));
return b2Vec(vector.x/m, vector.y/m);
}
[/code]

[font="Consolas,"] [/font]

Share this post


Link to post
Share on other sites
Hassanbasil    195
alvaro's method is just what you're asking for - but what you're asking for doesn't seem to be the right way to do it, normalizing the vector and making it a unit vector is actually what looks suitable in your case, since it has the length of 1 (hence the name unit vector)

let's assume you have the vector (5,10), your desired method will make it (0.5,1), now calculate the length of it: sqrt(0.5*0.5+1*1) = sqrt(1.25) != 1
now the normalization method: sqrt((5 / sqrt(5 * 5 + 10 * 10))^2 + (10 / sqrt(5 * 5 + 10 * 10))^2) = 1

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