Page 1 of 1

how to improve 2d performance and some bugs ?

Posted: Thu Aug 01, 2013 1:15 pm
by mohscorpion
hi
i am new to pure basic , i wanted to test some 2d drawing .
i have written a radar sweep like program using this code:

Code: Select all

h = 700
w=700

Structure ray
  r.i
  theta.i
  x.i
  y.i
  sin.f
  cos.f
EndStructure 


Procedure showmap(height,width,rtheta)
  ;Delay(1)
EndProcedure
Procedure.f GSin(winkel.f) 
  ProcedureReturn Sin(winkel*(2*3.14159265/360)) 
EndProcedure 


Procedure.f GCos(winkel.f) 
  ProcedureReturn Cos(winkel*(2*3.14159265/360)) 
EndProcedure 


Dim rays.ray(360)

For t = 0 To 359
  tmp = t
  tmp = tmp -90 
  If (tmp < 0 )
    tmp = tmp + 360
  EndIf
  rtmp.f = Radian(tmp)
  xtmp = (w/2) + r * (Int(GCos(tmp)*100)/100)
  ytmp = ( h/2) + r * (Int(GSin(tmp)*100)/100)
  rays(t)\theta=tmp
  rays(t)\x=xtmp
  rays(t)\y=ytmp
  rays(t)\cos=GCos(tmp)
  rays(t)\sin=GSin(tmp)
  
Next



InitSprite()
OpenWindow(0, 0, 0, h, w, "2DDrawing Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
;OpenWindowedScreen(WindowID(0), 0, 0, h, w, 0, 0, 0, #PB_Screen_WaitSynchronization )
CanvasGadget(0,0,0,h,w)
StartDrawing(CanvasOutput(0))

Box(0,0,h,w,$000000)
StopDrawing()
Repeat
  Repeat 
    Event = WindowEvent()
    
    Select Event
      Case #PB_Event_CloseWindow
        Quit = 1
    EndSelect
    
  Until Event = 0
  
  
  r = h / 2
  
  For deg = 0 To 359 Step 1
    StartDrawing(CanvasOutput(0))
    DrawingMode( #PB_2DDrawing_Transparent)
    Circle(w/2,h/2,2,RGB(Random(255), Random(255), Random(255)))
    
    theta = deg
    theta = theta -90 
    If (theta < 0 )
      theta = theta + 360
    EndIf
    rtheta.f = Radian(theta)
    rtheta2.f =Radian(theta+1)
    rtheta3.f =Radian(theta-1)
    r2 = r
    
    LineXY(w/2,h/2,rays(deg+1)\cos*r+w/2,rays(deg+1)\sin*r+h/2,$20f3fa)
    If deg = 0 
      tmpdeg=359 
    Else 
      tmpdeg=deg-1 
    EndIf
    LineXY(w/2,h/2,rays(deg)\cos*r+w/2,rays(deg)\sin*r+h/2,$000000)
    LineXY(w/2,h/2,rays(tmpdeg)\cos*r+w/2,rays(tmpdeg)\sin*r+h/2,$000000)
    For j = 1 To 5
      radius = Random(w/2-1)
      x.i = Int((w/2) + radius * rays(tmpdeg)\cos)
      y.i = Int(( h/2) + radius * rays(tmpdeg)\sin)
      Plot(x,y,RGB(Random(255), Random(255), Random(255)))
    Next
    DrawText(50,650,"theta=" + Str(deg) )
    StopDrawing()
  Next
 Until Quit = 1

there is two problems :
1- it is slow ( i have tried windows screen too)
2- it is supposed for radar to delete previously drawn line when inserting new line but it seems that new line is written with a little different angle ( i guess because of rounding sin and cos )
can any one shed some light on this ?

Re: how to improve 2d performance and some bugs ?

Posted: Thu Aug 01, 2013 2:40 pm
by Kukulkan
You should not call StartDrawing() each time. This eats up most of the speed.

Only the repeat part:

Code: Select all

Repeat
  Repeat
    Event = WindowEvent()
   
    Select Event
      Case #PB_Event_CloseWindow
        Quit = 1
    EndSelect
   
  Until Event = 0
 
 
  r = h / 2
  
  StartDrawing(CanvasOutput(0))
  Box(0,0,h,w,$000000)
  DrawingMode( #PB_2DDrawing_Transparent)
  For deg = 0 To 359 Step 1
    Circle(w/2,h/2,2,RGB(Random(255), Random(255), Random(255)))
   
    theta = deg
    theta = theta -90
    If (theta < 0 )
      theta = theta + 360
    EndIf
    rtheta.f = Radian(theta)
    rtheta2.f =Radian(theta+1)
    rtheta3.f =Radian(theta-1)
    r2 = r
   
    LineXY(w/2,h/2,rays(deg+1)\cos*r+w/2,rays(deg+1)\sin*r+h/2,$20f3fa)
    If deg = 0
      tmpdeg=359
    Else
      tmpdeg=deg-1
    EndIf
    LineXY(w/2,h/2,rays(deg)\cos*r+w/2,rays(deg)\sin*r+h/2,$000000)
    LineXY(w/2,h/2,rays(tmpdeg)\cos*r+w/2,rays(tmpdeg)\sin*r+h/2,$000000)
    For j = 1 To 5
      radius = Random(w/2-1)
      x.i = Int((w/2) + radius * rays(tmpdeg)\cos)
      y.i = Int(( h/2) + radius * rays(tmpdeg)\sin)
      Plot(x,y,RGB(Random(255), Random(255), Random(255)))
    Next
    DrawText(50,650,"theta=" + Str(deg) )
  Next
  StopDrawing()
 Until Quit = 1
To fast to see...

Might be even faster if you do StartDrawing() only once before your GUI loop and stop only after loop was ended...

Kukulkan

Re: how to improve 2d performance and some bugs ?

Posted: Thu Aug 01, 2013 2:50 pm
by mohscorpion
the problem is that i have to show moving sweeper to user , i know it slows the program , i wanted to know if is there any solution for this?

Re: how to improve 2d performance and some bugs ?

Posted: Thu Aug 01, 2013 4:35 pm
by Kukulkan
Does this help?

Code: Select all

EnableExplicit

#ScreenWidth = 600
#ScreenHeight = 600
#refresh_every_ms = 20
#radius = 300

Structure structHit
  Radius.i
  Angle.f
  Visibility.i
  Size.i
EndStructure

Global NewList Hits.structHit()

Procedure ShowRadar()

  Protected Angle.f = 0
  Protected Event.i, Quit.i, x.i, Pos.i
  Protected LastRefresh.i
  
  ; generate hits
  For x.i = 1 To 20
    AddElement(Hits())
    Hits()\Radius = Random(#radius, 10)
    Hits()\Angle = Random(2*#PI*1000) / 1000
    Hits()\Visibility = 0 ; first invisible
    Hits()\Size = Random(5,1)
  Next 
  
  OpenWindow(0, 0, 0, #ScreenWidth, #ScreenHeight, "2DDrawing Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  CanvasGadget(0,0,0,#ScreenWidth,#ScreenHeight)
  ; make black from the beginning
  StartDrawing(CanvasOutput(0))
  Box(0,0,#ScreenWidth,#ScreenHeight, RGB(0,0,0))
  StopDrawing()
  
  StartDrawing(CanvasOutput(0))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  Repeat
    Event = WindowEvent()
   
    Select Event
      Case #PB_Event_CloseWindow
        Quit = 1
    EndSelect
    
    Angle.f = Angle.f + 0.01
    If Angle.f > 2*#PI
      Angle.f = 0
    EndIf
    
    If ElapsedMilliseconds() > LastRefresh.i + #refresh_every_ms
      StopDrawing()
      StartDrawing(CanvasOutput(0))
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      LastRefresh.i = ElapsedMilliseconds()
    EndIf
    
    ; dim the whole screen
    Box(0,0,#ScreenWidth,#ScreenHeight, RGBA(0,0,0, 3))
    
    ; draw rotating line
    LineXY(#ScreenWidth/2, 
           #ScreenHeight/2, 
           #ScreenWidth/2 + Sin(Angle.f) * #radius, 
           #ScreenHeight/2 + Cos(Angle.f) * #radius, 
           RGBA(0,255,0,200))
    
    ; check hits
    ForEach Hits()
      With Hits()
        If Abs(\Angle - Angle.f) < 0.01
          ; it is a hit on the line, make visible
          Hits()\Visibility = 100 + (\Size * 10) ; bigger hits lasting longer
        EndIf
        If \Visibility > 0
          ; draw visible hits...
          Circle(#ScreenWidth/2 + Sin(\Angle) * \Radius, 
                 #ScreenHeight/2 + Cos(\Angle) * \Radius, 
                 \Size, 
                 RGBA(200,255,200, 255))
          \Visibility = \Visibility - 1
        EndIf
      EndWith
    Next
    
  Until Quit = 1
  StopDrawing()
  
  CloseWindow(0)  
    
EndProcedure

ShowRadar()
Kukulkan

Re: how to improve 2d performance and some bugs ?

Posted: Fri Aug 02, 2013 2:04 am
by mohscorpion
it helps but there are several problems :
1- sweeper starts from bottom and goes CCW which i need CW and start from north
2- hits are calculated before sweep which in my case is not , data are gathered from analog to digital data which i tried to simulate with random points
3- also it cleans old hits before end of sweep which in my case i need them for about 5 rounds ( dim very slower )
but thanks very much , i will change my code based on your method and reevaluate
:)

Re: how to improve 2d performance and some bugs ?

Posted: Fri Aug 02, 2013 7:56 am
by Danilo
Try with sprites (windowed screen) instead 2D drawing commands like Line, Box, etc.

10 years old, so it doesn't work anymore out-of-the-box with latest PB: http://purearea.net/pb/CodeArchiv_v393/Graphics/Demos/Radar.pb
Maybe you want to test with 10 years old PB version.

Skeleton of Radar.pb for PB5.20 beta7+ (important, because Sprite3D change):

Code: Select all

; original: http://purearea.net/pb/CodeArchiv_v393/Graphics/Demos/Radar.pb

;#Width  = 1600 
;#Height = 1200 
#Width  = 1280
#Height = 1024
;#Width  = 1024 
;#Height = 768 
;#Width  = 800 
;#Height = 600 

#rotator_speed = 3 

#max_objects = 10 

Structure _OBJ 
  x.l 
  y.l 
  Transparency.l 
  Degree.f 
EndStructure 

NewList Objects._OBJ()


Procedure.f GSin(winkel.f) 
   ProcedureReturn Sin(winkel*(2*3.14159265/360)) 
EndProcedure 


Procedure.f GCos(winkel.f) 
   ProcedureReturn Cos(winkel*(2*3.14159265/360)) 
EndProcedure 


Procedure ObjectSound(x) 
  ;Beep_(800,50) 
EndProcedure 


Procedure MakeSprites() 

  h = #Height-100 

  If CreateSprite(1,512,512)=0 Or CreateSprite(0,512,512)=0 Or CreateSprite(2,256,256)=0 Or CreateSprite(3,h,h)=0 
    CloseScreen() 
    MessageRequester("ERROR","Cant create Sprites !") 
    End 
  EndIf 

  ; Radar rotator (green > black)
  StartDrawing(SpriteOutput(0)) 
    angle.f=90 
    Repeat 
      Line(255,255,GSin(angle)*255.0,GCos(angle)*255,RGB(0,Int(angle*2.8),0)) 
      angle.f - 0.001 
    Until angle <=0 
  StopDrawing() 
  
  ; Radar rotator (green > black) - reverse
  StartDrawing(SpriteOutput(1)) 
    angle.f=0
    Repeat 
      Line(255,255,GSin(angle)*255.0,GCos(angle)*255,RGB(0,Int((90-angle)*2.8),0)) 
      angle.f + 0.001
    Until angle >=90.0
  StopDrawing() 
  
  
  ; Radar objects 
  StartDrawing(SpriteOutput(2)) 
    For a = 127 To 0 Step -1 
      Circle(127,127,a,RGB(255-2*a,255-2*a,255-2*a)) 
    Next a 
  StopDrawing() 
  ZoomSprite(2,32,32) 

  ; Radar chassis 
  StartDrawing(SpriteOutput(3)) 
    Circle(h/2,h/2,h/2,RGB($40,$40,$40)) 
    Circle(h/2,h/2,h/2-10,RGB($00,$00,$00)) 
    DrawingMode(4) 
    For a = 0 To 5 
      Circle(h/2,h/2,h/10*a,RGB($40,$40,$40)) 
    Next a 
    For a = -2 To 2 
      Line(0,h/2+a,h,0,RGB($40,$40,$40)) 
    Next a 
    For a = -2 To 2 
      Line(h/2+a,0,0,h,RGB($40,$40,$40)) 
    Next a 
    For a = 30 To 330 Step 30 
      Line(h/2,h/2,GSin(a)*h/2,GCos(a)*h/2,RGB($40,$40,$40)) 
    Next a 
  StopDrawing() 

EndProcedure 


;- Start 
If InitKeyboard()=0 Or InitSprite()=0
  MessageRequester("ERROR","Cant init DirectX !") 
EndIf 

If OpenScreen(#Width,#Height,32,"Radar")=0 
  If OpenScreen(#Width,#Height,24,"Radar")=0 
    If OpenScreen(#Width,#Height,16,"Radar")=0 
      MessageRequester("ERROR","Cant open screen !") 
EndIf:EndIf:EndIf 
SetFrameRate(60)

MakeSprites() 


;- Init objects
;AddElement(Objects())
;Objects()\x      = (#Width/2-16)  -#Height/4+50 
;Objects()\y      = (#Height/2-16) +#Height/4+50 
;Objects()\Degree = 30 

;- Main loop 
Repeat 
  time = ElapsedMilliseconds()
  ExamineKeyboard()
  If IsScreenActive() And ScreenDeactivated = #False
      If KeyboardReleased(#PB_Key_Space)
          reverse ! 1
      EndIf
    If reverse = 0
        angle.f - #rotator_speed
    Else
        angle.f + #rotator_speed
    EndIf
    If angle < 0:angle+360:EndIf
    If angle > 360:angle-360:EndIf
    ClearScreen(0) 
    SpriteQuality(1) 
    ZoomSprite(reverse,#Height-100,#Height-100) 
    RotateSprite(reverse,angle,#PB_Absolute)
    DisplaySprite(reverse,(#Width-#Height)/2+50,50) 

    ;SpriteBlendingMode(5,2)
    
    ForEach Objects()
        ; display objects
    Next
    
    DisplayTransparentSprite(3,(#Width-#Height)/2+50,50,255) 

  ElseIf ScreenDeactivated = #False 
    ScreenDeactivated = #True 
  ElseIf IsScreenActive() And ScreenDeactivated = #True 
      ScreenDeactivated = #False 
      FlipBuffers() 
      MakeSprites() 
  EndIf 
  FlipBuffers() 
  Repeat:Delay(1):Until ElapsedMilliseconds()-20>=time 
Until KeyboardPushed(#PB_Key_Escape) 
;- End
Added SPACE key to reverse the radar (CW vs CCW).
Removed the objects and blending mode, don't understand what you want to display exactly.

Re: how to improve 2d performance and some bugs ?

Posted: Fri Aug 02, 2013 10:12 am
by Kukulkan
I agree, sprites will be much more faster and also better looking.

For example, I would recommend a rotating sprite with the fading trail to get the radar-effect. Also some sprites as hits etc.

Best,

Kukulkan

Re: how to improve 2d performance and some bugs ?

Posted: Sat Aug 03, 2013 9:36 pm
by mohscorpion
lemme explain more what i am trying to do
my application will be a like a radar , getting data from a network stream based on angle and points to display
so what i get is actually is like 4096 packets containing angle ( from north ) and points .
i am trying to replace .net application with purebasic and show simplicity and performance of purebasic .
so sweeper rotates at different speeds like 48/24/12 rpm and it displays points in each angle .
in my sample program i simulated a 360 angle sweep by 1 degree step and some random points to show (to compare to .net counterpart's performance ).