Advertisement

Trig functions and lookup tables

Started by April 11, 2000 12:58 PM
18 comments, last by MENTAL 24 years, 8 months ago
I have found a document on gamedev.net about lookup tables. I have decided to use one for calculating the angles of a circle (360 in my lookup table). The code goes like this: float LookUpCircleCos[360]; float LookUpCircleSin[360]; void InitLookUpCircle(void) { int Degrees; for(Drgrees = 0; Degrees < 360; Degrees++) { LookUpCircleSin = sin(rad(Degrees)); LookUpCircleCos = cos(rad(Degrees)); } } this is basically the original pascal code put into c. now, i have 2 problems. 1st: which header file has the "rad" function (couldn''t see it in math.h), and second of all, how the hell do i use it! I know how to use arrays, but i dont know how to apply the numbers to my data. example: 1 2 o o <-this o should be a further down, not possible in ascii // o c how do i get point1 to transform to point2 (c is the center of rotation)? any help appreciated MENTAL
well, first, you need to access the correct index into the table in your table generation:

LookUpCircleSin[Degrees] = ...

but there is no "rad" function (that i know of). to convert from degrees to radians multiply degrees by (pi/180).

now to apply, just plug your angle into lookup table:

where c = {x,y} center point
and o = {x,y} object point
where LengthOfRotationArm is the distance from object point to center point

o.x = (LookUpCircleCos[deg] * LengthOfRotationArm) + c.x
o.y = (LookUpCircleSin[deg] * LengthOfRotationArm) + c.y

those should be the correct transformations.


crazy166
some people think i'm crazy, some people know it
Advertisement
Probably a little something like this.

There is no degrees to radians converter function in C,
you have to make it yourself - most programmers use either a #define or an inline function, such as:
#define DEG2RAD(a) (a*M_PI) / 180.0f

thats basically what''s in Quake 1, where M_PI is your own definition of PI. Then you just call it DEG2RAD(angle)
so the trg function becomes:
sin(DEG2RAD(degrees));

Right, now I see a couple of obvious mistakes in your code,
when you go
LookUpCircleSin = sin(rad(Degrees));
it should be,
LookUpCircleSin[Degrees] = sin(DEG2RAD(Degrees));
that will put the correct angle in the correct element
of the array.
So, once you''ve created these lookup tables, instead of
calling sin(DEG2RAD(angle)); everytime you need an angle
computed, you just go LookUpCircleSin[angle];
a lot faster, I think.

Hope some of that rambling helped.

-Mezz
also, just because there are 360 degrees in a circle, doesn''t mean you can''t use 1000 sin and cos values around the circle. using 720 values in table would give you half degree precision.
this can be noticeable as the object gets far from center point and movement between degrees gets choppy.

to calc these values just:
for ( x < 1000 )
lookupsin[x] = sin( (6.28 / 1000)*x )


then your circular movement is much smoother as you go from 1 to 1000.


crazy166
some people think i'm crazy, some people know it
I think look up tables are not what you should be implementing here. The problem is you are trying to perform a 2d rotation, look up tables will not answer problems..

A look up table is, just as its name suggests, a table. It''s a table of pre-calculated values, in this case of cos(angle) and sin(angle).

The theory is, asking the cpu for sin() or cosine() is slow, but once you set up a look up table you can obtain the values from it instead.

ie sin(angle) now becomes LookUpCircleSin[angle]

You see?

Personally, I''m against using look up tables anymore for sin and cosine. The problem is, you will always have to round off your angles to some accuracy or another. In this case it''s whole degrees, what happens when you need sin(0.23423)?

Look up tables are good for more complex formulae, rather than sines. If I get a complex formula, consisting of several multiplies etc etc, I decide on an accuracy for the results, then use a look-up table.

BUT before I do that, I ALWAYS leave the full formula in the main loop while I test the rest of the program. Only when everything else around it is working, will I swap it for a look up table, then I''ll carefully test it to see what difference it has made (not to performance, but to accuracy!)

Do a search for some information on 2D rotations, and be prepared for some matrix math!

Leave look up tables for now!

Cheers

Matt


Check out my project at: www.btinternet.com/~Matthew.Bennett
Look up tables for sin and cos are almost a must, since sin and cos take a long time for the computer to process, while look up tables go much faster

From what I can see, you are trying to rotate a point (x,y) around a center origin (cx,cy) by an certain angle.

Here''s the formula:

new_x = (cos_look_up[angle] - sin_look_up[angle]) + cx;
new_y = (cos_look_up[angle] + sin_look_up[angle]) + cy;


I hope this is right since its from memory
Advertisement
Thank you all very much for the helpful information. I''ve got the lookup tables working perfectly now, and I now know what do do with them.

to 3DModelMan: the reason I''m using lookup tables is because the game is in full 3D, but I only need to rotate objects around 2 axis, so the lookup tables would leave more time for drawing.

to mezz: sorry about the mistake in the code. i did actually mean to put the [Degrees] in, i just forgot (this code was written on the spot, not a cut-and-paste job

thanks for the Rad function too. Maybe ANSI should have put on in their c library guidelines. Oh well.

MENTAL
Oh dear. I''ve just noticed something. how do you apply the loopup tables to the angle? 2 people are saying 2 different things

is it this:

o.x = (LookUpCircleCos[deg] * LengthOfRotationArm) + c.x
o.y = (LookUpCircleSin[deg] * LengthOfRotationArm) + c.y

or this:

o.x = (cos_look_up[angle] - sin_look_up[angle]) + c.x;
o.y = (cos_look_up[angle] + sin_look_up[angle]) + c.y;

or do both work?

MENTAL
Hi,

I learned that lookup tables for sine and cosine are done with. They take an enormous cache hit, that slows your program more down then using the standard sin and cosine methods.

Unless you are calling sine and cosine several times after eachother ofcourse. But that is most of the times not the case.

Jaap Suter
____________________________Mmmm, I''ll have to think of one.
quote: Original post by MENTAL
is it this:

o.x = (LookUpCircleCos[deg] * LengthOfRotationArm) + c.x
o.y = (LookUpCircleSin[deg] * LengthOfRotationArm) + c.y

or this:

o.x = (cos_look_up[angle] - sin_look_up[angle]) + c.x;
o.y = (cos_look_up[angle] + sin_look_up[angle]) + c.y;
MENTAL


Well, it should be the first one.
Try to follow this:

x = cos( angle );
y = sin( angle );

This will give you the x,y position on a one unit circle, so, if you simply multiply by the radius, you are extending that point our from the midpoint of the circle, and it will extend in the correct direction.
so:

x = cos_lookup_table( angle ) * radius;
y = sin_lookup_table( angle ) * radius;

The larger the radius, the less precision you will have, though.

then, you will need to offset your x and y positions depending on where the midpoint of your circle is, so just change the previous example to:

x = ( cos_lookup_table( angle ) * radius ) + mid_x;
y = ( sin_lookup_table( angle ) * radius ) + mid_y;

You may need to reverse the y value to something like:

y = mid_y - ( sin_lookup_table( angle ) * radius );

But only if you are working in the fourth quadrant, like the coordinate system of the computer monitor. It all depends how you set it up, though, you could always make that transformation later. Sorry if I wasn''t clear with that last bit.
-Evan

By the way, you may want to pick up a trig book... they''re kind of fun.

This topic is closed to new replies.

Advertisement