Link to home
Start Free TrialLog in
Avatar of DanMacDonald
DanMacDonald

asked on

How to find the angle between two vectors without using acos() (J2ME)

I'm doing some J2ME programming using JSR 184. One of the things lacking from the CLDC 1.1 spec is any of the inverse trig functions. Does anyone have any suggestions for finding the angle between two vectors not using the inverse trig functions?
ASKER CERTIFIED SOLUTION
Avatar of ozo
ozo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of DanMacDonald
DanMacDonald

ASKER

I want to find the angle between two vectors so that I can rotate a billboard about the Y axis to face the camera.  So I  find the angle between the camera vector and a vector lieing on horizontal X axis (rotation about the Y axis = 0) and from that I can figure out what angle of rotation to apply to my billboard. I ended up doing a acos( ) lookup table, generating it in VC. It worked quite nicely.

The reason I dont use an inverse trig function is that J2ME does not have inverse trig functions. :)
I wonder how J2ME can do camera rotations without trig functions.
A lookup table certainly works, otherwise, I supose you could take an approximate function, rotate it, then check dot product again to refine the approximation until you were close enough.
Or can you just directly take the transform from vector a to vector b and apply that transform to the rest of the billboard?
A C grade is usually given only after expressing your reasons for your dissatisfaction with the answer given, and after the experts have been given ample time to address the issues you raise in your complaint.
http:/help.jsp#hi73
You didn't even give me enough time to see your response to my questions to try to clarify your need.

Since you're trying to rotate by an angle, and a 2-D rotation matrix looks like
 cos(r)  sin(r)
-sin(r)  cos(r)
if you know cos(r), you need not find r in order to generate the rotation matrix
you need only know that sin(r)² + cos(r)² = 1
I work with a number of different 3D API's for J2ME. Not all the devices are CLDC 1.1  and so most of my calculations are in FixedPoint math. At first I implemented billboarding the traditional way by creating a transformation matrix that oriented the billboard verticies to face the camera. However due to the number of intermediate operations involved in creating a new coordinate system and using those vectors to build a transformation matrix a lot of little precision errors along the way amounted to unacceptable visual artifacts.

Since the game I am working on is basically an FPS where the players camera is always a fixed elevation. I found it was simpler to just take the 2d Rotation formulas and rotate the points of the billboard in object space about it's Y axis. With far fewer operations it was much easier to keep track of precision and it produced much fewer artifacts.  To get the angle of rotation required, I would find the vector that was 0 degrees rotation about the billboards location, and then find the vector between the billboard location and the camera. Finding the angle between these two vectors would tell me how much to rotate the billboard to ensure it always faced the camera.
The graphics library I had been using previously implemented an acos( ) function. However when switching to JSR 184 I lost the acos function and needed a way to port my code. It turns out that JRS 184 has a "setOrientation ( )" function for mesh's that takes an angle of rotation. So I don't have to manually rotate the billboard verticies myself.  I'm familiar with the rotation equations, and the definition of the dot product, the answer I wanted was exactly what I asked.

The answer you supplied was exactly what I knew, how to get the cosine of the angle between two vectors, what I needed to know was how to convert that into an angle that I could use.  Your last comment is much closer to a solution

sin(r) = sqrt(1-cos(r)2) would have helped me build the 2d rotations I needed. Which is a good idea, but having the angle of rotation and supplying it to setOrientation works even better.

What you asked for
finding the angle between two vectors not using the inverse trig functions
is impossible since any method for finding the angle between two vectors would be an inverse trig function.
It is not the fault of the answerer when the answer to a question is impossible.
If what you really wanted were ways to compute an inverse cosine function
then you could have gotten answers like using a lookup table, or
arccos(y) = arctan(sqrt(1-y²)/y)
and arctan(y) is approximately y/(1+.28y²) for -1<=y<=1
and arctan(y) = pi/2 - arctan(1/y) for y < -1 or y > 1
or arccos(y) is approximately sqrt(1-y)*(1.5707288-0.212114*y+0.0742610*y²-0.0187293*y³)
or sometimes languages have an atan2 function where arctan(y/x) = atan2(y,x)
but I had no idea whether you already knew any of that or whether any of that would address your real needs.
You can also get the sin of the angle between two vectors, with appropriate sign, from the cross product, if you want to use it in a rotation matrix or in an arctangent function.
Subsequently you've done a great job of answering the question. I would change the grade if I could... I know the moderators dislike questions being left open. Since I had found a workable solution I wanted to close the question and move on as I would not be needing any subsequent answeres. I didn't realize that an average grade was such a large issue, I was under the impression that points where the primary metric.
There is a Maclaurin series expansion for the arc cos that will give you the answer to any desired degree of precision.  See

http://mathworld.wolfram.com/InverseCosine.html
  and
http://mathworld.wolfram.com/MaclaurinSeries.html

It's trivial to implement this as a function you can call.

(I didn't post the equation directly because it's a bit ugly without typesetting. )

Hope this helps.