Bug in Vector3f.angleBetween?

I had a look at the source code of com.jme.math.Vector3f and saw this code:



    public float angleBetween(Vector3f otherVector) {

        float dotProduct = dot(otherVector);

        float angle = FastMath.acos(dotProduct);

        return angle;

    }



Is this correct? I mean, shouldn't there be a division by the lengths of the two vectors after calculating the dot product?

I was just wondering why my code didn't work.

If I use the following it works:



float angle = FastMath.acos(dir.dot(dist) / (dist.length() * dir.length()));

my 3d math sucks :frowning:

thats why i tried to look it up and i think i found a nice site which explains it well.



http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

So acos(dot(v1,v2)) is valid, but only if both vectors are normalized, which normally won't be the case.



Otherwise you have to use:



acos(dot(v1,v2)/(len(v1)*len(v2)))



see for example Emma's Final Year Project

Well, it DOES say that in the method description as well:


angleBetween returns (in radians) the angle between two vectors.
It is assumed that both this vector and the given vector are unit vectors (iow, normalized).



And considering how easy it is to normalize a vector... perhaps you could explain to a math newb why this is a problem :) After all - the angle between the vectors does not depend on their length.

Oh sorry, I was so stupid that I forgot to read the manual :frowning:

Well, no… your question is valid of-course… Do you estimate that your way of calculating angles between non-normalized vectors is faster (enough to matter) than normalizing the said vectors and calculating the angle then? Because if it is, I'd like to know it - there might be cases where we do numerous vector calculations in a very short time and optimizing everything is the obsession of several nut-cases among us, including yours truly.

It should be faster because normalizing means to divide each component of each vector by the length of the vector, whereas "my" method (I didn't invent it :))

involves only a division of the dot product by the two lengths. So it is 6 divisions against 2.



I tried to make a benchmark but depending on the actual values, the results always seemee to differ. Very strange. It seems that dividing by 0.00002 is faster than by 10000.2.

Except with your way, there is no way to avoid the computation of the length, which is 2 additions and 3 multiplications per vector.



Let's say I am a programmer, and have 1 vector to test with 10 other vectors, the first thing I would do is normalize my vector once, and then normalize each other vector and call the angleBetween with these normalized vectors, even if it involves 33 divisions, 33 multiplications and 22 additions, it might be better than the 60 multiplications, 30 divisions and 40 additions. That of course leaves the choice to the user, and not to the library, which I think would be reasonable anyway.

Yes thats true. But maybe there is some need for another method "angleBetweenNonNormalized(Vector3f other)".

Or maybe not :slight_smile:



What I found interesting is the following:



public Vector3f divideLocal(float scalar) {

        scalar = 1f/scalar;

        x *= scalar;

        y *= scalar;

        z *= scalar;

        return this;

    }



I didn't know that floating point multiplication is faster than division.

It is absolutely incredible how people can optimize such simple things like normalize even further.

I just had a look into the "Bullet Continuous Collision Detection and Physics Library" and this is how they did it:



inline const Vector3 Normalize(const Vector3& a)

{

return RsqrtNr(Dot(a, a)) * a;

}



I don't know wheather this is really faster but it looks impressive and I do not understand it  XD

Most likely RsqrtNr stands for reciprocal of the square root of which, by the way, is the same as 1/(xx+yy+z*z)… so it is not much better at all.

Most of the resources of my game will probably go to waste due to an inefficient framework anyways, so I am not worried about vectors too much :slight_smile: