Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Coding for OpenGL "live"

by SuicideJunkie (Vicar)
on Aug 23, 2011 at 14:10 UTC ( #921909=CUFP: print w/replies, xml ) Need Help??

I decided I wanted to do some graphics earlier this month, so I pulled down the openGL module and started gnawing on the spinning cube demo that came with it.

I quickly found that it is very easy to break things, blind your viewpoint and generally mess things up with transformations being off. And I also found that it took forever to see what was going on when I had to run the script over and over.

So I thought; hey, this is a scripting language. Let me use the power of the eval, and have it do the work for me!

And thus I split it into two scripts. One with the basics to initialize and loop, the other to edit while it is being continuously re-evaled. Now, I can add a minus sign to a formula, and see the results immediately on screen. I can start defining a polygon or triangle strip, and watch as the shape grows when I enter new points.

I would say it has sped up everything by 10x, since I can just try things effortlessly, and actually *see* the differences flip back and forth.

Readmore for Sample code :

Main loop

#!/usr/bin/perl -w use strict; use warnings; use OpenGL qw/ :all /; use constant R30D => 0.523598776; eval {glutInit(); 1} or die qq { This requires GLUT. }; glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA) +; glutInitWindowSize(500, 500); my $Window_ID = glutCreateWindow( "Open Gl Window" ); # Register the callback function to do the drawing. glutDisplayFunc(\&cbRenderScene); # If there's nothing to do, draw. glutIdleFunc(\&cbRenderScene); # It's a good idea to know when our window's resized. glutReshapeFunc(\&resizeEvent); # And let's get some input. # glutKeyboardFunc(\&cbKeyPressed); # glutSpecialFunc(\&cbSpecialKeyPressed); # glutPassiveMotionFunc(\&mouseMove); # glutMotionFunc(\&mouseMove); # glutMouseFunc(\&mouseClick); # Pass off control to OpenGL. # Above functions are called as appropriate. glutMainLoop(); exit 0; sub resizeEvent { my ($Width, $Height) = @_; print "Resize: $Width, $Height\n"; # Let's not core dump, no matter what. $Height = 1 if ($Height <1); glViewport(0, 0, $Width, $Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0,$Width/$Height,0.1,100.0); glMatrixMode(GL_MODELVIEW); $main::window_Width = $Width; $main::window_Height = $Height; } sub cbRenderScene { eval {do '';}; print $@ . "\r"; # Take a quick nap to avoid wasting CPU select (undef,undef,undef,0.1); }

And a demo which renders some colored hexagons.

no warnings; # Draw a grid of hexagons glMatrixMode(GL_MODELVIEW); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1,1,0); glPointSize(10); glLineWidth(1); glDisable(GL_DEPTH_TEST); glLoadIdentity(); glTranslatef(-5,-8,-30); glPushMatrix(); glTranslatef(0,0,0); for my $x (0..10) { glTranslatef(cos(R30D),sin(R30D),0); glPushMatrix(); for my $y(0..10) { glTranslatef(0,1,0); drawHex([$x%2,$y%2,0], [0,.5-$y/20,$y/10]); } glPopMatrix(); } glPopMatrix(); glutSwapBuffers(); sub drawHex { my $border=shift; my $fill = shift; my $r = shift || 0.5; my $bwidth = shift || 0.05; $r = $r-2*$bwidth; my $s = $r / cos(R30D); my $h = $s * sin(R30D); #print "$h, $r, $s"; if (defined $fill) { glColor3f(@$fill); glBegin(GL_POLYGON); glVertex2f($bwidth+$h,-$r); glVertex2f($bwidth+$h+$s,-$r); glVertex2f($bwidth+2*$h+$s,0); glVertex2f($bwidth+$h+$s, $r); glVertex2f($bwidth+$h, $r); glVertex2f($bwidth,0); glEnd(); } if (defined $border) { glColor3f(@$border); glBegin(GL_LINE_LOOP); glVertex2f($bwidth+$h,-$r); glVertex2f($bwidth+$h+$s,-$r); glVertex2f($bwidth+2*$h+$s,0); glVertex2f($bwidth+$h+$s, $r); glVertex2f($bwidth+$h, $r); glVertex2f($bwidth,0); glEnd(); } }

Replies are listed 'Best First'.
Re: Coding for OpenGL "live"
by spx2 (Deacon) on Aug 26, 2011 at 13:35 UTC
    This is really awesome. I had a plan to write the net-version(unfolded cube version) of a Rubik's cube inside my package CM::Rubik .
    Now I know what I'm going to use to do it( thanks ! ), your script with the eval-thingie is really a good idea.
    It's a very good idea and I totally agree on the 10x argument.
Re: Coding for OpenGL "live"
by Anonymous Monk on Oct 04, 2011 at 15:06 UTC

    for fun, remove the "no warnings" line. You'll see that you are continually calling the perl complier

    I futzed with this for a bit, refactoring the code in sample to just require (|| die) the code. I added a sub (do draw) around the loose code in drawframe and called it after the require.

    Im not thinking you need to recompile several times/sec

      Maybe you could've provided the code since you refactored it ..

      Its been a while, but to clarify:

      require is not terribly useful because it will only load the draw code once.

      The code DOES need to recompile repeatedly in order to incorporate changes to the drawframe code as soon as they are saved to disk. (This being the entire point of live coding.) An enhancement could be made to only recompile the code if the file on disk has been changed since the last frame, but reloading it every frame is simple and effective.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://921909]
Approved by Corion
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2018-01-18 02:22 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (206 votes). Check out past polls.