/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- CreateEnvironment
- Display
- MakeGeometry
- MakeLighting
- MakeCamera
- HandleKeyboard
- HandleSpecialKeyboard
- HandleMouse
- HandleMainMenu
- HandleSpeedMenu
- HandleVisibility
- HandleIdle
- DrawTextXY
- GiveUsage
<?php
/*
Converted example from http://astronomy.swin.edu.au/pbourke/historical/glut/
Original Author Paul Bourke <pbourke@swin.edu.au>
Converted to PHP by Markus Fischer <mfischer@guru.josefine.at>
*/
error_reporting(E_ALL);
define('DRAFT', 0);
define('MEDIUM', 1);
define('BEST', 2);
$drawquality = DRAFT;
$spincamera = TRUE;
$cameradirection = 1;
$updownrotate = 60.0;
$ballbounce = TRUE;
$ballspeed = 2.0;
foreach(array('OVALID', 'SPHEREID', 'BOXID', 'PLANEID', 'TEXTID') as $i => $const)
define($const, $i+1);
for ($i=1;$i<$argc;$i++) {
if (strstr($argv[$i],"-h") != NULL)
GiveUsage($argv[0]);
if (strstr($argv[$i],"-q") != NULL) {
if ($i+1 >= $argc)
GiveUsage($argv[0]);
$drawquality = $argv[$i+1];
if ($drawquality < DRAFT)
$drawquality = DRAFT;
if ($drawquality > BEST)
$drawquality = BEST;
$i++;
}
}
/* Set things up and go */
glutInit($argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("OpenGL Demo");
glutDisplayFunc('Display');
glutVisibilityFunc('HandleVisibility');
glutKeyboardFunc('HandleKeyboard');
glutSpecialFunc('HandleSpecialKeyboard');
glutMouseFunc('HandleMouse');
CreateEnvironment();
/* Set up some menus */
$speedmenu = glutCreateMenu('HandleSpeedMenu');
glutAddMenuEntry("Slow",1);
glutAddMenuEntry("Medium",2);
glutAddMenuEntry("fast",3);
$mainmenu = glutCreateMenu('HandleMainMenu');
glutAddMenuEntry("Toggle camera spin",1);
glutAddMenuEntry("Toggle ball bounce",2);
glutAddSubMenu("Ball speed",$speedmenu);
glutAddMenuEntry("Quit",100);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
exit;
/*
This is where global settings are made, that is,
things that will not change in time
*/
function CreateEnvironment() {
global $drawquality;
glEnable(GL_DEPTH_TEST);
if ($drawquality == DRAFT)
glShadeModel(GL_FLAT);
if ($drawquality == MEDIUM)
glShadeModel(GL_SMOOTH);
if ($drawquality == BEST) {
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glShadeModel(GL_SMOOTH);
glDisable(GL_DITHER); /* Assume RGBA capabilities */
}
glLineWidth(1.0);
glPointSize(1.0);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glFrontFace(GL_CW);
glDisable(GL_CULL_FACE);
glClearColor(0.0,0.0,0.0,0.0); /* Background colour */
glEnable(GL_COLOR_MATERIAL);
}
/*
This is the basic display callback routine
It creates the geometry, lighting, and viewing position
In this case it rotates the camera around the scene
*/
function Display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
MakeCamera(FALSE,0,0);
MakeLighting();
MakeGeometry();
glPopMatrix();
/* glFlush(); This isn't necessary for double buffers */
glutSwapBuffers();
}
/*
Create the geometry
*/
function MakeGeometry() {
global $drawquality, $ballbounce, $ballspeed;
static $theta = 0.0;
$radius = 0.5;
$mshin1 = array(5.0); /* For the sphere */
$mspec1 = array(0.5,0.5,0.5,1.0);
$mdiff1 = array(0.6,0.0,0.6,1.0);
$mamb1 = array(0.1,0.0,0.1,1.0);
$mdiff2 = array(0.0,1.0,0.0,1.0); /* Green plane */
$mamb2 = array(0.0,0.2,0.0,1.0);
$mdiff3 = array(0.5,0.5,0.5,1.0); /* Grey boxes */
$mamb3 = array(0.2,0.2,0.2,1.0);
/* Create a green ground plane */
glLoadName(PLANEID);
if ($drawquality > DRAFT)
glBegin(GL_POLYGON);
else
glBegin(GL_LINE_LOOP);
glColor3f(0.0,1.0,0.0);
if ($drawquality > DRAFT) {
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE, $mdiff2);
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT, $mamb2);
}
glNormal3f( 0.0, 1.0, 0.0);
glVertex3f( 2.0, 0.0, 2.0);
glVertex3f( 2.0, 0.0,-2.0);
glVertex3f(-2.0, 0.0,-2.0);
glVertex3f(-2.0, 0.0, 2.0);
glEnd();
/* Place a few grey boxes around the place */
glLoadName(BOXID);
glColor3f(0.5,0.5,0.5);
if ($drawquality > DRAFT) {
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE, $mdiff3);
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT, $mamb3);
}
glPushMatrix();
glTranslatef(1.8,0.2,1.8);
if ($drawquality > DRAFT)
glutSolidCube(0.4);
else
glutWireCube(0.4);
glTranslatef(-3.6,0.0,0.0);
if ($drawquality > DRAFT)
glutSolidCube(0.4);
else
glutWireCube(0.4);
glPopMatrix();
/* Create a magenta bouncing ball */
glLoadName(SPHEREID);
glColor3f(0.6,0.0,0.6);
if ($drawquality > DRAFT) {
glMaterialfv(GL_FRONT,GL_SHININESS,$mshin1);
glMaterialfv(GL_FRONT,GL_SPECULAR,$mspec1);
}
glPushMatrix();
glTranslatef(0.0,$radius+0.5*(1+sin(M_PI*$theta/180)),0.0);
glScalef($radius,$radius,$radius);
if ($ballbounce)
$theta += $ballspeed;
if ($drawquality > DRAFT)
glutSolidSphere(1.0,16,16);
else
glutWireSphere(1.0,32,32);
glPopMatrix();
/* Create a white half-oval loop at one end */
glLoadName(OVALID);
glBegin(GL_LINE_STRIP);
glColor3f(1.0,1.0,1.0);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
for ($i=0;$i<=180;$i++)
glVertex3f(2*cos($i*M_PI/180),1.5*sin($i*M_PI/180),-2.0);
glEnd();
/* Write some text */
glLoadName(TEXTID);
DrawTextXY(-2.0,-0.25,2.0,0.002,"PHP OpenGL Demo");
}
/*
Set up the lighing environment
*/
function MakeLighting() {
global $drawquality;
$globalambient = array(0.3,0.3,0.3,1.0);
/* The specifications for 3 light sources */
$pos0 = array(1.0,1.0,0.0,0.0); /* w = 0 == infinite distance */
$dif0 = array(0.8,0.8,0.8,1.0);
$pos1 = array(5.0,-5.0,0.0,0.0); /* Light from below */
$dif1 = array(0.4,0.4,0.4,1.0); /* Fainter */
if ($drawquality > DRAFT) {
/* Set ambient globally, default ambient for light sources is 0 */
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,$globalambient);
glLightfv(GL_LIGHT0,GL_POSITION,$pos0);
glLightfv(GL_LIGHT0,GL_DIFFUSE,$dif0);
glLightfv(GL_LIGHT1,GL_POSITION,$pos1);
glLightfv(GL_LIGHT1,GL_DIFFUSE,$dif1);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
}
}
/*
Set up the camera
Optionally creating a small viewport about
the mouse click point for object selection
*/
function MakeCamera($pickmode,$x,$y) {
global $updownrotate, $spincamera, $cameradirection;
static $theta = 0;
$viewport = array();
/* Camera setup */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if ($pickmode == TRUE) {
glGetIntegerv(GL_VIEWPORT, $viewport); /* Get the viewport bounds */
gluPickMatrix($x,$viewport[3]-$y,3.0,3.0,$viewport);
}
gluPerspective(70.0, /* Field of view */
1.0, /* aspect ratio */
0.1,1000.0); /* near and far */
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5*cos($theta*M_PI/180)*sin($updownrotate*M_PI/180),
5*cos($updownrotate*M_PI/180),
5*sin($theta*M_PI/180)*sin($updownrotate*M_PI/180),
0.0,0.0,0.0, /* Focus */
0.0,1.0,0.0); /* Up */
if ($spincamera)
$theta += ($cameradirection * 0.2);
}
/*
Deal with plain key strokes
*/
function HandleKeyboard($key,$x,$y) {
global $spincamera, $ballbounce;
switch (ord($key)) {
case 27: /* ESC */
case ord('Q'):
case ord('q'): exit(); break;
case ord('s'):
case ord('S'): $spincamera = !$spincamera; break;
case ord('b'):
case ord('B'): $ballbounce = !$ballbounce; break;
}
}
/*
Deal with special key strokes
*/
function HandleSpecialKeyboard($key,$x,$y) {
global $updownrotate, $cameradirection;
switch ($key) {
case GLUT_KEY_LEFT: $cameradirection = -1; break;
case GLUT_KEY_RIGHT: $cameradirection = 1; break;
case GLUT_KEY_UP: $updownrotate -= 2; break;
case GLUT_KEY_DOWN: $updownrotate += 2; break;
}
}
/*
Handle mouse events
*/
function HandleMouse($button,$state,$x,$y) {
$maxselect = 100;
$nhits = 0;
$selectlist = array();
if ($state == GLUT_DOWN) {
glSelectBuffer($maxselect);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(-1);
glPushMatrix();
MakeCamera(TRUE,$x,$y);
MakeGeometry();
glPopMatrix();
$nhits = glRenderMode(GL_RENDER);
if ($button == GLUT_LEFT_BUTTON) {
} else if ($button == GLUT_MIDDLE_BUTTON) {
} /* Right button events are passed to menu handlers */
if ($nhits == -1)
error_log("Select buffer overflow");
$selectlist = glGetSelectBuffer();
#var_dump($selectlist);
if ($nhits > 0) {
echo "\tPicked $nhits objects: ";
for ($i=0;$i<$nhits;$i++)
echo $selectlist[4*$i+3] . " ";
echo "\n";
}
}
}
/*
Handle the main menu
*/
function HandleMainMenu($whichone) {
global $spincamera, $ballbounce;
switch ($whichone) {
case 1: $spincamera = !$spincamera; break;
case 2: $ballbounce = !$ballbounce; break;
case 100: exit(); break;
}
}
/*
Handle the ball speed sub menu
*/
function HandleSpeedMenu($whichone) {
global $ballspeed;
switch ($whichone) {
case 1: $ballspeed = 0.5; break;
case 2: $ballspeed = 2; break;
case 3: $ballspeed = 10; break;
}
}
/*
How to handle visibility
*/
function HandleVisibility($visible) {
if ($visible == GLUT_VISIBLE)
glutIdleFunc('HandleIdle');
else
glutIdleFunc(array());
}
/*
What to do on an idle event
*/
function HandleIdle() {
glutPostRedisplay();
}
/*
Draw text in the x-y plane
The x,y,z coordinate is the bottom left corner (looking down -ve z axis)
*/
function DrawTextXY($x,$y,$z,$scale,$s) {
glPushMatrix();
glTranslatef($x,$y,$z);
glScalef($scale,$scale,$scale);
for ($i=0;$i<strlen($s);$i++)
glutStrokeCharacter(GLUT_STROKE_ROMAN,$s[$i]);
glPopMatrix();
}
/*
Display the program usage information
*/
function GiveUsage($cmd) {
echo <<<USAGE
Usage: $cmd [-h] [-q n]
-h this text
-q n quality, 0,1,2
Key Strokes and Menus:
q - quit
s - toggle camera spin
b - toggle ball bounce
left arrow - change rotation direction
right arrow - change rotation direction
down arrow - rotate camera down
up arrow - rotate camera up
USAGE;
exit;
}