• 13
• 10
• 27
• 9
• 9

Vector transformation

This topic is 2413 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

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.

//pimms

Share on other sites
Compute the maximum of the absolute values of the coordinates and divide every coordinate by it. Is that what you wanted?

Share on other sites
i think you're looking for vector normalization to have a unit vector that is the direction? (the link is 3d, just remove any z from calculation and it's fine)

Share on other sites
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.

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 on other sites

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

Share on other sites
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 on other sites
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