Author Topic: Programming Fast circle code for OpenGL  (Read 8830 times)

Offline peterb

  • Bot Destroyer
  • ***
  • Posts: 148
    • View Profile
Programming Fast circle code for OpenGL
« on: April 22, 2010, 07:33:50 PM »
FAST Circle draw routine

Below a fast routine to draw a complete circle in OpenGL
Since other programmers here can benefit from it, i drop the code here
.
My demo code is mainly a routine which does draw a lot of circles about 166 from small to large.
It does draw a lot of circles which seams to 'scrol by' but in fact they're all redrawn so it shows the speed of this routine..
Usually drawing large circles is a slow operation....
Its fast because i minimize complex math like sin and cos (which in this language is called sind and cosd).
It should require little conversion to rewrite this to C++ as i used Basic4GL which nativly supports openGL v1.0

main routine splits the drawing and start drawing from top bottem and both sides.
lines will be drawn till 45 degrees since i start from 4 sides, at 45 degrees the lines connect to a circle.
Delta defines how often splits are made (and so a one time recalculate with cos and sin is needed).

the code can even be more optimized for real small circles (using a few sprites)


I found an equivalent for line(x1,y2,x2,y2) in the OpenGL command   glBegin(GL_lines) (see pic below code)


This code runs in Basic4GL (handy to test openGL routines), it not a full blown language like vb6, vb.net, or c++
But typing is easy and since it uses openGL its amazing Fast.. (but not complete enough to make DB clone in it, lacks mod function and others).

[div class=\'codetop\']CODE[div class=\'codemain\' style=\'height:200px;white-space:pre;overflow:auto\']
const Xsize = 1000, ysize = 600
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho (0, Xsize,Ysize, 0,0,1)
glMatrixmode(GL_MODELVIEW)
     
'turn of depth
 glDisable(GL_DEPTH_TEST)        
'clear screen
 glClear(GL_COLOR_BUFFER_BIT)          
 
          'http://basic4gl.wikispaces.com/2D+Drawing+in+OpenGL  
dim radius as integer
dim xpos,ypos  
dim w1,h1,w2,h2,corner,delta,i
   
for i =1 to 800  
xpos = -400+i
ypos = -400 +i    
     
       
 For radius = 0 to 500 step 3
     
        glClear(GL_COLOR_BUFFER_BIT)  
        glBegin(GL_LINES)  
        corner = 0
        w1 =  0
        h1 = radius
       

    if radius < 300 then delta = 6     endif
    if radius < 280 then delta = 10    endif
    if radius < 100 then delta = 15    endif
    if radius < 60  then delta = 22    endif
    if radius < 15  then delta = 45    endif
      while  corner <46
        corner = corner + delta
                                         
        w2 = radius * sind(corner)
        h2 = radius * cosd(corner)
         glVertex2f(xpos+w1, ypos+h1): glVertex2f(xpos+w2, ypos+h2)
         glVertex2f(xpos-w1, ypos+h1): glVertex2f(xpos-w2, ypos+h2)
         glVertex2f(xpos+w1, ypos-h1): glVertex2f(xpos+w2, ypos-h2)
         glVertex2f(xpos-w1, ypos-h1): glVertex2f(xpos-w2, ypos-h2)
         glVertex2f(xpos+h1, ypos+w1): glVertex2f(xpos+h2, ypos+w2)
         glVertex2f(xpos-h1, ypos+w1): glVertex2f(xpos-h2, ypos+w2)
         glVertex2f(xpos+h1, ypos-w1): glVertex2f(xpos+h2, ypos-w2)
         glVertex2f(xpos-h1, ypos-w1): glVertex2f(xpos-h2, ypos-w2)
   
          w1 = w2
          h1 = h2
          wend
   
       next
        glend()


line types
« Last Edit: April 22, 2010, 08:03:51 PM by peterb »

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Programming Fast circle code for OpenGL
« Reply #1 on: April 23, 2010, 01:04:49 PM »
glu is just a wrapper around OpenGL, so it shouldn't be faster than well formatted OpenGL.

Offline peterb

  • Bot Destroyer
  • ***
  • Posts: 148
    • View Profile
Programming Fast circle code for OpenGL
« Reply #2 on: April 24, 2010, 06:31:38 PM »
Quote from: Numsgil
glu is just a wrapper around OpenGL, so it shouldn't be faster than well formatted OpenGL.

So then this code this OK then


Hmm the only improvement left might be to replace the sind and cond with an array with a depth of 5 (dont require more values since i use only a few angles
well maybe thats not even required such a large circles are not practical in DB

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Programming Fast circle code for OpenGL
« Reply #3 on: April 25, 2010, 02:56:22 PM »
Quote from: peterb
Quote from: Numsgil
glu is just a wrapper around OpenGL, so it shouldn't be faster than well formatted OpenGL.

So then this code this OK then

Well you could use a display list.  Essentially it'd be like creating a precomputed stamp of a circle.  Then you could feel free to use sin and cos all you want since it would only get called once, and then cached afterwards.

Offline peterb

  • Bot Destroyer
  • ***
  • Posts: 148
    • View Profile
Programming Fast circle code for OpenGL
« Reply #4 on: April 26, 2010, 07:44:39 AM »
Quote from: Numsgil
Quote from: peterb
Quote from: Numsgil
glu is just a wrapper around OpenGL, so it shouldn't be faster than well formatted OpenGL.

So then this code this OK then

Well you could use a display list.  Essentially it'd be like creating a precomputed stamp of a circle.  Then you could feel free to use sin and cos all you want since it would only get called once, and then cached afterwards.


hmm i like to minimize cos and sin calls since these functions are complex and thus slow i think.
I'm not sure if darwin bots works with a bots direction, or rather with a deltaX & deltaY ( i think sin cos are only required when a collision occurs
Circle collisions might however be more complex, since a small circle can bump into a larger one... hmm collision checks must be a whole big topic..

Offline ikke

  • Bot Destroyer
  • ***
  • Posts: 300
    • View Profile
Programming Fast circle code for OpenGL
« Reply #5 on: April 26, 2010, 11:58:52 AM »
Quote from: peterb
hmm i like to minimize cos and sin calls since these functions are complex and thus slow i think.
I'm not sure if darwin bots works with a bots direction, or rather with a deltaX & deltaY ( i think sin cos are only required when a collision occurs
Circle collisions might however be more complex, since a small circle can bump into a larger one... hmm collision checks must be a whole big topic..
Bots don't have a fixed heading and rotation (angles) equals sine & cosine, implicit or explicit

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Programming Fast circle code for OpenGL
« Reply #6 on: April 26, 2010, 12:41:13 PM »
Quote from: peterb
hmm i like to minimize cos and sin calls since these functions are complex and thus slow i think.
I'm not sure if darwin bots works with a bots direction, or rather with a deltaX & deltaY ( i think sin cos are only required when a collision occurs
Circle collisions might however be more complex, since a small circle can bump into a larger one... hmm collision checks must be a whole big topic..

You would be fine to use sin and cos, since they're only called once when you build the display list.  After that the vertex positions end up being stored on the graphics card.  So it beats out trying to re-send the data across the bus for every circle for every frame.

Internally Havok uses vectors (deltaX, deltaY).  We only call sine or cosine when we convert things to angles for use in sysvars.

sin and cos are actually not as slow as you might think on a computer.  Only about the cost of 20 floating point multiplies or something like that.  It's a hardware call that gets evaluated by the FPU on the processor.  So if you can't get around sin/cos calls using vectors, you're almost always better off performance-wise just calling sin/cos instead of trying to approximate them in software.

Offline peterb

  • Bot Destroyer
  • ***
  • Posts: 148
    • View Profile
Programming Fast circle code for OpenGL
« Reply #7 on: April 28, 2010, 02:19:00 PM »
Quote
You would be fine to use sin and cos, since they're only called once when you build the display list.  After that the vertex positions end up being stored on the graphics card.  So it beats out trying to re-send the data across the bus for every circle for every frame.

ehm .. ??
How does that work my routine uses a minimum of sin cos commands but their values, you can store them in the graphic card ???
the routine is a buildup of lines from 8 start points my circle (from top left right and bottem, in 2 directions makes 8)

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Programming Fast circle code for OpenGL
« Reply #8 on: April 28, 2010, 10:56:08 PM »
Quote from: peterb
Quote
You would be fine to use sin and cos, since they're only called once when you build the display list.  After that the vertex positions end up being stored on the graphics card.  So it beats out trying to re-send the data across the bus for every circle for every frame.

ehm .. ??
How does that work my routine uses a minimum of sin cos commands but their values, you can store them in the graphic card ???

Yes.  More to the point, graphics cards can only draw things which are stored in a hardware buffer anyway.  So your openGL commands get converted in to that anyway.

Offline peterb

  • Bot Destroyer
  • ***
  • Posts: 148
    • View Profile
Programming Fast circle code for OpenGL
« Reply #9 on: April 29, 2010, 06:49:00 AM »
Quote from: Numsgil
Quote from: peterb
Quote
You would be fine to use sin and cos, since they're only called once when you build the display list.  After that the vertex positions end up being stored on the graphics card.  So it beats out trying to re-send the data across the bus for every circle for every frame.

ehm .. ??
How does that work my routine uses a minimum of sin cos commands but their values, you can store them in the graphic card ???

Yes.  More to the point, graphics cards can only draw things which are stored in a hardware buffer anyway.  So your openGL commands get converted in to that anyway.

I'm not sure if i'm following this you mean that a 'drawn' object is stored in the graphics card
And so you can then adres a whole object like move all the lines by 1 vector ??  (moving a poly line)
(so no redraw of the complete circle ?), only have one command like move object(XXX) by vector(x,y,z)   //z=0
In my sample i just redraw each frame.
If move by vector is possible that would be way faster..




Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Programming Fast circle code for OpenGL
« Reply #10 on: April 29, 2010, 07:00:23 PM »
Quote from: peterb
I'm not sure if i'm following this you mean that a 'drawn' object is stored in the graphics card

So it's quite possible I'm just confusing you.  In which case ignore moe.  But the vertex positions, color information, etc. are, yes.  The graphics cards have on board memory (called VRAM).  They're basically an entirely separate computer inside your system.  They can only draw things which they have in memory.  When you use the immediate mode OpenGL calls, the graphics driver figures out some way to send them to the garphics card's memory for the one frame you want to draw, then it discards them unless you tell it otherwise.

Quote
And so you can then adres a whole object like move all the lines by 1 vector ??  (moving a poly line)
(so no redraw of the complete circle ?), only have one command like move object(XXX) by vector(x,y,z)   //z=0
In my sample i just redraw each frame.
If move by vector is possible that would be way faster..

Yes.  Vertices are transformed by a matrix before they are drawn.  So you just have to change the matrix and you can rotate, scale, scew, transform, etc. an "object" (consisting of vertices).