Using RingOpenGL and RingFreeGLUT for 3D Graphics

In this chapter we will learn about using RingOpenGL

Samples Source (Authors)

The samples in this chapter are based on C Tutorials

from

  1. http://www.lighthouse3d.com/tutorials/glut-tutorial/
  2. http://www.wikihow.com/Make-a-Cube-in-OpenGL

What is RingOpenGL?

RingOpenGL contains the Ring binding to the OpenGL library

You can learn about OpenGL from : https://www.opengl.org/

RingOpenGL comes with support for the next versions

  • OpenGL 1.1
  • OpenGL 1.2
  • OpenGL 1.3
  • OpenGL 1.4
  • OpenGL 1.5
  • OpenGL 2.0
  • OpenGL 2.1
  • OpenGL 3.0
  • OpenGL 3.2
  • OpenGL 3.3
  • OpenGL 4.0
  • OpenGL 4.1
  • OpenGL 4.2
  • OpenGL 4.3
  • OpenGL 4.4
  • OpenGL 4.5
  • OpenGL 4.6

For example, if you want to use OpenGL 2.1 then load RingOpenGL 2.1 library

load "opengl21lib.ring"

What is RingFreeGLUT?

RingFreeGLUT contains the Ring binding to the FreeGLUT library

You can learn about FreeGLUT from : http://freeglut.sourceforge.net/

To use the RingFreeGLUT library, Just load the library

load "freeglut.ring"

The First Window using RingFreeGLUT

Example:

load "freeglut.ring"

func main
        glutInit()
        glutInitDisplayMode(GLUT_SINGLE)
        glutInitWindowSize(800, 600)
        glutInitWindowPosition(100, 10)
        glutCreateWindow("RingFreeGLUT - Test 1")
        glutDisplayFunc(:displayCode)
        glutMainLoop()

func displaycode

Screen Shot

RingFreeGLUT

Drawing using RingOpenGL

Example:

load "freeglut.ring"
load "opengl21lib.ring"


func main
        glutInit()
        glutInitDisplayMode(GLUT_SINGLE)
        glutInitWindowSize(800, 600)
        glutInitWindowPosition(100, 10)
        glutCreateWindow("RingFreeGLUT - Test 2")
        glutDisplayFunc(:displayCode)
        glutMainLoop()

func displaycode
        glClear(GL_COLOR_BUFFER_BIT)
        glColor3f(0,255,0)
        glBegin(GL_POLYGON)
                glVertex3f(0.0, 0.0, 0.0)
                glVertex3f(0.5, 0.0, 0.0)
                glVertex3f(0.5, 0.5, 0.0)
                glVertex3f(0.0, 0.5, 0.0)
        glEnd()
        glColor3f(255,0,0)
        glBegin(GL_POLYGON)
                glVertex3f(0.0, 0.0, 0.0)
                glVertex3f(0.5, 0.0, 0.0)
                glVertex3f(-0.5,- 1, 0.0)
                glVertex3f(0.0, -1, 0.0)
        glEnd()
        glColor3f(0,0,255)
        glBegin(GL_POLYGON)
               glVertex3f(0.0, 0.0, 0.0)
                glVertex3f(-0.5, 0.0, 0.0)
                glVertex3f(-0.5,- 0.5, 0.0)
                glVertex3f(0.0, -0.5, 0.0)
        glEnd()

        glFlush()

Screen Shot

RingFreeGLUT

The First Triangle

Example:

load "freeglut.ring"
load "opengl21lib.ring"

func main
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowSize(320,320)
        glutInitWindowPosition(100, 10)
        glutCreateWindow("RingFreeGLUT - Test 3")
        glutDisplayFunc(:renderScene)
        glutMainLoop()

func renderScene

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glBegin(GL_TRIANGLES)
                glVertex3f(-0.5,-0.5,0.0)
                glVertex3f(0.5,0.0,0.0)
                glVertex3f(0.0,0.5,0.0)
        glEnd()

        glutSwapBuffers()

Screen Shot

RingFreeGLUT

Window Resize Event

Example:

load "freeglut.ring"
load "opengl21lib.ring"

func main

        // init GLUT and create window
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test 4")

        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)

        glutMainLoop()

func renderScene

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glBegin(GL_TRIANGLES)
                glVertex3f(-2,-2,-5.0)
                glVertex3f(2,0.0,-5.0)
                glVertex3f(0.0,2,-5.0)
        glEnd()

        glutSwapBuffers()

func changesize

        h = glutEventHeight()
        w = glutEventWidth()

                // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if (h = 0)
                h = 1
        ok

        ratio =  w * 1.0 / h

        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        // Reset Matrix
        glLoadIdentity()

        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45,ratio,1,100)

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)

Triangle Rotation

Example:

load "freeglut.ring"
load "opengl21lib.ring"

angle = 0

func main

        // init GLUT and create window
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test 5")

        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)
        glutIdleFunc(:renderScene)

        glutMainLoop()

func renderScene

        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        // Reset transformations
        glLoadIdentity()
        // Set the camera
        gluLookAt(      0.0, 0.0, 10.0,
                                0.0, 0.0,  0.0,
                                0.0, 1.0,  0.0)

        glRotatef(angle, 0.0, 1.0, 0.0)

        glBegin(GL_TRIANGLES)
                glVertex3f(-2.0,-2.0, 0.0)
                glVertex3f( 2.0, 0.0, 0.0)
                glVertex3f( 0.0, 2.0, 0.0)
        glEnd()

        angle+=0.1

        glutSwapBuffers();

func changesize

        h = glutEventHeight()
        w = glutEventWidth()

                // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if (h = 0)
                h = 1
        ok

        ratio =  w * 1.0 / h

        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        // Reset Matrix
        glLoadIdentity()

        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45,ratio,1,100)

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)

Screen Shot

RingFreeGLUT

Keyboard Events and Colors

Example:

load "freeglut.ring"
load "opengl21lib.ring"

angle = 0

red=1.0
blue=1.0
green=1.0

func main

        // init GLUT and create window
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test 6")

        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)
        glutIdleFunc(:renderScene)

        // here are the new entries
        glutKeyboardFunc(:processNormalKeys)
        glutSpecialFunc(:processSpecialKeys)

        glutMainLoop()

func renderScene

        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        // Reset transformations
        glLoadIdentity()
        // Set the camera
        gluLookAt(      0.0, 0.0, 10.0,
                                0.0, 0.0,  0.0,
                                0.0, 1.0,  0.0)

        glRotatef(angle, 0.0, 1.0, 0.0)


        glColor3f(red,green,blue);

        glBegin(GL_TRIANGLES)
                glVertex3f(-2.0,-2.0, 0.0)
                glVertex3f( 2.0, 0.0, 0.0)
                glVertex3f( 0.0, 2.0, 0.0)
        glEnd()

        angle+=0.1

        glutSwapBuffers();

func changesize

        h = glutEventHeight()
        w = glutEventWidth()

                // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if (h = 0)
                h = 1
        ok

        ratio =  w * 1.0 / h

        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        // Reset Matrix
        glLoadIdentity()

        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45,ratio,1,100)

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)

func processNormalKeys
        key = GLUTEventKey()
        if key = 27
                shutdown()
        ok

func processSpecialKeys

        key = GLUTEventKey()

        switch key
                on GLUT_KEY_F1
                                red = 1.0
                                green = 0.0
                                blue = 0.0
                on GLUT_KEY_F2
                                red = 0.0
                                green = 1.0
                                blue = 0.0
                on GLUT_KEY_F3
                                red = 0.0
                                green = 0.0
                                blue = 1.0
        off

Screen Shot

RingFreeGLUT

The Camera

Example:

load "freeglut.ring"
load "opengl21lib.ring"

// angle of rotation for the camera direction
angle=0.0
// actual vector representing the camera's direction
lx=0.0
lz=-1.0
// XZ position of the camera
x=0.0
z=5.0

func drawSnowMan

        glColor3f(1.0, 1.0, 1.0)

// Draw Body
        glTranslatef(0.0 ,0.75, 0.0)
        glutSolidSphere(0.75,20,20)

// Draw Head
        glTranslatef(0.0, 1.0, 0.0)
        glutSolidSphere(0.25,20,20)

// Draw Eyes
        glPushMatrix()
        glColor3f(0.0,0.0,0.0)
        glTranslatef(0.05, 0.10, 0.18)
        glutSolidSphere(0.05,10,10)
        glTranslatef(-0.1, 0.0, 0.0)
        glutSolidSphere(0.05,10,10)

        glPopMatrix()

// Draw Nose
        glColor3f(1.0, 0.5 , 0.5)
        glutSolidCone(0.08,0.5,10,2)


func changeSize
        w = glutEventWidth()
        h = glutEventHeight()

        // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if h = 0
                h = 1
        ok

        ratio =  w * 1.0  / h

                // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

                // Reset Matrix
        glLoadIdentity()


        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45.0, ratio, 0.1, 100.0);

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)


func processNormalKeys
        key = glutEventKey()

        if key = 27
                shutdown()
        ok



func renderScene

        // Clear Color and Depth Buffers

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        // Reset transformations
        glLoadIdentity()
        // Set the camera
        gluLookAt(      x, 1.0, z,
                        x+lx, 1.0,  z+lz,
                        0.0, 1.0,  0.0)

                // Draw ground

        glColor3f(0.9, 0.9, 0.9)
        glBegin(GL_QUADS)
                glVertex3f(-100.0, 0.0, -100.0)
                glVertex3f(-100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0, -100.0)
        glEnd()

                // Draw 36 SnowMen
        for i = -3 to 2
                for  j=-3 to 2
                        glPushMatrix()
                        glTranslatef(i*10.0,0,j * 10.0)
                        drawSnowMan()
                        glPopMatrix()
                next
        next
        glutSwapBuffers()




func processSpecialKeys

        key = glutEventKey()

        fraction = 0.1

        switch key
                on GLUT_KEY_LEFT
                        angle -= 0.01
                        lx = sin(angle)
                        lz = -cos(angle)
                on GLUT_KEY_RIGHT
                        angle += 0.01
                        lx = sin(angle)
                        lz = -cos(angle)
                on GLUT_KEY_UP
                        x += lx * fraction
                        z += lz * fraction
                on GLUT_KEY_DOWN
                        x -= lx * fraction
                        z -= lz * fraction
        off


func main

        // init GLUT and create window

        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)

        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test 7")

        // register callbacks
        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)
        glutIdleFunc(:renderScene)
        glutKeyboardFunc(:processNormalKeys)
        glutSpecialFunc(:processSpecialKeys)

        // OpenGL init
        glEnable(GL_DEPTH_TEST)

        // enter GLUT event processing cycle
        glutMainLoop()

Screen Shot

RingFreeGLUT

Another Example:

load "freeglut.ring"
load "opengl21lib.ring"

// angle of rotation for the camera direction
angle = 0.0

// actual vector representing the camera's direction
lx=0.0 lz=-1.0

// XZ position of the camera
x=0.0 z=5.0
// the key states. These variables will be zero
//when no key is being presses
deltaAngle = 0.0
deltaMove = 0

func changeSize
        w = glutEventWidth()
        h = glutEventHeight()

        // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if h = 0
                h = 1
        ok

        ratio =  w * 1.0 / h

        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        // Reset Matrix
        glLoadIdentity()

        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45.0, ratio, 0.1, 100.0)

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)


func drawSnowMan

        glColor3f(1.0, 1.0, 1.0)

// Draw Body

        glTranslatef(0.0 ,0.75, 0.0)
        glutSolidSphere(0.75,20,20)

// Draw Head
        glTranslatef(0.0, 1.0, 0.0)
        glutSolidSphere(0.25,20,20)

// Draw Eyes
        glPushMatrix()
        glColor3f(0.0,0.0,0.0)
        glTranslatef(0.05, 0.10, 0.18)
        glutSolidSphere(0.05,10,10)
        glTranslatef(-0.1, 0.0, 0.0)
        glutSolidSphere(0.05,10,10)
        glPopMatrix()

// Draw Nose
        glColor3f(1.0, 0.5 , 0.5)
        glRotatef(0.0,1.0, 0.0, 0.0)
        glutSolidCone(0.08,0.5,10,2)


func computePos deltaMove

        x += deltaMove * lx * 0.1
        z += deltaMove * lz * 0.1


func computeDir deltaAngle

        angle += deltaAngle
        lx = sin(angle)
        lz = -cos(angle)

func renderScene

        if deltaMove
                computePos(deltaMove)
        ok

        if deltaAngle
                computeDir(deltaAngle)
        ok

        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        // Reset transformations
        glLoadIdentity()
        // Set the camera
        gluLookAt(      x, 1.0, z,
                                x+lx, 1.0,  z+lz,
                                0.0, 1.0,  0.0)

// Draw ground

        glColor3f(0.9, 0.9, 0.9)
        glBegin(GL_QUADS)
                glVertex3f(-100.0, 0.0, -100.0)
                glVertex3f(-100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0, -100.0)
        glEnd()

// Draw 36 SnowMen

        for i = -3 to 2
                for j=-3 to 2
                        glPushMatrix()
                        glTranslatef(i*10.0,0,j * 10.0)
                        drawSnowMan()
                        glPopMatrix()
                next
        next
        glutSwapBuffers()


func pressKey
        key = glutEventKey()
        xx = glutEventX()
        yy = glutEventY()

        switch key
                on GLUT_KEY_LEFT
                         deltaAngle = -0.01
                on GLUT_KEY_RIGHT
                         deltaAngle = 0.01
                on GLUT_KEY_UP
                         deltaMove = 0.5
                on GLUT_KEY_DOWN
                        deltaMove = -0.5
        off

func releaseKey

        key = glutEventKey()

        switch key
                on GLUT_KEY_LEFT
                        deltaAngle = 0.0
                on GLUT_KEY_RIGHT
                        deltaAngle = 0.0
                on GLUT_KEY_UP
                        deltaMove = 0
                on GLUT_KEY_DOWN
                        deltaMove = 0
        off

func main

        // init GLUT and create window
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test 8")

        // register callbacks
        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)
        glutIdleFunc(:renderScene)

        glutSpecialFunc(:pressKey)

        // here are the new entries
        glutIgnoreKeyRepeat(1)
        glutSpecialUpFunc(:releaseKey)

        // OpenGL init
        glEnable(GL_DEPTH_TEST)

        // enter GLUT event processing cycle
        glutMainLoop()

Mouse Events

Example:

load "freeglut.ring"
load "opengl21lib.ring"

// angle of rotation for the camera direction
angle = 0.0

// actual vector representing the camera's direction
lx=0.0 lz=-1.0

// XZ position of the camera
x=0.0  z=5.0

// the key states. These variables will be zero
//when no key is being presses
deltaAngle = 0.0
deltaMove = 0.0
xOrigin = -1

func changeSize
        w = glutEventWidth()
        h = glutEventHeight()

        // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if h = 0
                h = 1
        ok

        ratio =  w * 1.0 / h

        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        // Reset Matrix
        glLoadIdentity()

        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45.0, ratio, 0.1, 100.0)

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)


func drawSnowMan

        glColor3f(1.0, 1.0, 1.0)

        // Draw Body
        glTranslatef(0.0 ,0.75, 0.0)
        glutSolidSphere(0.75,20,20)

        // Draw Head
        glTranslatef(0.0, 1.0, 0.0)
        glutSolidSphere(0.25,20,20)

        // Draw Eyes
        glPushMatrix()
        glColor3f(0.0,0.0,0.0)
        glTranslatef(0.05, 0.10, 0.18)
        glutSolidSphere(0.05,10,10)
        glTranslatef(-0.1, 0.0, 0.0)
        glutSolidSphere(0.05,10,10)
        glPopMatrix()

        // Draw Nose
        glColor3f(1.0, 0.5 , 0.5)
        glRotatef(0.0,1.0, 0.0, 0.0)
        glutSolidCone(0.08,0.5,10,2)


func computePos deltaMove

        x += deltaMove * lx * 0.1
        z += deltaMove * lz * 0.1

func renderScene

        if deltaMove
                computePos(deltaMove)
        ok

        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        // Reset transformations
        glLoadIdentity()
        // Set the camera
        gluLookAt(      x, 1.0, z,
                        x+lx, 1.0,  z+lz,
                        0.0, 1.0,  0.0)

        // Draw ground

        glColor3f(0.9, 0.9, 0.9)
        glBegin(GL_QUADS)
                glVertex3f(-100.0, 0.0, -100.0)
                glVertex3f(-100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0, -100.0)
        glEnd()

        // Draw 36 SnowMen

        for i = -3 to 2
                for  j=-3 to 2
                                         glPushMatrix()
                                         glTranslatef(i*10.0,0,j * 10.0)
                                         drawSnowMan()
                                         glPopMatrix()
                 next
        next
        glutSwapBuffers()

func processNormalKeys

        key  = glutEventKey()

                if key = 27
                         shutdown()
                ok


func pressKey
        key  = glutEventKey()

           switch key
                         on GLUT_KEY_UP
                                deltaMove = 0.5
                         on GLUT_KEY_DOWN
                                 deltaMove = -0.5
           off


func releaseKey
        key  = glutEventKey()
                switch key
                         on GLUT_KEY_UP
                                deltaMove = 0
                         on GLUT_KEY_DOWN
                                deltaMove = 0
                off


func mouseMove
        xx = glutEventX()
        yy = glutEventY()
                // this will only be true when the left button is down
                if xOrigin >= 0

                // update deltaAngle
                deltaAngle = (xx - xOrigin) * 0.001

                // update camera's direction
                lx = sin(angle + deltaAngle)
                lz = -cos(angle + deltaAngle)
        ok



func mouseButton

        button  = glutEventButton()
        state = glutEventState()
        xx = glutEventX()
        yy = glutEventY()

        // only start motion if the left button is pressed
        if button = GLUT_LEFT_BUTTON
                // when the button is released
                if state = GLUT_UP
                        angle += deltaAngle
                        xOrigin = -1
                else
                        // state = GLUT_DOWN
                        xOrigin = xx
                ok
                fflush(stdout)
        ok


func main

        // init GLUT and create window
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test 9")

        // register callbacks
        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)
        glutIdleFunc(:renderScene)

        glutIgnoreKeyRepeat(1)
        glutKeyboardFunc(:processNormalKeys)
        glutSpecialFunc(:pressKey)
        glutSpecialUpFunc(:releaseKey)

        // here are the two new functions
        glutMouseFunc(:mouseButton)
        glutMotionFunc(:mouseMove)

        // OpenGL init
        glEnable(GL_DEPTH_TEST)

        // enter GLUT event processing cycle
        glutMainLoop()

Using Fonts

Example:

load "freeglut.ring"
load "opengl21lib.ring"


// angle of rotation for the camera direction
angle = 0.0

// actual vector representing the camera's direction
lx=0.0 lz=-1.0

// XZ position of the camera
x=0.0  z=5.0

// the key states. These variables will be zero
//when no key is being presses
deltaAngle = 0.0
deltaMove = 0
xOrigin = -1

// Constant definitions for Menus
C_RED  = 1
C_GREEN = 2
C_BLUE = 3
C_ORANGE = 4

C_FILL = 5
C_LINE = 6

// Pop up menu identifiers
fillMenu=NULL
fontMenu=NULL
mainMenu=NULL
colorMenu=NULL

// color for the nose
red = 1.0
blue=0.5
green=0.5

// scale of snowman
scale = 1.0

// menu status
menuFlag = 0

// default font
font = GLUT_BITMAP_TIMES_ROMAN_24

C_INT_GLUT_BITMAP_8_BY_13 = 7
C_INT_GLUT_BITMAP_9_BY_15 = 8
C_INT_GLUT_BITMAP_TIMES_ROMAN_10  = 9
C_INT_GLUT_BITMAP_TIMES_ROMAN_24  = 10
C_INT_GLUT_BITMAP_HELVETICA_10  = 11
C_INT_GLUT_BITMAP_HELVETICA_12  = 12
C_INT_GLUT_BITMAP_HELVETICA_18  = 13

func changeSize
        w = glutEventWidth()
        h = glutEventHeight()

        // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if h = 0
                h = 1
        ok

        ratio =  w * 1.0 / h

        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        // Reset Matrix
        glLoadIdentity()

        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45.0, ratio, 0.1, 100.0)

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)

func drawSnowMan

        glScalef(scale, scale, scale)
        glColor3f(1.0, 1.0, 1.0)

// Draw Body
        glTranslatef(0.0 ,0.75, 0.0)
        glutSolidSphere(0.75,20,20)

// Draw Head
        glTranslatef(0.0, 1.0, 0.0)
        glutSolidSphere(0.25,20,20)

// Draw Eyes
        glPushMatrix()
        glColor3f(0.0,0.0,0.0)
        glTranslatef(0.05, 0.10, 0.18)
        glutSolidSphere(0.05,10,10)
        glTranslatef(-0.1, 0.0, 0.0)
        glutSolidSphere(0.05,10,10)
        glPopMatrix()

// Draw Nose
        glColor3f(red, green, blue)
        glRotatef(0.0,1.0, 0.0, 0.0)
        glutSolidCone(0.08,0.5,10,2)

        glColor3f(1.0, 1.0, 1.0)

func renderBitmapString x,y,z,font,string
        glRasterPos3f(x, y,z)
        for c in string
                glutBitmapCharacter(font,ascii(c))
        next


func computePos deltaMove

        x += deltaMove * lx * 0.1
        z += deltaMove * lz * 0.1


func renderScene

        if  deltaMove
                computePos(deltaMove)
        ok

        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        // Reset transformations
        glLoadIdentity()

        // Set the camera
        gluLookAt(      x, 1.0, z,
                        x+lx, 1.0,  z+lz,
                        0.0, 1.0,  0.0)

        // Draw ground

        glColor3f(0.9, 0.9, 0.9)
        glBegin(GL_QUADS)
                glVertex3f(-100.0, 0.0, -100.0)
                glVertex3f(-100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0, -100.0)
        glEnd()

// Draw 36 SnowMen
        for i = -3 to 2
                for j = -3 to 2
                        glPushMatrix()
                        glTranslatef(i*10.0, 0.0, j * 10.0)
                        drawSnowMan()
                        number = (i+3)*6+(j+3)
                        renderBitmapString(0.0, 0.5, 0.0,font ,""+number)
                        glPopMatrix()
                next
        next

        glutSwapBuffers()


// -----------------------------------
//             KEYBOARD
// -----------------------------------

func processNormalKeys
        key = glutEventKey()
        xx = glutEventX()
        yy = glutEventY()

        switch key
                on 27
                        glutDestroyMenu(mainMenu)
                        glutDestroyMenu(fillMenu)
                        glutDestroyMenu(colorMenu)
                        glutDestroyMenu(fontMenu)
                        Shutdown()
        off


func pressKey

        key = glutEventKey()
        xx = glutEventX()
        yy = glutEventY()

        switch key
                on GLUT_KEY_UP
                         deltaMove = 0.5
                on GLUT_KEY_DOWN
                        deltaMove = -0.5
        off


func releaseKey

        key = glutEventKey()

        switch key
                on GLUT_KEY_UP
                        deltaMove = 0
                on GLUT_KEY_DOWN
                        deltaMove = 0
        off


// -----------------------------------
//             MOUSE
// -----------------------------------

func mouseMove
        xx = glutEventX()
        yy = glutEventY()

        // this will only be true when the left button is down
        if xOrigin >= 0

                // update deltaAngle
                deltaAngle = (xx - xOrigin) * 0.001

                // update camera's direction
                lx = sin(angle + deltaAngle)
                lz = -cos(angle + deltaAngle)
        ok


func mouseButton

        button = glutEventButton()
        state = glutEventState()
        xx = glutEventX()
        yy = glutEventY()

        // only start motion if the left button is pressed
        if button = GLUT_LEFT_BUTTON
                // when the button is released
                if state = GLUT_UP
                        angle += deltaAngle
                        xOrigin = -1
                else
                        // state = GLUT_DOWN
                        xOrigin = xx
                ok
        ok


// -----------------------------------
//             MENUS
// -----------------------------------

func processMenuStatus

        status = glutEventStatus()

        if status = GLUT_MENU_IN_USE
                menuFlag = 1
        else
                menuFlag = 0
        ok


func processMainMenu

        // nothing to do in here
        // all actions are for submenus


func processFillMenu

        option = glutEventValue()

        switch option

                on C_FILL
                        glPolygonMode(GL_FRONT, GL_FILL)
                on C_LINE
                         glPolygonMode(GL_FRONT, GL_LINE)
        off


func processFontMenu

        option = glutEventValue()

        switch (option) {
                on C_INT_GLUT_BITMAP_8_BY_13
                        font = GLUT_BITMAP_8_BY_13
                on C_INT_GLUT_BITMAP_9_BY_15
                        font = GLUT_BITMAP_9_BY_15
                on C_INT_GLUT_BITMAP_TIMES_ROMAN_10
                        font = GLUT_BITMAP_TIMES_ROMAN_10
                on C_INT_GLUT_BITMAP_TIMES_ROMAN_24
                        font = GLUT_BITMAP_TIMES_ROMAN_24
                on C_INT_GLUT_BITMAP_HELVETICA_10
                        font = GLUT_BITMAP_HELVETICA_10
                on C_INT_GLUT_BITMAP_HELVETICA_12
                        font = GLUT_BITMAP_HELVETICA_12
                on C_INT_GLUT_BITMAP_HELVETICA_18
                        font = GLUT_BITMAP_HELVETICA_18
        off

func processColorMenu

        option = glutEventValue()

        switch option
                on C_RED
                        red = 1.0
                        green = 0.0
                        blue = 0.0
                on C_GREEN
                        red = 0.0
                        green = 1.0
                        blue = 0.0
                on C_BLUE
                        red = 0.0
                        green = 0.0
                        blue = 1.0
                on C_ORANGE
                        red = 1.0
                        green = 0.5
                        blue = 0.5
        off


func createPopupMenus

        fontMenu = glutCreateMenu(:processFontMenu)

        glutAddMenuEntry("BITMAP_8_BY_13 ",C_INT_GLUT_BITMAP_8_BY_13 )
        glutAddMenuEntry("BITMAP_9_BY_15",C_INT_GLUT_BITMAP_9_BY_15 )
        glutAddMenuEntry("BITMAP_TIMES_ROMAN_10 ",C_INT_GLUT_BITMAP_TIMES_ROMAN_10  )
        glutAddMenuEntry("BITMAP_TIMES_ROMAN_24",C_INT_GLUT_BITMAP_TIMES_ROMAN_24  )
        glutAddMenuEntry("BITMAP_HELVETICA_10 ",C_INT_GLUT_BITMAP_HELVETICA_10  )
        glutAddMenuEntry("BITMAP_HELVETICA_12",C_INT_GLUT_BITMAP_HELVETICA_12  )
        glutAddMenuEntry("BITMAP_HELVETICA_18",C_INT_GLUT_BITMAP_HELVETICA_18  )

        fillMenu = glutCreateMenu(:processFillMenu)

        glutAddMenuEntry("Fill",C_FILL)
        glutAddMenuEntry("Line",C_LINE)

        colorMenu = glutCreateMenu(:processColorMenu)
        glutAddMenuEntry("Red",C_RED);
        glutAddMenuEntry("Blue",C_BLUE);
        glutAddMenuEntry("Green",C_GREEN);
        glutAddMenuEntry("Orange",C_ORANGE);

        mainMenu = glutCreateMenu(:processMainMenu)

        glutAddSubMenu("Polygon Mode", fillMenu)
        glutAddSubMenu("Color", colorMenu)
        glutAddSubMenu("Font",fontMenu)
        // attach the menu to the right button
        glutAttachMenu(GLUT_RIGHT_BUTTON)

        // this will allow us to know if the menu is active
        glutMenuStatusFunc(:processMenuStatus)


// -----------------------------------
//             MAIN
// -----------------------------------

func main

        // init GLUT and create window
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test 11")

        // register callbacks
        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)
        glutIdleFunc(:renderScene)

        glutIgnoreKeyRepeat(1)
        glutKeyboardFunc(:processNormalKeys)
        glutSpecialFunc(:pressKey)
        glutSpecialUpFunc(:releaseKey)

        // here are the two new functions
        glutMouseFunc(:mouseButton)
        glutMotionFunc(:mouseMove)

        // OpenGL init
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)

        // init Menus
        createPopupMenus()

        // enter GLUT event processing cycle
        glutMainLoop()

Screen Shot

RingFreeGLUT

Frames Per Second

Example

load "freeglut.ring"
load "opengl21lib.ring"

// angle of rotation for the camera direction
angle = 0.0

// actual vector representing the camera's direction
lx=0.0 lz=-1.0

// XZ position of the camera
x=0.0  z=5.0

// the key states. These variables will be zero
//when no key is being presses
deltaAngle = 0.0
deltaMove = 0
xOrigin = -1

// Constant definitions for Menus
C_RED  = 1
C_GREEN = 2
C_BLUE = 3
C_ORANGE = 4

C_FILL = 5
C_LINE = 6

// Pop up menu identifiers
fillMenu=NULL
fontMenu=NULL
mainMenu=NULL
colorMenu=NULL

// color for the nose
red = 1.0
blue=0.5
green=0.5

// scale of snowman
scale = 1.0

// menu status
menuFlag = 0

// default font
font = GLUT_BITMAP_TIMES_ROMAN_24

C_INT_GLUT_BITMAP_8_BY_13 = 7
C_INT_GLUT_BITMAP_9_BY_15 = 8
C_INT_GLUT_BITMAP_TIMES_ROMAN_10  = 9
C_INT_GLUT_BITMAP_TIMES_ROMAN_24  = 10
C_INT_GLUT_BITMAP_HELVETICA_10  = 11
C_INT_GLUT_BITMAP_HELVETICA_12  = 12
C_INT_GLUT_BITMAP_HELVETICA_18  = 13

// width and height of the window
h = 0
w = 0

// variables to compute frames per second
frame=0
time=0
timebase=0
s = ""

func changeSize
        w = glutEventWidth()
        h = glutEventHeight()

        // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if h = 0
                h = 1
        ok

        ratio =  w * 1.0 / h

        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        // Reset Matrix
        glLoadIdentity()

        // Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        // Set the correct perspective.
        gluPerspective(45.0, ratio, 0.1, 100.0)

        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)

func drawSnowMan

        glScalef(scale, scale, scale)
        glColor3f(1.0, 1.0, 1.0)

// Draw Body
        glTranslatef(0.0 ,0.75, 0.0)
        glutSolidSphere(0.75,20,20)

// Draw Head
        glTranslatef(0.0, 1.0, 0.0)
        glutSolidSphere(0.25,20,20)

// Draw Eyes
        glPushMatrix()
        glColor3f(0.0,0.0,0.0)
        glTranslatef(0.05, 0.10, 0.18)
        glutSolidSphere(0.05,10,10)
        glTranslatef(-0.1, 0.0, 0.0)
        glutSolidSphere(0.05,10,10)
        glPopMatrix()

// Draw Nose
        glColor3f(red, green, blue)
        glRotatef(0.0,1.0, 0.0, 0.0)
        glutSolidCone(0.08,0.5,10,2)

        glColor3f(1.0, 1.0, 1.0)

func renderBitmapString x,y,z,font,string
        glRasterPos3f(x, y,z)
        for c in string
                glutBitmapCharacter(font,ascii(c))
        next

func renderStrokeFontString x,y,z,font,string
        glPushMatrix()
        glTranslatef(x, y,z)
        glScalef(0.002, 0.002, 0.002)
        for c in string
                glutStrokeCharacter(font, Ascii(c));
        next
        glPopMatrix()


func restorePerspectiveProjection

        glMatrixMode(GL_PROJECTION)
        // restore previous projection matrix
        glPopMatrix()

        // get back to modelview mode
        glMatrixMode(GL_MODELVIEW)


func setOrthographicProjection

        // switch to projection mode
        glMatrixMode(GL_PROJECTION)

        // save previous matrix which contains the
        //settings for the perspective projection
        glPushMatrix()

        // reset matrix
        glLoadIdentity()

        // set a 2D orthographic projection
        gluOrtho2D(0, w, h, 0)

        // switch back to modelview mode
        glMatrixMode(GL_MODELVIEW)



func computePos deltaMove

        x += deltaMove * lx * 0.1
        z += deltaMove * lz * 0.1


func renderScene

        if  deltaMove
                computePos(deltaMove)
        ok

        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        // Reset transformations
        glLoadIdentity()

        // Set the camera
        gluLookAt(      x, 1.0, z,
                        x+lx, 1.0,  z+lz,
                        0.0, 1.0,  0.0)

        // Draw ground

        glColor3f(0.9, 0.9, 0.9)
        glBegin(GL_QUADS)
                glVertex3f(-100.0, 0.0, -100.0)
                glVertex3f(-100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0,  100.0)
                glVertex3f( 100.0, 0.0, -100.0)
        glEnd()

// Draw 9 SnowMen
        for i = -3 to -1
                for j = -3 to -1
                        glPushMatrix()
                        glTranslatef(i*10.0, 0.0, j * 10.0)
                        drawSnowMan()
                        number = (i+3)*3+(j+3)
                        renderBitmapString(0.0, 0.5, 0.0,font ,""+number)
                        glPopMatrix()
                next
        next

        // Code to compute frames per second
        frame++

        time=glutGet(GLUT_ELAPSED_TIME)
        if time - timebase > 1000
                s = "RingFreeGLUT - FPS: " + (frame*1000.0/(time-timebase))
                timebase = time
                frame = 0
        ok

        // Code to display a string (fps) with bitmap fonts
        setOrthographicProjection()

        glPushMatrix()
        glLoadIdentity()
        renderBitmapString(5,30,0,GLUT_BITMAP_HELVETICA_18,s)
        glPopMatrix()

        restorePerspectiveProjection()

        glutSwapBuffers()


// -----------------------------------
//             KEYBOARD
// -----------------------------------

func processNormalKeys
        key = glutEventKey()
        xx = glutEventX()
        yy = glutEventY()

        switch key
                on 27
                        glutDestroyMenu(mainMenu)
                        glutDestroyMenu(fillMenu)
                        glutDestroyMenu(colorMenu)
                        glutDestroyMenu(fontMenu)
                        Shutdown()
        off


func pressKey

        key = glutEventKey()
        xx = glutEventX()
        yy = glutEventY()

        switch key
                on GLUT_KEY_UP
                         deltaMove = 0.5
                on GLUT_KEY_DOWN
                        deltaMove = -0.5
        off


func releaseKey

        key = glutEventKey()

        switch key
                on GLUT_KEY_UP
                        deltaMove = 0
                on GLUT_KEY_DOWN
                        deltaMove = 0
        off


// -----------------------------------
//             MOUSE
// -----------------------------------

func mouseMove
        xx = glutEventX()
        yy = glutEventY()

        // this will only be true when the left button is down
        if xOrigin >= 0

                // update deltaAngle
                deltaAngle = (xx - xOrigin) * 0.001

                // update camera's direction
                lx = sin(angle + deltaAngle)
                lz = -cos(angle + deltaAngle)
        ok


func mouseButton

        button = glutEventButton()
        state = glutEventState()
        xx = glutEventX()
        yy = glutEventY()

        // only start motion if the left button is pressed
        if button = GLUT_LEFT_BUTTON
                // when the button is released
                if state = GLUT_UP
                        angle += deltaAngle
                        xOrigin = -1
                else
                        // state = GLUT_DOWN
                        xOrigin = xx
                ok
        ok


// -----------------------------------
//             MENUS
// -----------------------------------

func processMenuStatus

        status = glutEventStatus()

        if status = GLUT_MENU_IN_USE
                menuFlag = 1
        else
                menuFlag = 0
        ok


func processMainMenu

        // nothing to do in here
        // all actions are for submenus


func processFillMenu

        option = glutEventValue()

        switch option

                on C_FILL
                        glPolygonMode(GL_FRONT, GL_FILL)
                on C_LINE
                         glPolygonMode(GL_FRONT, GL_LINE)
        off


func processFontMenu

        option = glutEventValue()

        switch (option) {
                on C_INT_GLUT_BITMAP_8_BY_13
                        font = GLUT_BITMAP_8_BY_13
                on C_INT_GLUT_BITMAP_9_BY_15
                        font = GLUT_BITMAP_9_BY_15
                on C_INT_GLUT_BITMAP_TIMES_ROMAN_10
                        font = GLUT_BITMAP_TIMES_ROMAN_10
                on C_INT_GLUT_BITMAP_TIMES_ROMAN_24
                        font = GLUT_BITMAP_TIMES_ROMAN_24
                on C_INT_GLUT_BITMAP_HELVETICA_10
                        font = GLUT_BITMAP_HELVETICA_10
                on C_INT_GLUT_BITMAP_HELVETICA_12
                        font = GLUT_BITMAP_HELVETICA_12
                on C_INT_GLUT_BITMAP_HELVETICA_18
                        font = GLUT_BITMAP_HELVETICA_18
        off

func processColorMenu

        option = glutEventValue()

        switch option
                on C_RED
                        red = 1.0
                        green = 0.0
                        blue = 0.0
                on C_GREEN
                        red = 0.0
                        green = 1.0
                        blue = 0.0
                on C_BLUE
                        red = 0.0
                        green = 0.0
                        blue = 1.0
                on C_ORANGE
                        red = 1.0
                        green = 0.5
                        blue = 0.5
        off


func createPopupMenus

        fontMenu = glutCreateMenu(:processFontMenu)

        glutAddMenuEntry("BITMAP_8_BY_13 ",C_INT_GLUT_BITMAP_8_BY_13 )
        glutAddMenuEntry("BITMAP_9_BY_15",C_INT_GLUT_BITMAP_9_BY_15 )
        glutAddMenuEntry("BITMAP_TIMES_ROMAN_10 ",C_INT_GLUT_BITMAP_TIMES_ROMAN_10  )
        glutAddMenuEntry("BITMAP_TIMES_ROMAN_24",C_INT_GLUT_BITMAP_TIMES_ROMAN_24  )
        glutAddMenuEntry("BITMAP_HELVETICA_10 ",C_INT_GLUT_BITMAP_HELVETICA_10  )
        glutAddMenuEntry("BITMAP_HELVETICA_12",C_INT_GLUT_BITMAP_HELVETICA_12  )
        glutAddMenuEntry("BITMAP_HELVETICA_18",C_INT_GLUT_BITMAP_HELVETICA_18  )

        fillMenu = glutCreateMenu(:processFillMenu)

        glutAddMenuEntry("Fill",C_FILL)
        glutAddMenuEntry("Line",C_LINE)

        colorMenu = glutCreateMenu(:processColorMenu)
        glutAddMenuEntry("Red",C_RED);
        glutAddMenuEntry("Blue",C_BLUE);
        glutAddMenuEntry("Green",C_GREEN);
        glutAddMenuEntry("Orange",C_ORANGE);

        mainMenu = glutCreateMenu(:processMainMenu)

        glutAddSubMenu("Polygon Mode", fillMenu)
        glutAddSubMenu("Color", colorMenu)
        glutAddSubMenu("Font",fontMenu)
        // attach the menu to the right button
        glutAttachMenu(GLUT_RIGHT_BUTTON)

        // this will allow us to know if the menu is active
        glutMenuStatusFunc(:processMenuStatus)


// -----------------------------------
//             MAIN
// -----------------------------------

func main

        // init GLUT and create window
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowPosition(100,100)
        glutInitWindowSize(320,320)
        glutCreateWindow("RingFreeGLUT - Test - 9 SnowMan")

        // register callbacks
        glutDisplayFunc(:renderScene)
        glutReshapeFunc(:changeSize)
        glutIdleFunc(:renderScene)

        glutIgnoreKeyRepeat(1)
        glutKeyboardFunc(:processNormalKeys)
        glutSpecialFunc(:pressKey)
        glutSpecialUpFunc(:releaseKey)

        // here are the two new functions
        glutMouseFunc(:mouseButton)
        glutMotionFunc(:mouseMove)

        // OpenGL init
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)

        // init Menus
        createPopupMenus()

        // enter GLUT event processing cycle
        glutMainLoop()

Screen Shots:

The First screen shot

RingFreeGLUT

The Second screen shot

RingFreeGLUT

Make a Cube using RingOpenGL and RingFreeGLUT

Example:

load "freeglut.ring"
load "opengl21lib.ring"

// ----------------------------------------------------------
// Global Variables
// ----------------------------------------------------------
rotate_y=0
rotate_x=0

// ----------------------------------------------------------
// display() Callback function
// ----------------------------------------------------------
func display

  //  Clear screen and Z-buffer
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

  // Reset transformations
  glLoadIdentity()

  // Rotate when user changes rotate_x and rotate_y
  glRotatef( rotate_x, 1.0, 0.0, 0.0 )
  glRotatef( rotate_y, 0.0, 1.0, 0.0 )

  //Multi-colored side - FRONT
  glBegin(GL_POLYGON)

  glColor3f( 1.0, 0.0, 0.0 )     glVertex3f(  0.5, -0.5, -0.5 )      # P1 is red
  glColor3f( 0.0, 1.0, 0.0 )     glVertex3f(  0.5,  0.5, -0.5 )      # P2 is green
  glColor3f( 0.0, 0.0, 1.0 )     glVertex3f( -0.5,  0.5, -0.5 )      # P3 is blue
  glColor3f( 1.0, 0.0, 1.0 )     glVertex3f( -0.5, -0.5, -0.5 )      # P4 is purple

  glEnd()

  // White side - BACK
  glBegin(GL_POLYGON)
  glColor3f(   1.0,  1.0, 1.0 )
  glVertex3f(  0.5, -0.5, 0.5 )
  glVertex3f(  0.5,  0.5, 0.5 )
  glVertex3f( -0.5,  0.5, 0.5 )
  glVertex3f( -0.5, -0.5, 0.5 )
  glEnd()

  // Purple side - RIGHT
  glBegin(GL_POLYGON)
  glColor3f(  1.0,  0.0,  1.0 )
  glVertex3f( 0.5, -0.5, -0.5 )
  glVertex3f( 0.5,  0.5, -0.5 )
  glVertex3f( 0.5,  0.5,  0.5 )
  glVertex3f( 0.5, -0.5,  0.5 )
  glEnd()

  // Green side - LEFT
  glBegin(GL_POLYGON)
  glColor3f(   0.0,  1.0,  0.0 )
  glVertex3f( -0.5, -0.5,  0.5 )
  glVertex3f( -0.5,  0.5,  0.5 )
  glVertex3f( -0.5,  0.5, -0.5 )
  glVertex3f( -0.5, -0.5, -0.5 )
  glEnd()

  // Blue side - TOP
  glBegin(GL_POLYGON)
  glColor3f(   0.0,  0.0,  1.0 )
  glVertex3f(  0.5,  0.5,  0.5 )
  glVertex3f(  0.5,  0.5, -0.5 )
  glVertex3f( -0.5,  0.5, -0.5 )
  glVertex3f( -0.5,  0.5,  0.5 )
  glEnd()

  // Red side - BOTTOM
  glBegin(GL_POLYGON)
  glColor3f(   1.0,  0.0,  0.0 )
  glVertex3f(  0.5, -0.5, -0.5 )
  glVertex3f(  0.5, -0.5,  0.5 )
  glVertex3f( -0.5, -0.5,  0.5 )
  glVertex3f( -0.5, -0.5, -0.5 )
  glEnd()

  glFlush()
  glutSwapBuffers()


// ----------------------------------------------------------
// specialKeys() Callback Function
// ----------------------------------------------------------
func specialKeys

        key = glutEventKey()

  //  Right arrow - increase rotation by 5 degree
        switch Key

        on GLUT_KEY_RIGHT
                rotate_y += 5

        //  Left arrow - decrease rotation by 5 degree
        on GLUT_KEY_LEFT
                rotate_y -= 5

        on GLUT_KEY_UP
                rotate_x += 5

        on GLUT_KEY_DOWN
                rotate_x -= 5

        off

  //  Request display update
  glutPostRedisplay()



// ----------------------------------------------------------
// main() function
// ----------------------------------------------------------
func main

  //  Initialize GLUT and process user parameters
  glutInit()

  //  Request double buffered true color window with Z-buffer
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

  // Create window
  glutCreateWindow("Awesome Cube")

  //  Enable Z-buffer depth test
  glEnable(GL_DEPTH_TEST)

  // Callback functions
  glutDisplayFunc(:display)
  glutSpecialFunc(:specialKeys)

  //  Pass control to GLUT for events
  glutMainLoop()

  //  Return to OS

Screen Shot:

RingOpenGL