Game Math 101: Changing the magnitude of a vector?
I find myself needing to change the magnitude of a vector quite often, and end up writing a lot of code that looks like:
v1 =Vector2.Multiply(Vector2.Normalize(v2), 250.0F);
Is there a better way? That just seems awfully inefficient.
It only gets worse when I want a particular magnitude vector in the opposite direction:
v1 =Vector2.Multiply(Vector2.Normalize(Vector2.Negate(v2)), 250.0F);
Or inverting the Y-axis of the thumbsticks:
acceleration =Vector2.Multiply(Vector2.Normalize(Vector2.Multiply(gpt.Left,newVector2(1, -1))), 800.0F);
Please, help a noob out...
Matt
[1342 byte] By [
MattStum] at [2007-12-24]
Well I'm not quite sure what exactly you are doing but I'll add a few notes.
If your vector isn't changing often, you can cache off the normal instead of calculating it. You should also be able to just do:
v1 = Vector2.Normalize(v2) * 250.0f;
Which is the same thing but not quite as verbose and arguably easier to read.
As for negating, just multiply by -250.0f and don't bother calling Negate().
To change a Vector V's magnitude to M:
Vector2 V = SomeNonZeroVectorValue();
V = V * M / V.Length();
of
V *= M / V.Length();
Makes no difference if M is positive or negative.
for instance:
Vector2 myVector = new Vector(33, 12);
myVector *= 250 / V.Length();
Inverting the Y axis should just be:
myVector.Y = -myVector.Y;
This makes it confusing to some begginners I imagine. Where is there a need for the ugly methods when there are operators there?
private float m_V1Normalized;
public float m_V1;
public float m_V2;
public float m_V3;
Constructor()
{
m_V1Normailzed = m_V1 / m_V1.Length();
}
void SomeMethod()
{
m_V2 = m_V1Normalized * 100.0f;
m_V3 = m_V1Normalized * 250.0f;
...
}
Why do you need to do this? Why don't you just see it as a direction? In that case you should only need to normalize it once. Then you scale the vector with your speed.
Kris Nye wrote: |
| To change a Vector V's magnitude to M: Vector2 V = SomeNonZeroVectorValue(); V = V * M / V.Length(); of V *= M / V.Length(); Makes no difference if M is positive or negative. for instance: Vector2 myVector = new Vector(33, 12); myVector *= 250 / V.Length(); Inverting the Y axis should just be: myVector.Y = -myVector.Y; |
|
While this is syntactically easier to type, it's essentially performing the same operations. So is it any more or less effecient than calling the static methods?
Kris Nye wrote: |
| Inverting the Y axis should just be: myVector.Y = -myVector.Y; |
|
Oh, I forgot to comment on this part. I understand that, but I can't change the Y value of the thumbstick vector... it's read-only. So, which is more efficient? Copy it to a temp variable and then assign the Y value to -Y and then use the temp variable in the calculation, OR use the thumbstick vector in-line and multiply it by "new Vector2(1,-1)" per my original example?
exal is correct, it dawned on me later: Keep your direction and speed seperate, then multiply them when you need your movement vector.
float speed;
Vector2 direction; //Should always be a unit vector (already normalized).
As you turn, update direction. When you need to move, multiply speed and direction into a new variable.
Vector2 delta = direction * speed;
I'm not familiar with the thumbpad but it looks like you are treating it like a Vector? If so, multiplying it by another vector won't return a vector. Possibly the easiest thing to do is just copy the value off into another vector then invert that Y.
Unless you've profiled your application and these vector operations are actually taking up a significant portion of your time, then you really shouldn't worry about minor optimizations to their performance. You should be using whatever code is the simplest and easiest to read.
There are some issues with the XNA Math libraries performing slower than they should (and they still haven't really commented on it), since they pass everything by value, but these won't really have an affect on you unless you are performing thousands of them in your inner loops.
Sound's like you are just flipping vectors when objects collide. Not really a place where improving the performance much is going to help you... unless you have 10000+ collisions per frame.
If though, you ever REALLY need maximum performance from a vector operation then write a static method that takes a vector parameter by reference, and just modify it there with your own optimized code. (Like I said, not worth the effort unless this is in an inner loop.)
// this will reverse the vectors magnitude more efficiently than any built in methods,
// and will probably be inlined by the compiler, but who cares?
public static void ReverseMagnitude(ref Vector3 v)
{
v.x = -v.x;
v.y = -v.y;
v.z = -v.z;
}