OpenGL sample using Tao Framework
Posted: Tue Mar 17, 2009 7:20 pm
Still has a problem, maybe Tao related, at application exit it puts CPU at 100% and never exists. It is a pretty simple OpenGL demo
%% args -t:winexe -ref:System.Windows.Forms.dll -ref:System.Drawing.dll -ref:Tao.OpenGl.dll -ref:Tao.Platform.Windows.dll
#******************************************************************************
#* This project is a test harness for the TAO framework running from
#* Cobra. It creates a simple 3D rendering engine and game
#* loop that can respond to keyboard and mouse events.
#* Code by Jonathan Fritz <!-- e --><a href="mailto:jonfritz@gmail.com">jonfritz@gmail.com</a><!-- e --> - <!-- m --><a class="postlink" href="http://www.jonathanfritz.ca">http://www.jonathanfritz.ca</a><!-- m -->
#* Timing code adopted from Jan Tosovsky <!-- m --><a class="postlink" href="http://nio.astronomy.cz/vb/opengl.html">http://nio.astronomy.cz/vb/opengl.html</a><!-- m -->
#* Use as you wish, but please give credit where it is due
#* ported to Cobra by aguspiza
#*******************************************************************************
use Tao.OpenGl
use Tao.Platform.Windows
use System.Windows.Forms
use System.Drawing
class TaoTest
def main is shared
Application.run(Form1())
class Form1
inherits Form
const viewAngle as float32 = 102.0f32
const axisSize as float32 = 25.0f32
const nRange as float32 = 50.0f32
var tickStart as int64 = 0i64
var tickElapsed as int64 = 0i64
var rotSpeed as float64 = 0.2f64 #rotation speed for our triangle in degrees/second
var rotation as float32 = 0f32 #the amount that our triangle should be rotated
var paused as bool = false #is the engine paused or not?
var fpsCount as int32 = 0 #a counter to calculate fps
var components as System.ComponentModel.IContainer?
var glCtrl as SimpleOpenGlControl?
var tmrFPS as Timer?
cue init
listen .load, ref .onLoad
listen .resize, ref .onResize
listen .disposed, ref .onDisposed
.initializeComponent
def initializeComponent
.components = System.ComponentModel.Container()
.glCtrl = SimpleOpenGlControl()
.tmrFPS = Timer(.components)
.suspendLayout
#
#glCtrl
#
listen .glCtrl.keyPress, ref .gl_KeyPress
listen .glCtrl.paint, ref .gl_redrawHandler
.glCtrl.accumBits = 0 to uint8
.glCtrl.autoCheckErrors = false
.glCtrl.autoFinish = false
.glCtrl.autoMakeCurrent = true
.glCtrl.autoSwapBuffers = true
.glCtrl.backColor = Color.black
.glCtrl.colorBits = 32 to uint8
.glCtrl.depthBits = 16 to uint8
.glCtrl.dock = DockStyle.Fill
.glCtrl.location = Point(0, 0)
.glCtrl.name = "glCtrl"
.glCtrl.size = Size(440, 438)
.glCtrl.stencilBits = 0 to uint8
.glCtrl.tabIndex = 0
#
#tmrFPS
#
listen .tmrFPS.tick, ref .tmrFPS_Tick
.tmrFPS.enabled = true
.tmrFPS.interval = 1000
#
#Form1
#
.autoScaleDimensions = SizeF(6.0f32, 13.0f32)
.autoScaleMode = AutoScaleMode.Font
.clientSize = Size(440, 438)
.controls.add(.glCtrl)
.name = "Form1"
.text = "Tao Test App"
.resumeLayout(false)
def onLoad(sender, e as EventArgs) #Load
"""
called on app start, initializes form and opengl
set up the open gl control
"""
.glCtrl.initializeContexts
#set opengl clear colour to black
Gl.glClearColor(0, 0, 0, 0)
#set opengl options
Gl.glShadeModel(Gl.gl_SMOOTH) #until we get lighting working, we#ll use boring flat shading
Gl.glEnable(Gl.gl_DEPTH_TEST) #let#s enable depth testing so that objects are drawn in the correct order
Gl.glEnable(Gl.gl_CULL_FACE) #tell opengl to cull faces that are hidden from view
#our projection options are set here
.windowResizeHandler(.height, .width)
#our model view options are set here
Gl.glMatrixMode(Gl.gl_MODELVIEW) #put opengl in modelview matrix mode
Gl.glLoadIdentity #initialize the model view stack with the identity matrix
#make the form visible
.visible = true
.glCtrl.focus
#start the game loop
.gameLoop
def gameLoop
"""
the game loop - runs constantly while the app is running
"""
#a temporary variable for shuffling
#var lastTick as int32
#grab the current tick count
.tickStart = Kernel.getTickCount
#loop while game isn#t paused
while not .paused
#calculate the new elapsed time
lastTick = .tickElapsed to int
.tickElapsed = Kernel.getTickCount - .tickStart
.tickElapsed = ((lastTick + .tickElapsed) / 2) to int64
#let windows do stuff
System.Windows.Forms.Application.doEvents
#calculate object rotation (in degrees) based on deltaTime and rotSpeed
temp as float32= (.tickElapsed - lastTick) to float32
temp = temp * .rotSpeed to float32
.rotation = .rotation + temp
.rotation = .rotation % 360
#force a redraw of the screen
.glCtrl.invalidate
#up the fps counter
.fpsCount += 1
def gl_KeyPress(sender, e as KeyPressEventArgs) # glCtrl.KeyPress
"""
handles key press events during gameplay
"""
if e.keyChar == System.Windows.Forms.Keys.Escape to char
.paused = not .paused
#takes action based on paused value
if .paused == false
.gameLoop
else
.text = "Paused"
def gl_redrawHandler(sender, e as PaintEventArgs) # glCtrl.Paint
"""
this gets called whenever our opengl control is redrawn
put all of your drawing code in here
"""
#clear screen and depth buffer
Gl.glClear(Gl.gl_COLOR_BUFFER_BIT | Gl.gl_DEPTH_BUFFER_BIT)
#do drawing inside of this block
Gl.glPushMatrix
#faux camera transformation
Gl.glRotatef(.viewAngle, 1.0f32, 0.2f32, 0.0f32)
#draw our 3D axes
.draw3DAxes
#create another push/pop pair
Gl.glPushMatrix
#rotate about the x axis
Gl.glRotatef(.rotation, 1, 0, 0)
#create us a quadric, which is like a 3D shape
#made from quadratics... i think.
q as Glu.GLUquadric = Glu.gluNewQuadric
#tell glu that we want our quadric to be drawn filled
Glu.gluQuadricDrawStyle(q, Glu.glu_FILL)
#yeah right! that#s hard!
Glu.gluCylinder(q, 15, 1, 25, 20, 20)
#delete it so it doesnt take up our memory
Glu.gluDeleteQuadric(q)
Gl.glPopMatrix
Gl.glPopMatrix
#flush the opengl buffer to the screen
Gl.glFlush
def draw3DAxes
"""
draws the coloured 3D axes to our scene. this has been pulled out
into its own sub so that they can be turned on/off at will
"""
#draw the z-axis
Gl.glColor3f(1.0f32, 0.0f32, 0.0f32)
Gl.glBegin(Gl.gl_LINES)
Gl.glVertex3f(0.0f32, 0.0f32, -.axisSize)
Gl.glVertex3f(0.0f32, 0.0f32, .axisSize)
Gl.glEnd
#draw the y-axis
Gl.glColor3f(0.0f32, 1.0f32, 0.0f32)
Gl.glBegin(Gl.gl_LINES)
Gl.glVertex3f(0.0f32, -.axisSize, 0.0f32)
Gl.glVertex3f(0.0f32, .axisSize, 0.0f32)
Gl.glEnd
#draw the x-axis
Gl.glColor3f(0.0f32, 0.0f32, 1.0f32)
Gl.glBegin(Gl.gl_LINES)
Gl.glVertex3f(-.axisSize, 0.0f32, 0.0f32)
Gl.glVertex3f(.axisSize, 0.0f32, 0.0f32)
Gl.glEnd
def windowResizeHandler(height as float32, width as float32)
#set our viewport to window dimensions
Gl.glViewport(0, 0, width to int, height to int)
#reset the projection matrix stack
Gl.glMatrixMode(Gl.gl_PROJECTION)
Gl.glLoadIdentity
#this value is basically our draw distance; the unit size of our clipping volume
#prevent division by zero
if .height == 0
.height = 1
#establish our clipping volume
if .width <= .height
Gl.glOrtho(-.nRange, .nRange, -.nRange * .height / .width, .nRange * .height / .width, -.nRange, .nRange)
else
Gl.glOrtho(-.nRange * .width / .height, .nRange * .width / .height, -.nRange, .nRange, -.nRange, .nRange)
def onResize(sender, e as EventArgs) # .Resize
.windowResizeHandler(.height, .width)
def onDisposed(sender, e as EventArgs) # .Disposed
#called on app exit - destroy all our objects
.glCtrl.destroyContexts
System.Windows.Forms.Application.exit
#BUG: 100% CPU here
def dispose(disposing as bool) is protected, override
if disposing
if .components
.components.dispose
base.dispose(disposing)
def tmrFPS_Tick(sender, e as EventArgs) # tmrFPS.Tick
#display the fps count in the title bar
.text = "[.fpsCount] FPS"
.fpsCount = 0