English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. C/C++

 
 
Thread Tools
Old 17 October 2020, 23:46   #1
a1k3k
Registered User
 
Join Date: Apr 2020
Location: Kernelville
Posts: 15
Help with smooth 3D Cube in C on A500 using Draw() and Move()

As a challenge, I've taken it upon myself to delve into Amiga coding in C and attempt to make a few 3D routines.

Is it possible to create a decently smooth wireframe rotating cube using C that runs on a stock A500?

I ask because I've seen [ Show youtube player ] and it seems he's managed to do it using pure C, but I haven't managed to do so yet.


In my own attempt, I've tried double buffering (swapping out two bitmaps every frame). The flicker is reduced, but the frame rate is still abysmally slow, something like 1-2 frames per second.

Even when I turn off rotation and just have basic horizontal movement, it's slow. On a souped-up UAE config it's smooth though.

So I reckon it's nothing to do with the transformation parts, which are integer and use lookup tables for trig functions.

I'm using a 320x200 screen with 2 bitplanes.

My cube is pretty much self-explanatory:

struct node cubeNodes[8] = {{-1, -1, -1},{-1, -1, 1},{-1, 1, -1},{-1, 1, 1},{1, -1, -1},{1, -1, 1},{1, 1, -1},{1, 1, 1}};


struct edge cubeEdges[12] = {{0, 1},{1, 3},{3, 2},{2, 0},{4, 5},{5, 7},{7, 6},{6, 4},{0, 4},{1, 5},{2, 6},{3, 7}};


My bitmap swapper:

void swapBitmap(){
static int bitmap = 0;

if (bitmap==0) {
rp.BitMap = &b2;
ri.BitMap = &b2;
SetRast(&rp,0);
bitmap=1;
} else {
rp.BitMap = &b;
ri.BitMap = &b;
SetRast(&rp,0);
bitmap=0;
}
}


where rp is the RastPort and ri is RastInfo.

My copper list updater:

void updateCopperLists() {
MakeVPort (&v, &vp);
MrgCop (&v);
LoadView (&v);
WaitTOF();
WaitBlit();
}


and finally, my draw routine which basically iterates through the object edges and does a Move() on the first vertex and a Draw() on the second vertex. On entry it swaps in the bitmap on which it'll draw on, and prior to exit updates the copper list so the bitmap is shown:

     swapBitmap();

for (i = 0; i < obj->edgeSize; i++)
{

/* Draw line using screen coordinates */
Move (&rp,
obj->nodes[obj->edges[i].nodeA].x + WIDTH / 2 + obj->centerAt.x,
-obj->nodes[obj->edges[i].nodeA].y + HEIGHT / 2 + obj->centerAt.y);
Draw (&rp, obj->nodes[obj->edges[i].nodeB].x + WIDTH / 2 +
obj->centerAt.x, -obj->nodes[obj->edges[i].nodeB].y + HEIGHT / 2 +
obj->centerAt.y);
}
}

updateCopperLists();


FWIW I've also tried starting the main code with Forbid() and Disable() but it doesn't help speed up in any measurable sense.

Anyone has any tips? Maybe it's something I'm overlooking? I'm pretty new to coding for the Amiga but I'd love to keep at it and get better as I've always wanted to code my own demo routines that can run on a bog standard A500.

I'd like to move on to assembler later on, but first I'd like to be able to hash it out in C.
a1k3k is offline  
Old 18 October 2020, 08:32   #2
Ernst Blofeld
<optimized out>
 
Ernst Blofeld's Avatar
 
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
I think your updateCopperLists function may be doing more than it needs to. I don't think you should be calling MrgCop on every buffer flip. This example http://amigadev.elowar.com/read/ADCD.../node05B3.html certainly looks like it does less.

I have used the second method described here http://amigadev.elowar.com/read/ADCD.../node0346.html with success before, but can't find my code at the moment to demonstrate.

Last edited by Ernst Blofeld; 18 October 2020 at 08:46.
Ernst Blofeld is offline  
Old 18 October 2020, 15:57   #3
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,186
The OS routines are abysmally slow. Interface directly with the hardware for a massive speed boost.
Samurai_Crow is offline  
Old 18 October 2020, 21:52   #4
a1k3k
Registered User
 
Join Date: Apr 2020
Location: Kernelville
Posts: 15
Quote:
Originally Posted by Ernst Blofeld View Post
I think your updateCopperLists function may be doing more than it needs to. I don't think you should be calling MrgCop on every buffer flip. This example http://amigadev.elowar.com/read/ADCD.../node05B3.html certainly looks like it does less.
The example uses Intuition's RethinkDisplay() which apparently does MrgCop() and LoadView(). Since I'm not using Intuition screens and bypassing it altogether, I just thought I'd do the same. Though you may be right that it probably shouldn't be called on every flip as they indicate in the RKM "WARNING: This routine can take several milliseconds to run, so do not use it lightly." but the example provided does not heed that.

Quote:
Originally Posted by Ernst Blofeld View Post
I have used the second method described here http://amigadev.elowar.com/read/ADCD.../node0346.html with success before, but can't find my code at the moment to demonstrate.
I've now tried this second method and it's still slow. Maybe a bit faster, but nothing usable.
a1k3k is offline  
Old 18 October 2020, 21:55   #5
a1k3k
Registered User
 
Join Date: Apr 2020
Location: Kernelville
Posts: 15
Quote:
Originally Posted by Samurai_Crow View Post
The OS routines are abysmally slow. Interface directly with the hardware for a massive speed boost.
Any pointers on how to do that in C? I'm fairly new to Amiga coding (although an old hand with coding in general).
a1k3k is offline  
Old 18 October 2020, 22:13   #6
Ernst Blofeld
<optimized out>
 
Ernst Blofeld's Avatar
 
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
Quote:
Originally Posted by a1k3k View Post
The example uses Intuition's RethinkDisplay() which apparently does MrgCop() and LoadView(). Since I'm not using Intuition screens and bypassing it altogether, I just thought I'd do the same. Though you may be right that it probably shouldn't be called on every flip as they indicate in the RKM "WARNING: This routine can take several milliseconds to run, so do not use it lightly." but the example provided does not heed that.


I've now tried this second method and it's still slow. Maybe a bit faster, but nothing usable.
How fast is it if you remove everything except for the buffer swapping? ie leaving very little apart from LoadView swapping buffers? And, conversely, how fast is it if you just use single buffering? It would be useful to know where the overhead really is.
Ernst Blofeld is offline  
Old 19 October 2020, 01:44   #7
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,186
If you're using more than 2 bits per pixel, reduce the palette depth. This will speed up the blitter by freeing up bandwidth used by the display DMA. You should only need 3 foreground colors to draw a cube.
Samurai_Crow is offline  
Old 19 October 2020, 09:05   #8
Ernst Blofeld
<optimized out>
 
Ernst Blofeld's Avatar
 
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
Looking at the youtube clip, he's not doing half the work you are. He's drawing into a single bitplane, probably clearing only the bits he's touched, and probably not using double buffering as he can probably sync with the display as he's drawing so little. I'm sure you can get your stuff to be smoother once you've worked out where the time is going, but I wouldn't compare to his.

You may want to check out the bartman gcc vs-code stuff that will allow you to profile in a modernish way.

Last edited by Ernst Blofeld; 19 October 2020 at 18:01.
Ernst Blofeld is offline  
Old 19 October 2020, 15:48   #9
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,186
Looking at the YouTube clip there are 2 playfields at 1 bitplane each. The Copper work is best done only once. A double-buffered one bitplane screen is easy when there are only 2 copper lists. The copper does all the bitplane changes too.
Samurai_Crow is offline  
Old 19 October 2020, 22:52   #10
a1k3k
Registered User
 
Join Date: Apr 2020
Location: Kernelville
Posts: 15
Quote:
Originally Posted by Ernst Blofeld View Post
How fast is it if you remove everything except for the buffer swapping? ie leaving very little apart from LoadView swapping buffers? And, conversely, how fast is it if you just use single buffering? It would be useful to know where the overhead really is.
So I included a little fps timer in the code and I get on my A1k 5-6 fps with absolutely nothing on, except buffer swap. With single buffer, I get a solid 6. OTOH on my 25MHz A3k I went from 25 to 43 fps.


Quote:
Originally Posted by Ernst Blofeld View Post
Looking at the youtube clip, he's not doing half the work you are. He's drawing into a single bitplane, probably clearing only the bits he's touched, and probably not using double buffering as he can probably sync with the display as he's drawing so little. I'm sure you can get your stuff to be smoother once you've worked out where the time is going, but I wouldn't compare to his.

You may want to check out the bartman gcc vs-code stuff that will allow you to profile in a modernish way.

Quote:
Originally Posted by Samurai_Crow View Post
Looking at the YouTube clip there are 2 playfields at 1 bitplane each. The Copper work is best done only once. A double-buffered one bitplane screen is easy when there are only 2 copper lists. The copper does all the bitplane changes too.
You're right guys, I absolutely missed the point that he's using a different approach. To start with, I'll probably try to cut down from 2 bitplanes to 1.

Thanks for all the insight, I appreciate it a lot!
a1k3k is offline  
Old 20 October 2020, 03:27   #11
Ernst Blofeld
<optimized out>
 
Ernst Blofeld's Avatar
 
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
Quote:
Originally Posted by a1k3k View Post
5-6 fps with absolutely nothing on, except buffer swap
This is surprising to me, I would have expected even OS friendly code to do around 15 fps to do nothing.
Ernst Blofeld is offline  
Old 27 October 2020, 14:04   #12
a1k3k
Registered User
 
Join Date: Apr 2020
Location: Kernelville
Posts: 15
Quote:
Originally Posted by Ernst Blofeld View Post
This is surprising to me, I would have expected even OS friendly code to do around 15 fps to do nothing.
So I screwed up big time in my earlier posts and FPS checks. I forget to comment out a call to a critical non-draw function: the rotation function. Yes, I know. I thought I had it commented out, but didn't.

Anyway, that function was the culprit. I was doing some math with doubles and that killed the speed. I changed it over to integer math and everything is way, way faster now and smooth as butter.

Here are some stats:
Screen is 320x256, 1 bitplane, 1 cube scaling, rotating and moving across the screen.

(A) Single buffer, no WaitTOF(): 30-31 with flicker
(B) Single buffer, 1 WaitTOF(): 25 fps solid with flicker
(C) Single buffer, 2 WaitTOF(): 16-17 fps with flicker

(D) Double buffer, no WaitTOF(): 30-31 without flicker
(E) Double buffer, 1 WaitTOF(): 25 fps solid without flicker
(F) Double buffer, 2 WaitTOF(): 16-17 fps without flicker

So out of the lot, D seems great. I guess B and E are at a constant 25 fps due to the WaitTOF() limiting refreshes.

Using 2 WaitTOF()'s decreases performance and is not required since I'm not using interlaced modes.

And without any work (no cube drawing and transformations):

(G) Single buffer, no WaitTOF(): 357 fps
(H) Single buffer, 1 WaitTOF(): 50 fps
(I) Single buffer, 2 WaitTOF(): 25 fps

(J) Double buffer, no WaitTOF(): 336 fps
(K) Double buffer, 1 WaitTOF(): 50 fps
(L) Double buffer, 2 WaitTOF(): 25 fps

For the double buffer swapper, all I do is set the LOFCprList, SHFCprList, RastInfo and RastPort bitmaps and then do a LoadView() (no MakeVPort() and MrgCop()).
a1k3k is offline  
Old 27 October 2020, 14:32   #13
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,186
Beam sync with WaitTOF can free up some processor time for other functions because, unlike PC, vertical blank triggers an interrupt on Amiga.
Samurai_Crow is offline  
Old 27 October 2020, 16:07   #14
Ernst Blofeld
<optimized out>
 
Ernst Blofeld's Avatar
 
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
Quote:
Originally Posted by a1k3k View Post
(D) Double buffer, no WaitTOF(): 30-31 without flicker
Maybe you want to move to triple buffering.
Ernst Blofeld is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Cube 68k arti support.Games 41 03 December 2019 16:53
Rotating cube getting cutoff Knocker Coders. Asm / Hardware 2 07 September 2016 08:13
Amiga Cube? fondpondforever Amiga scene 3 25 June 2015 08:40
Move it Move it... (68000) Gilloo Coders. Asm / Hardware 19 04 December 2011 17:36
Speccy on a cube daznic Retrogaming General Discussion 1 03 June 2009 19:44

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 07:16.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.25243 seconds with 15 queries