![]() |
|
sin & cos: small optimization |
Bruce Perry
Member #270
April 2000
|
A circle does have infinitely many axes of symmetry. But when drawing one, we make use of the vertical, horizontal and 45-degree diagonal axes. Thus our pixellated approximation will be symmetrical in these axes (and almost symmetrical in the other axes). Goodbytes, the distance comparison is just Pythagoras's Theorem. Square the x and y offsets (the coordinates of the point minus the coordinates of the centre of the circle), add the squares together, and compare this with a squared version of the radius. You can then potentially optimise this by making use of the last value of x*x and y*y, e.g. when x is incremented you can take advantage of the following identity: (x+1)*(x+1) = x*x + 2*x + 1 And thus you can modify 'x2', your squared x value, as follows: x2 += 2*x + 1; This may or may not be quicker than just recomputing x*x; it would depend on the processor architecture. However, taking advantage of old values of y² would almost certainly help because y will not always change. -- |
Mr. Xboxor
Member #3,763
August 2003
![]() |
Yeah, but umm, the allegro circle routine just adds and subtracts stuff, ABSOLUTELEY no multiplaction or division, just addition and substraction. What I want to know is how it checks which way is the closest by just adding and subtracting. "Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny |
Bob
Free Market Evangelist
September 2000
![]() |
Quote: What I want to know is how it checks which way is the closest by just adding and subtracting. Google for "Bresenham circle algorithm", or "midpoint circle algorithm" (they're not quite the same, but they both reduce to just adds/subtracts/shifts). -- |
Mr. Xboxor
Member #3,763
August 2003
![]() |
Quote: Google for "Bresenham circle algorithm", or "midpoint circle algorithm" (they're not quite the same, but they both reduce to just adds/subtracts/shifts). But that's what you're for Bob.:) And the allegro one doesn't use any shifts. Just addition and substraction, and not even a whole lot of that. "Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny |
Billybob
Member #3,136
January 2003
|
most importantly: if (df < 0) { df += d_e; d_e += 2; d_se += 2; } else { df += d_se; d_e += 2; d_se += 4; cy--; } cx++; insanely simple...yet so very very complex
|
Karadoc ~~
Member #2,749
September 2002
![]() |
Quote:
karadoc, it's
William, that is insulting to my intelligence...
remember that we are talking about lookup tables. ----------- |
kikabo
Member #3,679
July 2003
![]() |
just out of interest I found once that you can draw a circle using square root only instead of sin / cos (can't remember the situation - I think it was with atari basic!). this is due to the fact that in the fig below the #'s are right angles, so if you know the diameter D and distant X you can find Y because 2 triangles are formed that share dimensions, so the result can be found using pythag.... can't remember the formula though but it's a nice little puzzle for those on their lunch breaks. ** #* ** *| \ * *|| \ * *| | \ * *| | Y \ * *| | \ * *| | \ * *---#---o-------* X D
Edit: hah (I think) |
Billybob
Member #3,136
January 2003
|
Standard Circle forumla: r^2 = (x1 - x2)^2 + (y1 - y2)^2 center:(x1, y1) Unit Circle: y = (x + y)^2
|
Mr. Xboxor
Member #3,763
August 2003
![]() |
So do you guys think that you could use that circle drawing thing to approximate sin and cos values? I mean, if you can draw an approximated circle with sin and cos values, could you reverse the process, and instead use that circle to calculate sin and cos values? I'm writing a game with alot of rotation, and that would be sweet. Sure, I could use lookup tables, or a fixed point system, but that way would be cool too. As long as you don't have to add like a thousand things to get to the right point to calculate sin and cos. "Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny |
Billybob
Member #3,136
January 2003
|
Mr. Xboxor: I doubt it. The algorithim is designed to draw a circle, not calculate trig functions. sin/cos/tan are all designed to calculate trig functions. Use what they were designed for, is what I'm saying, because they would be more optimized in the intended usage. EDIT: Also, I don't think the algorithim has a concept of angle, heh. It just draws points, there are no angles involved really...right?
|
Bruce Perry
Member #270
April 2000
|
The 'pixel walk' method used in drawing a circle will use points on the circle's circumference, but the rate of change of the angle will not be constant or predictable. Sorry, you can't replace sin and cos this way. -- |
Evert
Member #794
November 2000
![]() |
Quote: Degrees are cool, it's the thing we are most use to. I never use degrees. Quote: It is also 0-360, not 0-6.282... Decimals are harder to deal with than integers, so degrees are better for that reason. No. Using only integer values for the angles is far too inaccurate to do anything useful with (unless possibly if you do something like an spline interpolation, but then you probably loose any speed gain you might have had). Quote: I mean, if you can draw an approximated circle with sin and cos values, could you reverse the process, and instead use that circle to calculate sin and cos values? Well, yeah, probably - using the laws for sines and cosines. However, it will be both less accurate and slower than using sin and cos directly. |
Billybob
Member #3,136
January 2003
|
Evert, you do realize i'm talking about the human mind, right? and not a machine? It's harder for our minds to do decimal compared to integers, unless you've studied decimal math in your head extensively. Calculator and computer wise, duh of course decimals are fine, but I was talking about why we use degrees so much, cause we can do the calcs in our heads a lot. i.e. And since we're the ones programming the computer, they have to follow suit Anyway, the more you use radians, though, the better. BTW, as for optimizing sin&cos: They actually aren't too bad. From Bob's exext.c code I came up with the Taylor Series(?) and this: eDIT: Whoopsie
|
Bruce Perry
Member #270
April 2000
|
I remember this subject being discussed somewhere else, and someone said it gets a lot more cunning than that. I fully believe that there are other series that converge much more quickly than the above. In any case, it is done in hardware for you on the PC, so any attempt to use your own algorithm is likely to be slower. -- |
Oscar Giner
Member #2,207
April 2002
![]() |
Not really ten operation. For sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! you need to write sin(x) = x- (x*x*x*)/(3*2) + (x*x*x*x*x)/(5*4*3*2) + (x*x*x*x*x*x*x)/(7*6*5*4*3*2) The good way is to calculate this in a loop, so you can reuse previous results. -- |
Karadoc ~~
Member #2,749
September 2002
![]() |
Quote:
i.e.
I think you might have meant x - pi. I prefer radians. They make sense. Degrees are just radians multiplied by a unitless constant. A waste of time. The trick is to not work with decimal values when dealing with radians. pi can't be expressed as a decimal number anyway. Instead, just leave pi in all your numbers. ----------- |
kikabo
Member #3,679
July 2003
![]() |
WH: |
orz
Member #565
August 2000
|
You could, if you really wanted too, "optimize" the sin/cos table using simmetry - a single period of the sine wave has several symmetries to it: //assuming 0 <= x < 256 (360 degrees == 256 arbitrary angle units) In that way, the size of the sin+cos table could be cut down to 20% of its normal size. But those kinds of branches might be expensive on modern computers; I doubt it would be worth it for the average program. You can try various other optimizations if you want: //assuming 0 <= x < 256 (360 degrees == 256 arbitrary angle units) But I expect that the way that Allegro currently does it is about as good as it's possible to get for the average program. (I probably screwed up one or both of the examples above...) |
Bruce Perry
Member #270
April 2000
|
Quote: never trusted that since I learned that you can prove that a = -a with it The proof is invalid. To the best of my recollection, it uses a step like the following: 0*2 = 0*3 You are only proving that a = -a after having established that a = 0. It's something along those lines anyway. If you post the proof I'll comment specifically on how it's invalid. -- |
Evert
Member #794
November 2000
![]() |
William Heatly said: you do realize i'm talking about the human mind, right? and not a machine? You do realize that I said I never use degrees? Quote: It's harder for our minds to do decimal compared to integers, unless you've studied decimal math in your head extensively.
rational numbers are not that much harder to deal with than integers. Real numbers is a different matter, because you cannot express them as a rational fraction. No big deal as long as you write sqrt(2) instead of 1.414..., pi instead of 3.1415... etc. Quote: but I was talking about why we use degrees so much, cause we can do the calcs in our heads a lot. As I said, I never use degrees. Bear in mind though - I do calculations that are outside the scope of game programming (calculating volume elements or areas). For these you need to express angles in radians because that is the natural way to express angles. As a quick example, the circumference of a unit circle is the integral of 1 over all possible angles. The answer, of course, is 2pi. But if you naively integrate over 360 degrees instead, the answer would be 360 (yes, I know how the transformation should be done and that if you do it correctly you get 2pi as well - that's why I said naively). |
Billybob
Member #3,136
January 2003
|
Quote: do calculations that are outside the scope of game programming (calculating volume elements or areas).
Ahh yes, area calculations are much easier with radians, sure. But I'm pretty sure that for most of your childhood you used degrees, cause they really don't teach radians until pre-calc. Afterwards, yes, it is quite possible that you adapted to radians just fine and use them.
|
kikabo
Member #3,679
July 2003
![]() |
Bruce, yep something like that
so when debugging, it's cause all you variables are negative! |
Marcello
Member #1,860
January 2002
![]() |
Um, 0/0 isn't defined, is it? Marcello |
kikabo
Member #3,679
July 2003
![]() |
could be infinity, could be 0, no wait I've just proved it's 2a !.. I'll stop deliberatly posting rubbish now and only do it by accident, stupidity or ignorance |
Thomas Fjellstrom
Member #476
June 2000
![]() |
It is defined. Its defined to throw an exception. (SIGFPE) -- |
|
|