Byzantine Reality

Avatar

Searching for Byzantine failures in the world around us

Articles tagged with 'howto'

HOWTO: Converting Simple OpenGL Code from C++ to Perl

Over the last few weeks I’ve been trying to learn OpenGL. However, I’ve had a miserable time trying to get various implementations of it to work on my Mac, notably with C++ and Java. I was surprised to learn that installing the Perl OpenGL implementation (or POGL) is pretty simple, and that converting OpenGL code written in C++ to Perl is also reasonably easy. The following is a heuristic method you can use to do the same, using an example from the OpenGL SuperBible by Richard S. Wright, Jr. The code is freely available from his site at http://www.starstonesoftware.com/OpenGL/, and feel free to use my Perl conversion of his code.

This ended up being longer than I thought, so I'll put a general summary here and then dive into it:
1. Install OpenGL support for Perl (POGL)
2. Change the comments from // to #
3. Import the POGL library
4. Change declarations of GL data types to just scalars.
5. Convert subroutine styles from C++ to Perl
6. Change all uses of a variable with $variable.
7. Add curly braces in one-line "if" blocks and convert "else if" to "elsif"
8. Remove the opening declaration of the main function and it’s return value
9. Change the GLUT instantiation line (the first line of the main method)
10. If functions are passed around, add \& to pass their references.

If you have Mac OS X, Perl is already installed and good to go. To install POGL, open a Terminal and type the following:
sudo cpan
install OpenGL
quit

Pretty simple! Running this as root is recommended, otherwise some of the files needed to update your basic Perl install may not go well. I said “yes” to all the optional installs and it was smooth sailing!

With that out of the way, let’s begin by analyzing Wright’s C++ OpenGL code:

// Stencil.cpp
// OpenGL SuperBible
// Richard S. Wright Jr.
// rwright@starstonesoftware.com

#include “../../shared/gltools.h” // OpenGL toolkit

// Initial square position and size
GLfloat x = 0.0f;
GLfloat y = 0.0f;
GLfloat rsize = 25;

// Step size in x and y directions
// (number of pixels to move each time)
GLfloat xstep = 1.0f;
GLfloat ystep = 1.0f;

// Keep track of windows changing width and height
GLfloat windowWidth;
GLfloat windowHeight;

///////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
GLdouble dRadius = 0.1; // Initial radius of spiral
GLdouble dAngle; // Looping variable

// Clear blue window
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);

// Use 0 for clear stencil, enable stencil test
glClearStencil(0.0f);
glEnable(GL_STENCIL_TEST);

// Clear color and stencil buffer
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

// All drawing commands fail the stencil test, and are not
// drawn, but increment the value in the stencil buffer.
glStencilFunc(GL_NEVER, 0×0, 0×0);
glStencilOp(GL_INCR, GL_INCR, GL_INCR);

// Spiral pattern will create stencil pattern
// Draw the spiral pattern with white lines. We
// make the lines white to demonstrate that the
// stencil function prevents them from being drawn
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINE_STRIP);
for(dAngle = 0; dAngle < 400.0; dAngle += 0.1)
{
glVertex2d(dRadius * cos(dAngle), dRadius * sin(dAngle));
dRadius *= 1.002;
}
glEnd();

// Now, allow drawing, except where the stencil pattern is 0×1
// and do not make any further changes to the stencil buffer
glStencilFunc(GL_NOTEQUAL, 0×1, 0×1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

// Now draw red bouncing square
// (x and y) are modified by a timer function
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(x, y, x + rsize, y – rsize);

// All done, do the buffer swap
glutSwapBuffers();
}

///////////////////////////////////////////////////////////
// Called by GLUT library when idle (window not being
// resized or moved)
void TimerFunction(int value)
{
// Reverse direction when you reach left or right edge
if(x > windowWidth-rsize || x < -windowWidth)
xstep = -xstep;

// Reverse direction when you reach top or bottom edge
if(y > windowHeight || y < -windowHeight + rsize)
ystep = -ystep;

// Check bounds. This is in case the window is made
// smaller while the rectangle is bouncing and the
// rectangle suddenly finds itself outside the new
// clipping volume
if(x > windowWidth-rsize)
x = windowWidth-rsize-1;

if(y > windowHeight)
y = windowHeight-1;

// Actually move the square
x += xstep;
y += ystep;

// Redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(33,TimerFunction, 1);
}

///////////////////////////////////////////////////////////
// Called by GLUT library when the window has chanaged size
void ChangeSize(int w, int h)
{
GLfloat aspectRatio;

// Prevent a divide by zero
if(h == 0)
h = 1;

// Set Viewport to window dimensions
glViewport(0, 0, w, h);

// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Establish clipping volume (left, right, bottom, top, near, far)
aspectRatio = (GLfloat)w / (GLfloat)h;
if (w <= h)
{
windowWidth = 100;
windowHeight = 100 / aspectRatio;
glOrtho (-100.0, 100.0, -windowHeight, windowHeight, 1.0, -1.0);
}
else
{
windowWidth = 100 * aspectRatio;
windowHeight = 100;
glOrtho (-windowWidth, windowWidth, -100.0, 100.0, 1.0, -1.0);
}

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

///////////////////////////////////////////////////////////
// Program entry point
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL);
glutInitWindowSize(800,600);
glutCreateWindow("OpenGL Stencil Test");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutTimerFunc(33, TimerFunction, 1);
glutMainLoop();

return 0;
}

Note: There are no notes in the downloadable files on Wright's site as to the license that this code is released under, nor have I asked him for his permission. However, as it is free to download it, I do not see a problem showing it to you here.

Begin by replacing C style comments with Perl style comments: Replace all instances of // with #. There may be a leftover /# that is not replaced correctly, look for those and replace those with ##.

Next, import the POGL libraries / packages by taking out this C++ line:
#include "../../shared/gltools.h" # OpenGL toolkit

And by putting these lines at the very top of your program:
#!/usr/bin/perl -w
use strict;
use OpenGL qw/ :all /;
use Math::Trig;

You don'

t always need the Trigonometry libraries, but with graphic manipulation (especially spheres!) it couldn't hurt. Next, replace all declarations of the GL data types with “my $”, and for floating point numbers, remove the “f” off the end if it is there. For example,

GLfloat x = 0.0f; becomes my $x = 0.0;
Don't forget to remove any casts to GL data types. Also, find all instances where a float is used C++ style (0.0f) and change those to Perl style (0.0).

Next, let's straighten up the subroutines. Over the last few weeks all the C++ OpenGL code I've seen either takes in arguments or doesn't, but have not returned any values (has a void return type). We can change those as follows:
Case 1: Takes no arguments:
void RenderScene(void) becomes sub RenderScene
Case 2: Takes in arguments:
void ChangeSize(int w, int h) { becomes
sub ChangeSize {
my ($w, $h) = @_; 

Either way, it isn't particularly difficult. Now comes the tedious part. Find any uses of a variable and add in a $ before it, so h = 0; becomes $h = 0;.

Next, find all your if statements and if they don't have curly braces on them, add them (even if it’s just one line inside the if block). If the C++ code uses “else if” statements, change those to “elsif”.

Finally, remove the beginning of the main function and its closing curly brace:
int main(int argc, char* argv[])
{

is removed, and return 0; } is removed.

Next, we need to call the GLUT library “the Perl” way, so make this change:
glutInit(&argc, argv); becomes eval {glutInit(); 1} or die "This test requires GLUT:\n$@\n";

Let’s wrap it up by appending “” to function names when we give their names to other functions:
glutReshapeFunc(ChangeSize); becomes glutReshapeFunc(\&ChangeSize);

My final output looks like this:

#!/usr/bin/perl -w
use strict;
use OpenGL qw/ :all /;
use Math::Trig;

# Stencil.cpp
# OpenGL SuperBible
# Richard S. Wright Jr.
# rwright@starstonesoftware.com
# Converted to Perl by Chris Bunch

# Initial square position and size
my $x = 0.0;
my $y = 0.0;
my $rsize = 25;

# Step size in x and y directions
# (number of pixels to move each time)
my $xstep = 1.0;
my $ystep = 1.0;

# Keep track of windows changing width and height
my $windowWidth;
my $windowHeight;

##############################
# Called to draw scene
sub RenderScene
{
my $dRadius = 0.1; # Initial radius of spiral
my $dAngle; # Looping variable

# Clear blue window
glClearColor(0.0, 0.0, 1.0, 0.0);

# Use 0 for clear stencil, enable stencil test
glClearStencil(0.0);
glEnable(GL_STENCIL_TEST);

# Clear color and stencil buffer
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

# All drawing commands fail the stencil test, and are not
# drawn, but increment the value in the stencil buffer.
glStencilFunc(GL_NEVER, 0×0, 0×0);
glStencilOp(GL_INCR, GL_INCR, GL_INCR);

# Spiral pattern will create stencil pattern
# Draw the spiral pattern with white lines. We
# make the lines white to demonstrate that the
# stencil function prevents them from being drawn
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_STRIP);
for($dAngle = 0; $dAngle < 400.0; $dAngle += 0.1)
{
glVertex2d($dRadius * cos($dAngle), $dRadius * sin($dAngle));
$dRadius *= 1.002;
}
glEnd();

# Now, allow drawing, except where the stencil pattern is 0×1
# and do not make any further changes to the stencil buffer
glStencilFunc(GL_NOTEQUAL, 0×1, 0×1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

# Now draw red bouncing square
# (x and y) are modified by a timer function
glColor3f(1.0, 0.0, 0.0);
glRectf($x, $y, $x + $rsize, $y – $rsize);

# All done, do the buffer swap
glutSwapBuffers();
}

##############################
# Called by GLUT library when idle (window not being
# resized or moved)
sub TimerFunction {
my ($value) = @_;
# Reverse direction when you reach left or right edge
if($x > $windowWidth-$rsize || $x < -$windowWidth) {
$xstep = -$xstep; }

# Reverse direction when you reach top or bottom edge
if($y > $windowHeight || $y < -$windowHeight + $rsize) {
$ystep = -$ystep; }

# Check bounds. This is in case the window is made
# smaller while the rectangle is bouncing and the
# rectangle suddenly finds itself outside the new
# clipping volume
if($x > $windowWidth-$rsize) {
$x = $windowWidth-$rsize-1; }

if($y > $windowHeight) {
$y = $windowHeight-1; }

# Actually move the square
$x += $xstep;
$y += $ystep;

# Redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(33,\&TimerFunction, 1);
}

##############################
# Called by GLUT library when the window has chanaged size
sub ChangeSize {
my ($w, $h) = @_;
my $aspectRatio;

# Prevent a divide by zero
if($h == 0) {
$h = 1; }

# Set Viewport to window dimensions
glViewport(0, 0, $w, $h);

# Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

# Establish clipping volume (left, right, bottom, top, near, far)
$aspectRatio = $w / $h;
if ($w <= $h)
{
$windowWidth = 100;
$windowHeight = 100 / $aspectRatio;
glOrtho (-100.0, 100.0, -$windowHeight, $windowHeight, 1.0, -1.0);
}
else
{
$windowWidth = 100 * $aspectRatio;
$windowHeight = 100;
glOrtho (-$windowWidth, $windowWidth, -100.0, 100.0, 1.0, -1.0);
}

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

##############################
# Program entry point
eval {glutInit(); 1} or die “This test requires GLUT:\n$@\n”;
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL);
glutInitWindowSize(800,600);
glutCreateWindow(“OpenGL Stencil Test”);
glutReshapeFunc(\&ChangeSize);
glutDisplayFunc(\&RenderScene);
glutTimerFunc(33, \&TimerFunction, 1);
glutMainLoop();

Whew! Try running it and see how it works! It takes a couple tries to get it right, but once you do, you’ve got a pretty good (although tedious) way to convert C++ OpenGL code to Perl! It takes longer than I’d like though, so I may have to write a script that does this for us…

HOWTO: Call Matlab from Java {Kinda}

Looking over some of the reports on my blog reveal that pretty much everyone to this point looking at this blog look at the Java / Matlab post and not much else. Therefore, here’s everything I’ve learned concretely on how to call Matlab from Java and what NOT to do to save you some grief:

What I did:
Make a file that contains all the commands you want to run when MATLAB starts. My script file looks like this (named scriptName):

cd /directoryWithMATLABScript/
myMATLABScript
quit

The Java code I have used is a modified version of the code here. Now, use the following Java code to call MATLAB with the commands from your script:

UPDATE (07/25): Appending to the output and error Strings in the method provided is ok for MATLAB scripts with small amounts of output. On scripts that produce large amounts of output, constantly reallocating memory to new Strings and copying over the old contents of output takes an unnecessarily long amount of time. Use a StringBuffer and its append method instead.

public static String runScript(File scriptName) {
String output = “”, error = “”;
try {
String commandToRun = “/Applications/MATLAB73/bin/matlab -nodisplay < ” + scriptName;
System.out.println(commandToRun);
Process p = Runtime.getRuntime().exec(commandToRun);

String s;

BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));

BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));

// read the output from the command
System.out.println(“\nHere is the standard output of the command:\n”);
while ((s = stdInput.readLine()) != null) {
output += s + “\n”;
System.out.println(s);
}

// read any errors from the attempted command
System.out.println(“\nHere is the standard error of the command (if any):\n”);
while ((s = stdError.readLine()) != null) {
error += s + “\n”;
System.out.println(s);
}

} catch (Exception e) {
System.out.println(“exception happened – here’s what I know: “);
e.printStackTrace();
System.exit(-1);
}
return output + error;
}

This method will run MATLAB, pipe in the commands from the script file, and capture the standard output and standard error into Strings, and return that. Feel free to modify this code to play with the output or errors you’re getting from MATLAB. You can also use a DataOutputStream to push data back into MATLAB; if you’re interested in that, this link pretty much summarizes it up (third post down).

It is important to use the “-nodisplay” flag when calling MATLAB, otherwise the MATLAB GUI / IDE will open and the contents of the script won’t be called. Be sure to read about the caveats of this method below! If this was helpful, drop a comment off and let me know!

What NOT to DO / Things to keep in mind:

  1. The Matlab site gives an example of using the JAR that comes with the Matlab installation to call Java from Matlab. This requires you to start up MATLAB first, then call your Java program from it, which is the exact OPPOSITE of what you need to do. Furthermore, there is ZERO documentation on this JAR, so if there was a way to do it, nobody seems to know (at least based from multiple Google searches).
  2. The Java documentation on the Process class gives many warnings about what types of programs you should not make it call. Make sure your MATLAB program is not one of them or you may get unreliable results.
  3. I had to remove all user interaction from my MATLAB scripts to get my code “functional”, but if you fiddle with the Output and Input Streams, you may be able to work around this.
  4. You COULD just have the Runtime method execute “matlab -r matlabScriptName” and it will start up MATLAB and run “matlabScriptName.m”, but once it’s done it will idle and never quit. Technically this works, but you’ll need a way to kill the MATLAB process cleanly, as hoping Java will do it for you orphans some of MATLAB’s helper programs.
  5. Newer versions of MATLAB come bundled with a Matlab to C compiler appropriately called “MCC”, located in the “bin” directory of your MATLAB installation. You COULD use it to compile Matlab code into C code and then just run the C code from Java, but it’s not supported on Mac OS X, so it doesn’t work for me, and Google searches on the net show that many others have had problems with it. Furthermore, it doesn’t look like it pulls in the needed dependencies for all your files, so it’s not obvious if it’ll work as a standalone file. Spending several hours trying to fix the MCC so that it would work on Mac OS X proved futile, as there ended up being other problems with the C linker…

Hopefully this saves any of you some of the time it took me figuring this out.

profile for Chris Bunch at Stack Overflow, Q&A for professional and enthusiast programmers