Ultimate Amiga

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1]   Go Down

Author Topic: Raycaster  (Read 4805 times)

0 Members and 1 Guest are viewing this topic.

Mia

  • A600
  • *
  • Karma: 1
  • Offline Offline
  • Posts: 101
  • Generic Amiga User
Raycaster
« on: February 22, 2017, 07:01:21 PM »

I've followed the tutorials on lodev.org by Lode Vandevenne and got the raycaster working in AMOS  8) - it's just an experiment to get my head around it. It works nice in UAE but is way toooooo slow on a stock machine - can anyone help with serious ways to speed this up in AMOS?

Code: [Select]
'AMOS Raycaster test by Mia 
MAPWIDTH=24
MAPHEIGHT=24
Dim WORLDMAP(MAPHEIGHT,MAPWIDTH)
Restore MAP
For HEIGHT=1 To MAPHEIGHT
   For WIDTH=1 To MAPWIDTH
      Read WORLDMAP(HEIGHT,WIDTH)
   Next WIDTH
Next HEIGHT
W=320
W#=320.0
H=256
Screen Open 0,W,H,8,Lowres
Double Buffer : Autoback 0
Flash Off : Curs Off
PSX#=22.0
PSY#=12.0
DRX#=-1.0
DRY#=0.0
PLANEX#=0.0
PLANEY#=0.66
TIME#=0.0
OLDTIME#=0.0
X=0
Repeat
   For X=1 To W
      CAMERAX#=2*X/W#-1
      RAYPSX#=PSX#
      RAYPSY#=PSY#
      RAYDRX#=DRX#+PLANEX#*CAMERAX#
      RAYDRY#=DRY#+PLANEY#*CAMERAX#
      MAPX=Int(RAYPSX#)
      MAPY=Int(RAYPSY#)
      SIDEDISTX#=0.0
      SIDEDISTY#=0.0
      If RAYDRX#<>0 and RAYDRY#<>0
         DELTADISTX#=Sqr(1.0+(RAYDRY#*RAYDRY#)/(RAYDRX#*RAYDRX#))
         DELTADISTY#=Sqr(1.0+(RAYDRX#*RAYDRX#)/(RAYDRY#*RAYDRY#))
      End If
      PERPWALLDIST#=0.0
      STPX=0
      STPY=0
      HIT=0
      SIDE=-1
      If RAYDRX#<0
         STPX=-1
         SIDEDISTX#=(RAYPSX#-MAPX)*DELTADISTX#
      Else
         STPX=1
         SIDEDISTX#=(MAPX+1.0-RAYPSX#)*DELTADISTX#
      End If
      If RAYDRY#<0
         STPY=-1
         SIDEDISTY#=(RAYPSY#-MAPY)*DELTADISTY#
      Else
         STPY=1
         SIDEDISTY#=(MAPY+1.0-RAYPSY#)*DELTADISTY#
      End If
      While HIT=0
         If SIDEDISTX#<SIDEDISTY#
            SIDEDISTX#=SIDEDISTX#+DELTADISTX#
            MAPX=MAPX+STPX
            SIDE=0
         Else
            SIDEDISTY#=SIDEDISTY#+DELTADISTY#
            MAPY=MAPY+STPY
            SIDE=1
         End If
         If MAPX>0 and MAPX<=MAPWIDTH and MAPY>0 and MAPY<=MAPHEIGHT
            If WORLDMAP(MAPX,MAPY)>0
               HIT=1
            End If
         Else
            HIT=2
         End If
      Wend
      If HIT=1
         'Calculate distance projected on camera direction
         If SIDE=0
            PERPWALLDIST#=(MAPX-RAYPSX#+(1.0-STPX)/2.0)/RAYDRX#
         Else
            PERPWALLDIST#=(MAPY-RAYPSY#+(1.0-STPY)/2.0)/RAYDRY#
         End If
         'calculate line height
         LINEHEIGHT=Int(H/PERPWALLDIST#)
         'calculate lowest and highest pixel in current strip
         DRWSTART=-LINEHEIGHT/2+H/2
         If DRWSTART<0
            DRWSTART=0
         End If
         DRWND=LINEHEIGHT/2+H/2
         If DRWND>=H
            DRWND=H-1
         End If
         CLOR=WORLDMAP(MAPX,MAPY)+1
         If SIDE=1
            CLOR=4
         End If
         Ink CLOR
         Draw X,DRWSTART To X,DRWND
      End If
   Next X
   OLDTIME#=TIME#
   TIME#=Timer
   FRAMETIME#=(TIME#-OLDTIME#)/50.0
   'Locate 0,0 : Print FRAMETIME#,PLANEX#,PLANEY#,DRX#,DRY#
   MOVESPEED#=FRAMETIME#*5.0
   ROTSPEED#=FRAMETIME#*3.0
   K$=Inkey$
   FLOWX=Int(PSX#+DRX#*MOVESPEED#)
   FLOWY=Int(PSY#*DRY#*MOVESPEED#)
   If K$="w" : Rem forward
      PSX#=PSX#+DRX#*MOVESPEED#
      PSY#=PSY#+DRY#*MOVESPEED#
      'check position
      'If WORLDMAP(FLOWX,Int(PSY#)
      'End If 
      'If WORLDMAP(Int(PSX#),FLOWY)
      'End If 
   End If
   If K$="s" : Rem back
      PSX#=PSX#-DRX#*MOVESPEED#
      PSY#=PSY#-DRY#*MOVESPEED#
   End If
   If K$="a" : Rem left
      OLDDRX#=DRX#
      DRX#=(DRX#*Cos(ROTSPEED#))-(DRY#*Sin(ROTSPEED#))
      DRY#=(OLDDRX#*Sin(ROTSPEED#))+(DRY#*Cos(ROTSPEED#))
      OLDPLANEX#=PLANEX#
      PLANEX#=(PLANEX#*Cos(ROTSPEED#))-(PLANEY#*Sin(ROTSPEED#))
      PLANEY#=(OLDPLANEX#*Sin(ROTSPEED#))+(PLANEY#*Cos(ROTSPEED#))
   End If
   If K$="d" : Rem right
      OLDDRX#=DRX#
      DRX#=DRX#*Cos(-ROTSPEED#)-DRY#*Sin(-ROTSPEED#)
      DRY#=OLDDRX#*Sin(-ROTSPEED#)+DRY#*Cos(-ROTSPEED#)
      OLDPLANEX#=PLANEX#
      PLANEX#=PLANEX#*Cos(-ROTSPEED#)-PLANEY#*Sin(-ROTSPEED#)
      PLANEY#=OLDPLANEX#*Sin(-ROTSPEED#)+PLANEY#*Cos(-ROTSPEED#)
   End If
   Screen Swap
   Wait Vbl
   Cls 0
Until Mouse Key=1
End
MAP:
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1
Data 1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1
Data 1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1



Logged

KevG

  • A600
  • *
  • Karma: 1
  • Offline Offline
  • Posts: 87
Re: Raycaster
« Reply #1 on: February 22, 2017, 10:21:01 PM »

Hello Mia.

I have only briefly looked at the code but you could try the following....

1. Use integer maths where possible.
2. Use Sin/Cos lookup tables
3. Don't use 'Inkeys' Use the scancode method.
4. Use 'Key Speed 1,1' as this speeds up keyboard reading(reset to 10,2 at end)
5. Store your graphics drawing in an array then iterate through the array to draw at once.
6. Disable multi tasking
7. Use 'Turbo Extension commands' e.g. F Draw instead of Draw
8. Reduce the No of colours.
9. Pre-calc as much as possible.
10. Structure the code better. Use procedures first then Gosubs when it works.
11. Probably more......

Regards, Kev G
Logged

Mia

  • A600
  • *
  • Karma: 1
  • Offline Offline
  • Posts: 101
  • Generic Amiga User
Re: Raycaster
« Reply #2 on: February 23, 2017, 07:08:57 PM »

hey Kev,

Thanks for the tips, I've got the mouse working to rotate and put a Step 2 on the casting loop, used Cls 0,x,h1 to x+1,h2 instead of Draw to get a 2x2 resolution at 160x128 and with Key Scan instead of Inkey$ I get 6 fps on stock a1200 now. lol
 
I saw your lookup tables in the 3d cube demo, but here it is -1.0000 to 1.0000 not 360 degrees, so the lookup table would be huge?

I know I can make AMOS use 68k big math routines like x*128/256 instead of x/2 - which is faster when compiled, and use Repeat..C=C+1...Until C>E instead of For..Next loops and they are faster also... but looking at how the calculations are done I don't think I'd be able to convert the float math to integer, it's also the first time I've looked into raycasting so I probably need to learn more, it is quite fun, so I'll try the turbo extension and add textures and sprites and watch it grind to a halt ;-)
Logged

SamuraiCrow

  • compile-time wierdo
  • Forum Mod
  • A1200
  • *****
  • Karma: 5
  • Offline Offline
  • Gender: Male
  • Posts: 946
  • Compile-time wierdo
Re: Raycaster
« Reply #3 on: February 24, 2017, 10:44:25 AM »

I would recommend AMCAF extension over Turbo Plus because it has the fixed point trigonometry functions built-in with 12bit fractional part.  But it uses AmosPro so the multitasking may not be easy to disable.

One other tip:  if you use a custom Copper list you can stretch the display vertically using the modulo register, cutting the blitter time in half for reduced resolutions and the Turbo Draw in AMCAF should be as efficient as F Draw is in Turbo Plus.
« Last Edit: February 24, 2017, 10:51:48 AM by SamuraiCrow »
Logged
Pages: [1]   Go Up
 

TinyPortal 2.2.2 © 2005-2022