6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 11:21 pm

All times are UTC




Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Fri Sep 20, 2002 5:04 pm 
Offline

Joined: Fri Sep 20, 2002 4:32 pm
Posts: 5
Hi
I just started coding on my good ol' friend, c64 again.
I'm trying to code a simple 2d routine using precalulated sin and cos tables. Since multiplication routines are far to slow for my taste, I've used an old method that was common back in the days, but unfortunately lacked accuracy.

the standard formula for rotating a 2d (x,y) co-ordinate around an origin by a certain angle goes something like..

x = oldx * cos(angle) - oldy * sin(angle)
y = oldx * sin(angle) + oldy * cos(angle)

..as most of us know by now ;)

the old routine i mentioned converted all multiplications to divisions.

sin(45) = 0,7
1 / 0,7 = 1,4 ; since we're going to use div instead of multi.

now.. we had to convert it so it could easily be divided by a single LSR
1,4 would turn in to 1.. so.. (55 would turn into 64 and so on)

x = oldx / 1 - oldy / 1
y = oldx / 1 + oldy / 1

we're still cursed dealing with signed numbers but hey, div by LSR is far less speed consuming than any multiplication routines. :) but as I mentioned before we're bound to falter into the problem of accuracy. so I'm wondering if you guys got any better ideas? I remember that someone once talked about a routine that only used additions and subtractions together with tables, but since I'm no math pro I can't figure it out :P any help would be appreciated.


Cheers
Undo

_________________
I need to find
Something to blame for a long lost time


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Sep 20, 2002 8:10 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
I haven't done much with rotations or other graphics, but I might throw in some quick comments here.

Using relatively small tables for sin & cos gives very poor accuracy near where the output =1 unless you have room for really large tables for super fast, accurate 16-bit math. If you really wanted the large tables for the C64, you could devise an extension bus to interface via the 44-pin expansion port and put a couple of MB of EPROM out there for various 128KB look-up tables.

Otherwise, using the first four iterations of the infinite series gives good accuracy for sin & cos for 16-bit work, or you might be able to find polynominal approximations that are more economical. Where I found the look-up table to work best is in the arctan function. Using a 17-element table of 16-bit numbers for the input range of 0 to 1 (output 0 to 45 deg) to get the arctan gives a maximum error of <.02deg after interpolation. Unfortunately, the interpolation also requires division and multiplication. With the 0-45 deg range, a little manipulation gets you the rest of the circle. Floating-point arithmetic is not necessary and frankly is a very inefficient use of processor power if the input and output ranges are known.

So how much accuracy do you need? If it's for C64 graphics, even 16-bit scaled integer trig might be an overkill. OTOH, it would be much faster than using the built-in floating-point routines. It works best to represent the circle with 65,536 points, so a degree is about 182 points and a radian is about 10,430. (I should make a note here for those on both sides of the Atlantic: The European convention is to use the comma for a radix, while the American is to use the period. When the original poster writes 1,4, that's 1.4 to us Americans.) Using the full 16-bit count to represent the circle results in 361 deg being the same as 1 deg, since it just rolls over.

As far as using only addition and subtraction, there is a way to get a square root this way, but it's extreeeeeemely slow. If you had a lot of time and only a few bytes of available program memory though, that would be the way to do it.

Edited 6/25/12 to add the link for the big math look-up tables

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Sep 21, 2002 12:06 am 
Offline

Joined: Fri Sep 20, 2002 4:32 pm
Posts: 5
thanks for the insight. :)

Well since speed is a priority over accuracy, I won't be using floating point routines at all. If I convert all floating points in the tables to integers using the following method I get a little loss in accuracy but not really that much.

ex.
0,52 * 64 = 33,28 (33 when we round off)

..64 is dividable easily using LSR 6 times and leaves pretty good accuracy. so just divide the final result of the eq with 64 et voila :) no nasty floating points. Since It's graphics I'm dealing with, to many 16bit variables would take far to much cycles away from me if I want a reasonably high framerate. So I'll be using 8bit as much as possible.

Oh.. I found a very interesting link..
http://www.catalase.com/optrot3d.htm

It's a fast 3d transform method for the 68000.. the last example on the page is one using only add and sub. I have to admit, I'm no math professor and I haven't even studied trig in school. (We simply didn't have that here in Sweden were I went :P) I've learned pretty much everything on my own. So I'm a little bit confused about the whole idea he's introducing. so once again any help would be appreciated :P

Cheers
Undo

_________________
I need to find
Something to blame for a long lost time


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Sep 21, 2002 2:21 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Note: Floating-point is not necessary for trig functions or almost anything else people think you need it for. I don't use it anymore, and I wasn't talking about using it above.

If you can actually make do with only 8 bits, you could have a few 256-byte look-up tables with simple X-register indexing, and it should really fly. If you do trig that way and then still use multiplication and division (albeit low-resolution), how many of the various operations do you figure you'll need to do in a second to get the desired performance?

Garth

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Sep 21, 2002 1:22 pm 
Offline

Joined: Fri Sep 20, 2002 4:32 pm
Posts: 5
True it will be a low resolution but since the graphic "screen" I'll be using is only 31*31 vpixels ('vpixel = 4*4 real pixels) 8 bits should be enough.

I got around 11592cycles left per frame to do calculations and other stuff for the rotation and there's around 961 pixels to calculate, that would allow around 603cycles per individual pixel/frame. Though we have to keep in mind that those 603 cycles includes converting, calculating and moving the pixels to the right location in a non-linear array. A framerate of 3-5fps would be nice.

In any way I would need to do atleast 4 (possibly even 5) signed multiplications per pixel, and that would take far to much time :/ If I'd narrow it down to 4 divisions and 1 possible multiplication then I'm left with the great loss of accuracy. Surely there's got be another way using a tad more memory and make the whole process move faster.

_________________
I need to find
Something to blame for a long lost time


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Sep 23, 2002 12:18 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Hi Garth,

> As far as using only addition and subtraction, there is a way to get a
> square root this way, but it's extreeeeeemely slow

Without using tables it's the fastest method I know of calculating roots.
See....

http://www.6502.org/source/integers/root.htm

... for an integer 6502 coded example.

A very similar routine is used in EhBASIC to calculate the 24 bit floating
point root and is better than eight times faster than the standard Microsoft 6502 BASIC root routine.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Sep 24, 2002 3:32 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Alright, here it is. Don't blink or you'll miss it. This one handles inputs from 1 to $8002. Put the input in a 2-byte variable INPUT, and the output comes out as a single byte in ROOT.

Code:
SQRT:  LDA    #1
       STA    ROOT
  loop:  JSR  sr1
         INC  ROOT
         JSR  sr1
         LDA  INPUT+1
       BPL    loop
       DEC    ROOT
       RTS
;---------------
  sr1: LDA    INPUT
       SEC
       SBC    ROOT
       STA    INPUT
       BCS    sr2
       DEC    INPUT+1
  sr2: RTS
;----------------------------


That's all there is to it. The speed isn't too bad for small numbers; but if you do the same method for 32-bit inputs, you can see it could require looping so many times you might as well go get a cup of coffee while you're waiting.

Say X is your input, and R is the root. Here's what you do:

R=1
X=X-R
R=R+1
X=X-R
Keep looping back to the second line until X becomes negative.
R=R-1

Much faster: R=(X+R^2)/2R, repeated until the answer converges. Start with a guess for R, and get a new resulting R, much closer to the actual square root of X. It takes very few iterations, unlike the method above.

Garth

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Last edited by GARTHWILSON on Tue Sep 24, 2002 7:40 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Sep 24, 2002 12:44 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Hi Garth,

> Don't blink or you'll miss it. This one handles inputs from 1 to
> $8002. Put the input in a 2-byte variable INPUT, and the output
> comes out as a single byte in ROOT.

Not quite, it's only faster for values up to 7.5 bits and that can be
done much quicker with a lookup table. For the high limit of your
routine it's over 15 times slower.

> When I clicked "Preview", all the spaces added for readability
> disappeared. Someone please tell me what I need to do to get
> monospacing for pieces of code like this!

I tried inserting [TAB] characters but that doesn't work either.

Lee.


Top
 Profile  
Reply with quote  
 Post subject: Formatting Code
PostPosted: Tue Sep 24, 2002 2:25 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1748
Location: Sacramento, CA
Everyone,


Here's how you can format your text. Type it in as you want it to be displayed. When done, Select all of the text by holding down your mouse button while dragging over the text. Now click the "CODE" button above.

Here's an example of Garth's code:

Code:
SQRT:          LDA   #1
                   STA   ROOT
loop:            JSR   sr1
                   INC   ROOT
                   JSR   sr1
                   LDA   INPUT+1
                   BPL   loop
                   DEC  ROOT
                   RTS
;---------------
sr1:             LDA   INPUT
                   SEC
                   SBC   ROOT
                   STA   INPUT 
                   BCS   sr2
                   DEC   INPUT+1
sr2:             RTS



As far as the math goes, I've done some 2D and 3D conversions...I'll try to dig some of the code up and see if it would help.

Daryl


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Sep 24, 2002 7:09 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
I had written,
>> Don't blink or you'll miss it. This one handles inputs from 1 to
>> $8002. Put the input in a 2-byte variable INPUT, and the output
>> comes out as a single byte in ROOT.

and Lee responded,
> Not quite, it's only faster for values up to 7.5 bits and that can be
> done much quicker with a lookup table. For the high limit of your
> routine it's over 15 times slower.

After I sent my post, I realized this could be misunderstood. The "don't blink or you'll miss it" was referring to the code length, not execution time, as this is the one I had previously said was extreeeeeemely slow.

I coded it and tried it right before posting. I hadn't added up cycles and made an equation to figure out how long it would take for different inputs. So when I tried it, I was a little surprised that it was as fast as it was for the range of numbers that could be handled with only a 16 (actually 15)-bit input. But extending it to handle a 32-bit input would require making the loop somewhere around twice as long, and you might have to go through it 64K times as many times, meaning it could take over 100,000 times as long. If you're really cramped for code and variable space and not speed, this might be the way to do it though, at least for inputs up to 15 bits.

Garth

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Sep 24, 2002 8:07 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Thanks for the advice Daryl on how to get the intentional spaces in code to stay. I edited my post above. The forum software still wouldn't do exactly what I wanted, but hopefully some more experimentation will do the trick.

Garth


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Sep 24, 2002 8:15 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1748
Location: Sacramento, CA
Undo,

Can you elaborate more on what you will be doing? Will your rotations always be around the center of your 31x31 display? Will there be a fixed shape in it ( or maybe just a few)? What will be the minimum/maximum angle of rotation per display update?

I have done some 2D & 3D coding in the past and found tables of data to be the best way as far as speed goes, depending upon the data being processed.

If you are rotating around the center point of your display, then there are several short-cuts available in using pre-calculated lookup tables.

I'd be glad to help if you can help to describe the application!

Daryl


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Sep 24, 2002 8:39 pm 
Offline

Joined: Fri Sep 20, 2002 4:32 pm
Posts: 5
:)

8BIT wrote:
Can you elaborate more on what you will be doing? Will your rotations always be around the center of your 31x31 display? Will there be a fixed shape in it ( or maybe just a few)? What will be the minimum/maximum angle of rotation per display update?


Yeah, the rotation will always be around the center of the 31x31 "screen". The whole 31x31 (961 pixels) image shall be rotated, I guess you could call it some sort of "bitmap rotation". The angle? around 10 deg. (10, 20, 30 and so on ;)

I agree that tables are by far the fastest way to do rotations in a case like this, the problem is finding a nifty method avoiding cycle-eaters like multiplication routines and such. any ideas?

thanks
Undo

_________________
I need to find
Something to blame for a long lost time


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Sep 24, 2002 10:56 pm 
I think I can give you a method using look-up tables and no multiplication/division if you can afford about 6k for the tables & code.

The basic idea is pre-calculate the new x,y position from the old one for each pixel. Since you are rotating about the center, you only have to calculate one quarter of the screen. The other three will be the same offsets, they'll just have different signs. Since you will be limiting the angles to 10,20,30, ect, only 8 tables would be needed. Each table will hold 2 bytes for each of the 256 pixels in the first quadrant (the new x and new y). This method will also eliminate the need to check to see if a pixel was rotated "off the screen".

Let me know if this method sounds practical.

Daryl


Top
  
Reply with quote  
 Post subject:
PostPosted: Wed Sep 25, 2002 1:58 pm 
Offline

Joined: Fri Sep 20, 2002 4:32 pm
Posts: 5
Thanks Daryl.
I'm not quite sure how much memory I'll be able to spare but 6kb is quite a nice price to pay for such great speed.

I'll try to fiddle some with the idea later tonight..

_________________
I need to find
Something to blame for a long lost time


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: