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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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 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
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
ASKER
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.
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.212 114*y+0.07 42610*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.
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.212
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.
ASKER
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.
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.
ASKER
The reason I dont use an inverse trig function is that J2ME does not have inverse trig functions. :)