News:

Welcome to RetroCoders Community

Main Menu

Flying donut

Started by mysoft, May 09, 2022, 03:40 PM

Previous topic - Next topic

mysoft

so i got some donut algorithm that was doing 3ms per frame in C... for 80x25 resolution... and optimized it
so that here i get 0.1ms for 80x25 (-gen gcc) but then i bumped the resolution to 512x384 and got 2.8ms

and added some shaped animation...

#define fbc -gen gcc -s gui -fpu sse -asm intel -Wc "-Ofast -march=native -mtune=native"

#include "crt.bi"
#include "fbgfx.bi"

const cWid=640 , cHei=480 'donut size
const cScanline=0         '1 to semi-transparent

const cMidX=cWid\2 , cMidY=cHei\2 
const cBlkW=1 , cBlkH=1 , cShades = 128\2
const cDonW=cWid\3 , cDonH = cHei/2 , cMaxY=cHei-3
const PI2 = ATN(1)*8

static shared as ubyte zBuff(cWid*cHei)=any
dim as long A,B,i,j,ScrWid,ScrHei
dim as double DonutX,DonutY

screeninfo ScrWid,ScrHei
screenres cWid*cBlkW , cHei*cBlkH , 8 , 2 , fb.GFX_SHAPED_WINDOW or fb.GFX_ALWAYS_ON_TOP

' !!! May need that on windows with newer freeebasic version? !!!
' but will break it for oler versions (not sure since when... assuming its the D2D render that breaks that)
rem palette 0,255,0,255

DonutX = (ScrWid\2)-cMidX : DonutY = (ScrHei\2)-cMidY
for N as long = 0 to (cShades*2-1)
  var NN = 32+((N*(255-32))\(cShades*2-1))
  palette 128+N,sqr(NN\2)*24,NN*.80,(NN\(N+1))
next N

const cPrecision = (cWid+cHei)\2
static shared as single _Sin(cPrecision+2) , _Cos(cPrecision+2)
for N as ulong = 0 to cPrecision+2
  _Sin(N) = sin(((N*PI2)/cPrecision))
  _Cos(N) = cos(((N*PI2)/cPrecision))
next N

dim as long AVG
dim as single dZoom = timer

do

  erase zBuff
  
  static as long iPage : iPage xor= 1
  screenset iPage xor 1,iPage
  
  line(cMidX-cMidX\2,cHei\16)-(cMidX+cMidX\2,cHei-cHei\16),0,bf
    
  dim as double TMR = timer
  dim as ubyte ptr pBuff = screenptr
  
  dim as single e=_Sin(A) , g=_Cos(A) , m=_Cos(B) , n=_Sin(B)
  
  'zoom in and bump
  static as long Dist = 5
  if Dist > 5 then
    Dist = 256 - tan(timer-dZoom)*251
    if Dist < 4 then Dist = 4
  else
    Dist = 5
  end if  
  
  for j=0 to cPrecision step 1
    
    dim as single d=_Cos(j) , dg=d*g , de=d*e , dn=d*n
    dim as single f=_Sin(j) , fe=f*e , fg=f*g , fg_5 = fg+Dist
    dim as single h=d+2 , he=h*e , hg=h*g , hm=h*m , hn=h*n
    
    for i=0 to cPrecision+2 step 4
      
      'calc pixel
      dim as single c=_Sin(i) , l=_Cos(i)
      dim as single DD=1/(c*he+fg_5)
      if DD > 1/3 then DD = (DD+1/3)/2
      dim as single t=c*hg-fe
      dim as long x=cMidX+clng(cDonW*DD*(l*hm-t*n)) 
      dim as long y=cMidY+clng(cDonH*DD*(l*hn+t*m))      
      dim as long NN=((cShades*1.1)*((fe-c*dg)*m-c*de-fg-l*dn))
      
      'plot pixel and Z order
      var iC = iif(NN>0,NN+128,128)
      
      'speed up "hack lines"
      static as long ox,oy
      var iZ = clng(DD*64)
      if i then
        while ox<>x orelse oy<>y
          if ox<>x then 
            ox += sgn(x-ox) : var o=ox+cWid*(oy or cScanline)
            if iZ>zBuff(o) then zBuff(o) = iZ : pBuff[o] = iC
          end if
          if oy<>y then 
            oy += sgn(y-oy) : var o=ox+cWid*(oy or cScanline)
            if iZ>zBuff(o) then zBuff(o) = iZ : pBuff[o] = iC
          end if
        wend
      else               
        var o=x+cWid*(y or cScanline) : ox=x : oy=y
        if iZ>zBuff(o) then zBuff(o) = iZ : pBuff[o] = iC
      end if      
      
    next i
    
  next j
  
  var dTMR = timer-TMR 
  if AVG=0 then AVG = dTMR*10000 else AVG = (AVG*31+(dTMR*10000))\32
  
  printf( "Spd: " & AVG\10 & "." & AVG mod 10 & !"ms  \r" )  
    
  TMR = timer-TMR
  static as long iSX=1,iSY=1
  var fSpeed = TMR*(ScrHei/8)
  DonutX += iSX*fSpeed : DonutY += iSY*fSpeed
  dim as long iLeft = (-cWid\3) , iRight  = ((ScrWid-cWid)+(cWid\3))
  dim as long iTop  = (-cHei\5) , iBottom = ((ScrHei-cHei)+(cHei\5))
  if DonutX <= iLeft   then DonutX = iLeft   : iSX = abs(iSX)
  if DonutX >= iRight  then DonutX = iRight  : iSX = -abs(iSX)
  if DonutY <= iTop    then DonutY = iTop    : iSY = abs(iSY)
  if DonutY >= iBottom then DonutY = iBottom : iSY = -abs(iSY)
  Screencontrol(fb.SET_WINDOW_POS,cint(DonutX),cint(DonutY) or 1)
  
  TMR = (timer-dZoom)/2.5
  'rotate donut
  A = culng(TMR*cPrecision) mod cPrecision
  B = culng(TMR*cPrecision/2) mod cPrecision
   
loop until len(inkey)