Skip to main content
gamedev.net
🔒 Locked

simple question about vector normalization

Started by speciesUnknown Aug 9, 2007 at 8:30 AM 8 replies 5.5k views
Original Post
speciesUnknown
speciesUnknown
HI, I feel like a bit of a noob. I need to know what the generally accepted procedure is for normalizing a zero length vector. My current function returns early if the vector is 0, like this:

	void normalize()
	{
		float length=get_length();
		if(length ==0)
			return;
		length /= 1;
		
		x *= length; 
		y *= length; 
		z *= length;
	};

Leaving the values set to 0. But, the vector is no longer of length 1, so its not really been normalized at all. I changed it to this when I realized I was getting divide by zero errors. I'm using one divide followed by 3 multiplies because thats faster than 3 divides. Should I just remove this optimization? Any advice would be appreciated.
Don't thank me, thank the moon's gravitation pull! Post in My Journal and help me to not procrastinate!
stevenmarky
stevenmarky
length /= 1;
This operation will have no affect on length.
I think you meant length=1/length.

Concerning the divide-by-zero; I checked my code and I realise I never check for this condition.
I guess I never try to normalise zero length vectors (is there ever a reason why you would want to?).

Perhaps I should assert(length!=0);
geolycosa
geolycosa
I don't think you can normalize a zero vector.
Will Miller | Game Designer | Big Huge Games
jpetrie
jpetrie
Normalization is impossible and meaningless for a zero-length vector.

I generally employ some kind of error trapping (such as asserts, exceptions, et cetera) when nonsense operations like this are attempted. I find "doing nothing" to be less than beneficial since it allows you to propagate around the source of the problem (which was probably bad math or bad algorithm design) quietly.
nmi
nmi
Mathematically a vector is normalized by dividing it through its length. Division by zero is undefined, so normalizing a zero-length vector is as well.

In practice you should investigate under which circumstances you are getting zero-length vectors. For instance when interpolating between two normal vectors that point into opposite directions you may end up with a zero-length vector that you want to normalize. In that particular example the problem is not that you are normalizing a zero vector, but that you are interpolating normal vectors pointing into opposite directions.

Putting in an assertion like steven suggested would be the way to go. Or you may just set the normalized vector to some arbitrary vector of length 1 (divide by zero now becomes a visual artifact instead).
speciesUnknown
speciesUnknown
Quote:

I guess I never try to normalize zero length vectors (is there ever a reason why you would want to?).


Anybody remember quake II, where if you went diagonally you moved faster than going just in X or Z direction? Same for quake I, doom, and a few others.
I create a vector from the x and z movement, and normalize it to prevent this. I think I'll create a new method for my vector class, since this is not standard behaviour.

These are my current steps:

First I fill a vector with the CONSCIOUS movements in the X and Z directions. There may not be any, therefore the entire algorythm is done with zero length vectors.

Then I multiply it by the speed the character is moving at.

I then multiply it by the y rotation matrix to make it face the direction the character is facing.

Then I add the environmental forces vector, which is the sum of things like gravity and wind.

The resultant vector becomes the overall translation the character goes through in one second. Then, I translate the character by this value.
movement.set_vector(x_movement,0,z_movement);movement.normalize(); movement *= character_speed;movement *= rotation_matrix;movement += environmental_forces;move(movement);

I came across this system after a lot of time spend thinking about it. Is it a little long winded?
Don't thank me, thank the moon's gravitation pull! Post in My Journal and help me to not procrastinate!
KOzymandias
KOzymandias
Maybe you should have 2 separate methods, one that checks only in debug (for vectors that should not be null, and the other when it can be).

I also use std::numeric_limits::epsilon() with this kind of tests... you probably dont want to normalize the vector V( 0.00000000001, 0, 0) either.

Another thing, you dont need to check with the length itself : use the square length instead, sqrt is time consuming.
speciesUnknown
speciesUnknown
If vectors are not allowed to be zero, I think Ill simply modify the algorithm to prevent strafe running.
Don't thank me, thank the moon's gravitation pull! Post in My Journal and help me to not procrastinate!
oliii
oliii
Non normalised vectors can turn your camera into a black hole :) We had a bug like that when a component of the camera became zero, and nuked the camera transform matrix.

Assert if zero. This is usually bad, but it can be acceptable in some cases. You can pass a bool as a parameter to perform the 0-length check.

Also, I usually return the length of the vector prior to normalisation, it can be useful to have around (i.e. converting vector into a direction-length object for ray-tracing).

float Vector::Normalise(bool assertIfZero=true, const float epsilon=(1.0E-8f)){    float length = Length();    if(length < epsilon)    {        if(assertIfZero)             assert(false);        *this = Vector(0, 0, 0);        return 0.0f;    }    *this /= length;    return length;    }
Everything is better with Metal.
speciesUnknown
speciesUnknown
What it think ill do, then, is cut the normalization step out of the algorithm i listed above, then do a test to see if the character is walking in the x and z directions. If not, ill skip adding the x and z movement components to the vector, and ill skip the normalization.
My camera has an internal vector format, since I wrote it long before i had a vector class. Now might be the time to remove this redundancy.
I cant think of any other situations where a vector should equal 0,0,0, so ill throw an exception if the vector is 0,0,0 when its normalized.

Thanks for your advice.
Don't thank me, thank the moon's gravitation pull! Post in My Journal and help me to not procrastinate!

Topic Locked

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

Sign in to reply to this topic.