Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

Vector transformation

Started by JoakimNordstrandStien Aug 8, 2011 at 11:37 PM 6 replies 1.4k views
Original Post
JoakimNordstrandStien
JoakimNordstrandStien
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
alvaro
alvaro
Compute the maximum of the absolute values of the coordinates and divide every coordinate by it. Is that what you wanted?
JoakimNordstrandStien
JoakimNordstrandStien
Thanks for the quick replies, guys. Appreciate it a lot

@alvaro
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]


@Hassanbasil
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.
JoakimNordstrandStien
JoakimNordstrandStien
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]
alvaro
alvaro

@alvaro
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.



I mean this:
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);
}


[font="Consolas,"] [/font]
Hassanbasil
Hassanbasil
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
JoakimNordstrandStien
JoakimNordstrandStien
Thanks again for your replies -

As it turned out, a Normalized vector is in fact what I was looking for to begin with. Thank you for putting up with my ridiculously bad math knowledge.

//Pimms

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.