diff options
Diffstat (limited to 'progs/demos/engine.c')
-rw-r--r-- | progs/demos/engine.c | 1343 |
1 files changed, 0 insertions, 1343 deletions
diff --git a/progs/demos/engine.c b/progs/demos/engine.c deleted file mode 100644 index ee7d5c154a9..00000000000 --- a/progs/demos/engine.c +++ /dev/null @@ -1,1343 +0,0 @@ -/** - * Simple engine demo (crankshaft, pistons, connecting rods) - * - * Brian Paul - * June 2006 - */ - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <GL/glew.h> -#include <GL/glut.h> -#include "readtex.h" -#include "trackball.h" - - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define DEG_TO_RAD(DEG) ((DEG) * M_PI / 180.0) - -#define TEXTURE_FILE "../images/reflect.rgb" - -/* Target engine speed: */ -const int RPM = 100.0; - -static int Win = 0; - - -/** - * Engine description. - */ -typedef struct -{ - const char *Name; - int Pistons; - int Cranks; - float V_Angle; - float PistonRadius; - float PistonHeight; - float WristPinRadius; - float Throw; - float CrankPlateThickness; - float CrankPinRadius; - float CrankJournalRadius; - float CrankJournalLength; - float ConnectingRodLength; - float ConnectingRodThickness; - /* display list IDs */ - GLuint CrankList; - GLuint ConnRodList; - GLuint PistonList; - GLuint BlockList; -} Engine; - - -typedef struct -{ - float CurQuat[4]; - float Distance; - /* When mouse is moving: */ - GLboolean Rotating, Translating; - GLint StartX, StartY; - float StartDistance; -} ViewInfo; - - -typedef enum -{ - LIT, - WIREFRAME, - TEXTURED -} RenderMode; - - -typedef struct -{ - RenderMode Mode; - GLboolean Anim; - GLboolean Wireframe; - GLboolean Blend; - GLboolean Antialias; - GLboolean Texture; - GLboolean UseLists; - GLboolean DrawBox; - GLboolean ShowInfo; - GLboolean ShowBlock; -} RenderInfo; - - -static GLUquadric *Q; - -static GLfloat Theta = 0.0; - -static const GLfloat PistonColor[4] = { 1.0, 0.5, 0.5, 1.0 }; -static const GLfloat ConnRodColor[4] = { 0.7, 1.0, 0.7, 1.0 }; -static const GLfloat CrankshaftColor[4] = { 0.7, 0.7, 1.0, 1.0 }; -static const GLfloat BlockColor[4] = {0.8, 0.8, 0.8, 0.75 }; - -static GLuint TextureObj; -static GLint WinWidth = 800, WinHeight = 500; - -static ViewInfo View; -static RenderInfo Render; - -#define NUM_ENGINES 3 -static Engine Engines[NUM_ENGINES] = -{ - { - "V-6", - 6, /* Pistons */ - 3, /* Cranks */ - 90.0, /* V_Angle */ - 0.5, /* PistonRadius */ - 0.6, /* PistonHeight */ - 0.1, /* WristPinRadius */ - 0.5, /* Throw */ - 0.2, /* CrankPlateThickness */ - 0.25, /* CrankPinRadius */ - 0.3, /* CrankJournalRadius */ - 0.4, /* CrankJournalLength */ - 1.5, /* ConnectingRodLength */ - 0.1, /* ConnectingRodThickness */ - 0, /* CrankList */ - 0, /* ConnRodList */ - 0, /* PistonList */ - 0 /* BlockList */ - }, - { - "Inline-4", - 4, /* Pistons */ - 4, /* Cranks */ - 0.0, /* V_Angle */ - 0.5, /* PistonRadius */ - 0.6, /* PistonHeight */ - 0.1, /* WristPinRadius */ - 0.5, /* Throw */ - 0.2, /* CrankPlateThickness */ - 0.25, /* CrankPinRadius */ - 0.3, /* CrankJournalRadius */ - 0.4, /* CrankJournalLength */ - 1.5, /* ConnectingRodLength */ - 0.1, /* ConnectingRodThickness */ - 0, /* CrankList */ - 0, /* ConnRodList */ - 0, /* PistonList */ - 0 /* BlockList */ - }, - { - "Boxer-6", - 6, /* Pistons */ - 3, /* Cranks */ - 180.0,/* V_Angle */ - 0.5, /* PistonRadius */ - 0.6, /* PistonHeight */ - 0.1, /* WristPinRadius */ - 0.5, /* Throw */ - 0.2, /* CrankPlateThickness */ - 0.25, /* CrankPinRadius */ - 0.3, /* CrankJournalRadius */ - 0.4, /* CrankJournalLength */ - 1.5, /* ConnectingRodLength */ - 0.1, /* ConnectingRodThickness */ - 0, /* CrankList */ - 0, /* ConnRodList */ - 0, /* PistonList */ - 0 /* BlockList */ - } -}; - -static int CurEngine = 0; - - - -static void -InitViewInfo(ViewInfo *view) -{ - view->Rotating = GL_FALSE; - view->Translating = GL_FALSE; - view->StartX = view->StartY = 0; - view->Distance = 12.0; - view->StartDistance = 0.0; - view->CurQuat[0] = -0.194143; - view->CurQuat[1] = 0.507848; - view->CurQuat[2] = 0.115245; - view->CurQuat[3] = 0.831335; -} - - -static void -InitRenderInfo(RenderInfo *render) -{ - render->Mode = LIT; - render->Anim = GL_TRUE; - render->Wireframe = GL_FALSE; - render->Blend = GL_FALSE; - render->Antialias = GL_FALSE; - render->Texture = GL_FALSE; - render->DrawBox = GL_FALSE; - render->ShowInfo = GL_TRUE; - render->ShowBlock = GL_FALSE; - render->UseLists = GL_FALSE; -} - - -/** - * Set GL for given rendering mode. - */ -static void -SetRenderState(RenderMode mode) -{ - static const GLfloat gray2[4] = { 0.2, 0.2, 0.2, 1.0 }; - static const GLfloat gray4[4] = { 0.4, 0.4, 0.4, 1.0 }; - - /* defaults */ - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, gray2); - - switch (mode) { - case LIT: - glEnable(GL_LIGHTING); - break; - case WIREFRAME: - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - glLineWidth(1.5); - break; - case TEXTURED: - glEnable(GL_LIGHTING); - glEnable(GL_TEXTURE_2D); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, gray4); - break; - default: - ; - } -} - - -/** - * Animate the engine parts. - */ -static void -Idle(void) -{ - /* convert degrees per millisecond to RPM: */ - const float m = 360.0 / 1000.0 / 60.0; - GLint t = glutGet(GLUT_ELAPSED_TIME); - Theta = ((int) (t * RPM * m)) % 360; - glutPostRedisplay(); -} - - -/** - * Compute piston's position along its stroke. - */ -static float -PistonStrokePosition(float throwDist, float crankAngle, float connRodLength) -{ - float x = throwDist * cos(DEG_TO_RAD(crankAngle)); - float y = throwDist * sin(DEG_TO_RAD(crankAngle)); - float pos = y + sqrt(connRodLength * connRodLength - x * x); - return pos; -} - - -/** - * Compute position of nth piston along the crankshaft. - */ -static float -PistonShaftPosition(const Engine *eng, int piston) -{ - const int i = piston / (eng->Pistons / eng->Cranks); - float z; - assert(piston < eng->Pistons); - z = 1.5 * eng->CrankJournalLength + eng->CrankPlateThickness - + i * (2.0 * (eng->CrankJournalLength + eng->CrankPlateThickness)); - if (eng->Pistons > eng->Cranks) { - if (piston & 1) - z += eng->ConnectingRodThickness; - else - z -= eng->ConnectingRodThickness; - } - return z; -} - - -/** - * Compute distance between two adjacent pistons - */ -static float -PistonSpacing(const Engine *eng) -{ - const int pistonsPerCrank = eng->Pistons / eng->Cranks; - const float z0 = PistonShaftPosition(eng, 0); - const float z1 = PistonShaftPosition(eng, pistonsPerCrank); - return z1 - z0; -} - - -/** - * (x0, y0) = position of big end on crankshaft - * (x1, y1) = position of small end on piston - */ -static void -ComputeConnectingRodPosition(float throwDist, float crankAngle, - float connRodLength, - float *x0, float *y0, float *x1, float *y1) -{ - *x0 = throwDist * cos(DEG_TO_RAD(crankAngle)); - *y0 = throwDist * sin(DEG_TO_RAD(crankAngle)); - *x1 = 0.0; - *y1 = PistonStrokePosition(throwDist, crankAngle, connRodLength); -} - - -/** - * Compute total length of the crankshaft. - */ -static float -CrankshaftLength(const Engine *eng) -{ - float len = (eng->Cranks * 2 + 1) * eng->CrankJournalLength - + 2 * eng->Cranks * eng->CrankPlateThickness; - return len; -} - - -/** - * Draw a piston. - * Axis of piston = Z axis. Wrist pin is centered on (0, 0, 0). - */ -static void -DrawPiston(const Engine *eng) -{ - const int slices = 30, stacks = 4, loops = 4; - const float innerRadius = 0.9 * eng->PistonRadius; - const float innerHeight = eng->PistonHeight - 0.15; - const float wristPinLength = 1.8 * eng->PistonRadius; - - assert(Q); - - glPushMatrix(); - glTranslatef(0, 0, -1.1 * eng->WristPinRadius); - - gluQuadricOrientation(Q, GLU_INSIDE); - - /* bottom rim */ - gluDisk(Q, innerRadius, eng->PistonRadius, slices, 1/*loops*/); - - /* inner cylinder */ - gluCylinder(Q, innerRadius, innerRadius, innerHeight, slices, stacks); - - /* inside top */ - glPushMatrix(); - glTranslatef(0, 0, innerHeight); - gluDisk(Q, 0, innerRadius, slices, loops); - glPopMatrix(); - - gluQuadricOrientation(Q, GLU_OUTSIDE); - - /* outer cylinder */ - gluCylinder(Q, eng->PistonRadius, eng->PistonRadius, eng->PistonHeight, - slices, stacks); - - /* top */ - glTranslatef(0, 0, eng->PistonHeight); - gluDisk(Q, 0, eng->PistonRadius, slices, loops); - - glPopMatrix(); - - /* wrist pin */ - glPushMatrix(); - glTranslatef(0, 0.5 * wristPinLength, 0.0); - glRotatef(90, 1, 0, 0); - gluCylinder(Q, eng->WristPinRadius, eng->WristPinRadius, wristPinLength, - slices, stacks); - glPopMatrix(); -} - - -/** - * Draw piston at particular position. - */ -static void -DrawPositionedPiston(const Engine *eng, float crankAngle) -{ - const float pos = PistonStrokePosition(eng->Throw, crankAngle, - eng->ConnectingRodLength); - glPushMatrix(); - glRotatef(-90, 1, 0, 0); - glTranslatef(0, 0, pos); - if (eng->PistonList) - glCallList(eng->PistonList); - else - DrawPiston(eng); - glPopMatrix(); -} - - -/** - * Draw connector plate. Used for crankshaft and connecting rods. - */ -static void -DrawConnector(float length, float thickness, - float bigEndRadius, float smallEndRadius) -{ - const float bigRadius = 1.2 * bigEndRadius; - const float smallRadius = 1.2 * smallEndRadius; - const float z0 = -0.5 * thickness, z1 = -z0; - GLfloat points[36][2], normals[36][2]; - int i; - - /* compute vertex locations, normals */ - for (i = 0; i < 36; i++) { - const int angle = i * 10; - float x = cos(DEG_TO_RAD(angle)); - float y = sin(DEG_TO_RAD(angle)); - normals[i][0] = x; - normals[i][1] = y; - if (angle >= 0 && angle <= 180) { - x *= smallRadius; - y = y * smallRadius + length; - } - else { - x *= bigRadius; - y *= bigRadius; - } - points[i][0] = x; - points[i][1] = y; - } - - /* front face */ - glNormal3f(0, 0, 1); - glBegin(GL_POLYGON); - for (i = 0; i < 36; i++) { - glVertex3f(points[i][0], points[i][1], z1); - } - glEnd(); - - /* back face */ - glNormal3f(0, 0, -1); - glBegin(GL_POLYGON); - for (i = 0; i < 36; i++) { - glVertex3f(points[35-i][0], points[35-i][1], z0); - } - glEnd(); - - /* edge */ - glBegin(GL_QUAD_STRIP); - for (i = 0; i <= 36; i++) { - const int j = i % 36; - glNormal3f(normals[j][0], normals[j][1], 0); - glVertex3f(points[j][0], points[j][1], z1); - glVertex3f(points[j][0], points[j][1], z0); - } - glEnd(); -} - - -/** - * Draw a crankshaft. Shaft lies along +Z axis, starting at zero. - */ -static void -DrawCrankshaft(const Engine *eng) -{ - const int slices = 20, stacks = 2; - const int n = eng->Cranks * 4 + 1; - const float phiStep = 360 / eng->Cranks; - float phi = -90.0; - int i; - float z = 0.0; - - for (i = 0; i < n; i++) { - glPushMatrix(); - glTranslatef(0, 0, z); - if (i & 1) { - /* draw a crank plate */ - glRotatef(phi, 0, 0, 1); - glTranslatef(0, 0, 0.5 * eng->CrankPlateThickness); - DrawConnector(eng->Throw, eng->CrankPlateThickness, - eng->CrankJournalRadius, eng->CrankPinRadius); - z += 0.2; - if (i % 4 == 3) - phi += phiStep; - } - else if (i % 4 == 0) { - /* draw crank journal segment */ - gluCylinder(Q, eng->CrankJournalRadius, eng->CrankJournalRadius, - eng->CrankJournalLength, slices, stacks); - z += eng->CrankJournalLength; - } - else if (i % 4 == 2) { - /* draw crank pin segment */ - glRotatef(phi, 0, 0, 1); - glTranslatef(0, eng->Throw, 0); - gluCylinder(Q, eng->CrankPinRadius, eng->CrankPinRadius, - eng->CrankJournalLength, slices, stacks); - z += eng->CrankJournalLength; - } - glPopMatrix(); - } -} - - -/** - * Draw crankshaft at a particular rotation. - * \param crankAngle current crankshaft rotation, in radians - */ -static void -DrawPositionedCrankshaft(const Engine *eng, float crankAngle) -{ - glPushMatrix(); - glRotatef(crankAngle, 0, 0, 1); - if (eng->CrankList) - glCallList(eng->CrankList); - else - DrawCrankshaft(eng); - glPopMatrix(); -} - - -/** - * Draw a connecting rod at particular position. - * \param eng description of connecting rod to draw - * \param crankAngle current crankshaft rotation, in radians - */ -static void -DrawPositionedConnectingRod(const Engine *eng, float crankAngle) -{ - float x0, y0, x1, y1; - float d, phi; - - ComputeConnectingRodPosition(eng->Throw, crankAngle, - eng->ConnectingRodLength, - &x0, &y0, &x1, &y1); - d = sqrt(eng->ConnectingRodLength * eng->ConnectingRodLength - x0 * x0); - phi = atan(x0 / d) * 180.0 / M_PI; - - glPushMatrix(); - glTranslatef(x0, y0, 0); - glRotatef(phi, 0, 0, 1); - if (eng->ConnRodList) - glCallList(eng->ConnRodList); - else - DrawConnector(eng->ConnectingRodLength, eng->ConnectingRodThickness, - eng->CrankPinRadius, eng->WristPinRadius); - glPopMatrix(); -} - - -/** - * Draw a square with a hole in middle. - */ -static void -SquareWithHole(float squareSize, float holeRadius) -{ - int i; - glBegin(GL_QUAD_STRIP); - glNormal3f(0, 0, 1); - for (i = 0; i <= 360; i += 5) { - const float x1 = holeRadius * cos(DEG_TO_RAD(i)); - const float y1 = holeRadius * sin(DEG_TO_RAD(i)); - float x2 = 0.0F, y2 = 0.0F; - if (i > 315 || i <= 45) { - x2 = squareSize; - y2 = squareSize * tan(DEG_TO_RAD(i)); - } - else if (i > 45 && i <= 135) { - x2 = -squareSize * tan(DEG_TO_RAD(i - 90)); - y2 = squareSize; - } - else if (i > 135 && i <= 225) { - x2 = -squareSize; - y2 = -squareSize * tan(DEG_TO_RAD(i-180)); - } - else if (i > 225 && i <= 315) { - x2 = squareSize * tan(DEG_TO_RAD(i - 270)); - y2 = -squareSize; - } - glVertex2f(x1, y1); /* inner circle */ - glVertex2f(x2, y2); /* outer square */ - } - glEnd(); -} - - -/** - * Draw block with hole through middle. - * Hole is centered on Z axis. - * Bottom of block is at z=0, top of block is at z = blockHeight. - * index is in [0, count - 1] to determine which block faces are drawn. - */ -static void -DrawBlockWithHole(float blockSize, float blockHeight, float holeRadius, - int index, int count) -{ - const int slices = 30, stacks = 4; - const float x = blockSize; - const float y = blockSize; - const float z0 = 0; - const float z1 = blockHeight; - - assert(index < count); - assert(Q); - gluQuadricOrientation(Q, GLU_INSIDE); - - glBegin(GL_QUADS); - /* +X face */ - glNormal3f(1, 0, 0); - glVertex3f( x, -y, z0); - glVertex3f( x, y, z0); - glVertex3f( x, y, z1); - glVertex3f( x, -y, z1); - /* -X face */ - glNormal3f(-1, 0, 0); - glVertex3f(-x, -y, z1); - glVertex3f(-x, y, z1); - glVertex3f(-x, y, z0); - glVertex3f(-x, -y, z0); - if (index == 0) { - /* +Y face */ - glNormal3f(0, 1, 0); - glVertex3f(-x, y, z1); - glVertex3f( x, y, z1); - glVertex3f( x, y, z0); - glVertex3f(-x, y, z0); - } - if (index == count - 1) { - /* -Y face */ - glNormal3f(0, -1, 0); - glVertex3f(-x, -y, z0); - glVertex3f( x, -y, z0); - glVertex3f( x, -y, z1); - glVertex3f(-x, -y, z1); - } - glEnd(); - - /* cylinder / hole */ - gluCylinder(Q, holeRadius, holeRadius, blockHeight, slices, stacks); - - /* face at z0 */ - glPushMatrix(); - glRotatef(180, 1, 0, 0); - SquareWithHole(blockSize, holeRadius); - glPopMatrix(); - - /* face at z1 */ - glTranslatef(0, 0, z1); - SquareWithHole(blockSize, holeRadius); - - gluQuadricOrientation(Q, GLU_OUTSIDE); -} - - -/** - * Draw the engine block. - */ -static void -DrawEngineBlock(const Engine *eng) -{ - const float blockHeight = eng->Throw + 1.5 * eng->PistonHeight; - const float cylRadius = 1.01 * eng->PistonRadius; - const float blockSize = 0.5 * PistonSpacing(eng); - const int pistonsPerCrank = eng->Pistons / eng->Cranks; - int i; - - for (i = 0; i < eng->Pistons; i++) { - const float z = PistonShaftPosition(eng, i); - const int crank = i / pistonsPerCrank; - int k; - - glPushMatrix(); - glTranslatef(0, 0, z); - - /* additional rotation for kth piston per crank */ - k = i % pistonsPerCrank; - glRotatef(k * -eng->V_Angle, 0, 0, 1); - - /* the block */ - glRotatef(-90, 1, 0, 0); - glTranslatef(0, 0, eng->Throw * 2); - DrawBlockWithHole(blockSize, blockHeight, cylRadius, - crank, eng->Cranks); - glPopMatrix(); - } -} - - -/** - * Generate display lists for engine parts. - */ -static void -GenerateDisplayLists(Engine *eng) -{ - eng->CrankList = glGenLists(1); - glNewList(eng->CrankList, GL_COMPILE); - DrawCrankshaft(eng); - glEndList(); - - eng->ConnRodList = glGenLists(1); - glNewList(eng->ConnRodList, GL_COMPILE); - DrawConnector(eng->ConnectingRodLength, eng->ConnectingRodThickness, - eng->CrankPinRadius, eng->WristPinRadius); - glEndList(); - - eng->PistonList = glGenLists(1); - glNewList(eng->PistonList, GL_COMPILE); - DrawPiston(eng); - glEndList(); - - eng->BlockList = glGenLists(1); - glNewList(eng->BlockList, GL_COMPILE); - DrawEngineBlock(eng); - glEndList(); -} - - -/** - * Free engine display lists (render with immediate mode). - */ -static void -FreeDisplayLists(Engine *eng) -{ - glDeleteLists(eng->CrankList, 1); - eng->CrankList = 0; - glDeleteLists(eng->ConnRodList, 1); - eng->ConnRodList = 0; - glDeleteLists(eng->PistonList, 1); - eng->PistonList = 0; - glDeleteLists(eng->BlockList, 1); - eng->BlockList = 0; -} - - -/** - * Draw complete engine. - * \param eng description of engine to draw - * \param crankAngle current crankshaft angle, in radians - */ -static void -DrawEngine(const Engine *eng, float crankAngle) -{ - const float crankDelta = 360.0 / eng->Cranks; - const float crankLen = CrankshaftLength(eng); - const int pistonsPerCrank = eng->Pistons / eng->Cranks; - int i; - - glPushMatrix(); - glRotatef(eng->V_Angle * 0.5, 0, 0, 1); - glTranslatef(0, 0, -0.5 * crankLen); - - /* crankshaft */ - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, CrankshaftColor); - glColor4fv(CrankshaftColor); - DrawPositionedCrankshaft(eng, crankAngle); - - for (i = 0; i < eng->Pistons; i++) { - const float z = PistonShaftPosition(eng, i); - const int crank = i / pistonsPerCrank; - float rot = crankAngle + crank * crankDelta; - int k; - - glPushMatrix(); - glTranslatef(0, 0, z); - - /* additional rotation for kth piston per crank */ - k = i % pistonsPerCrank; - glRotatef(k * -eng->V_Angle, 0, 0, 1); - rot += k * eng->V_Angle; - - /* piston */ - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, PistonColor); - glColor4fv(PistonColor); - DrawPositionedPiston(eng, rot); - - /* connecting rod */ - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ConnRodColor); - glColor4fv(ConnRodColor); - DrawPositionedConnectingRod(eng, rot); - glPopMatrix(); - } - - if (Render.ShowBlock) { - const GLboolean blend = glIsEnabled(GL_BLEND); - - glDepthMask(GL_FALSE); - if (!blend) { - glEnable(GL_BLEND); - } - glEnable(GL_CULL_FACE); - - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, BlockColor); - glColor4fv(BlockColor); - if (eng->CrankList) - glCallList(eng->BlockList); - else - DrawEngineBlock(eng); - - glDisable(GL_CULL_FACE); - glDepthMask(GL_TRUE); - if (!blend) { - glDisable(GL_BLEND); - } - } - - glPopMatrix(); -} - - -static void -DrawBox(void) -{ - const float xmin = -3.0, xmax = 3.0; - const float ymin = -1.0, ymax = 3.0; - const float zmin = -4.0, zmax = 4.0; - const float step = 0.5; - const float d = 0.01; - float x, y, z; - GLboolean lit = glIsEnabled(GL_LIGHTING); - GLboolean tex = glIsEnabled(GL_TEXTURE_2D); - - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - glLineWidth(1.0); - - glColor3f(1, 1, 1); - - /* Z min */ - glBegin(GL_LINES); - for (x = xmin; x <= xmax; x += step) { - glVertex3f(x, ymin, zmin); - glVertex3f(x, ymax, zmin); - } - glEnd(); - glBegin(GL_LINES); - for (y = ymin; y <= ymax; y += step) { - glVertex3f(xmin, y, zmin); - glVertex3f(xmax, y, zmin); - } - glEnd(); - - /* Y min */ - glBegin(GL_LINES); - for (x = xmin; x <= xmax; x += step) { - glVertex3f(x, ymin, zmin); - glVertex3f(x, ymin, zmax); - } - glEnd(); - glBegin(GL_LINES); - for (z = zmin; z <= zmax; z += step) { - glVertex3f(xmin, ymin, z); - glVertex3f(xmax, ymin, z); - } - glEnd(); - - /* X min */ - glBegin(GL_LINES); - for (y = ymin; y <= ymax; y += step) { - glVertex3f(xmin, y, zmin); - glVertex3f(xmin, y, zmax); - } - glEnd(); - glBegin(GL_LINES); - for (z = zmin; z <= zmax; z += step) { - glVertex3f(xmin, ymin, z); - glVertex3f(xmin, ymax, z); - } - glEnd(); - - glColor3f(0.4, 0.4, 0.6); - glBegin(GL_QUADS); - /* xmin */ - glVertex3f(xmin-d, ymin, zmin); - glVertex3f(xmin-d, ymax, zmin); - glVertex3f(xmin-d, ymax, zmax); - glVertex3f(xmin-d, ymin, zmax); - /* ymin */ - glVertex3f(xmin, ymin-d, zmin); - glVertex3f(xmax, ymin-d, zmin); - glVertex3f(xmax, ymin-d, zmax); - glVertex3f(xmin, ymin-d, zmax); - /* zmin */ - glVertex3f(xmin, ymin, zmin-d); - glVertex3f(xmax, ymin, zmin-d); - glVertex3f(xmax, ymax, zmin-d); - glVertex3f(xmin, ymax, zmin-d); - glEnd(); - - if (lit) - glEnable(GL_LIGHTING); - if (tex) - glEnable(GL_TEXTURE_2D); -} - - -static void -PrintString(const char *s) -{ - while (*s) { - glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); - s++; - } -} - - -static int -ComputeFPS(void) -{ - static double t0 = -1.0; - static int frames = 0; - double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; - static int fps = 0; - - frames++; - - if (t0 < 0.0) { - t0 = t; - fps = 0; - } - else if (t - t0 >= 1.0) { - fps = (int) (frames / (t - t0) + 0.5); - t0 = t; - frames = 0; - } - - return fps; -} - - -static void -Draw(void) -{ - int fps; - GLfloat rot[4][4]; - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glPushMatrix(); - - glTranslatef(0.0, 0.0, -View.Distance); - build_rotmatrix(rot, View.CurQuat); - glMultMatrixf(&rot[0][0]); - - glPushMatrix(); - glTranslatef(0, -0.75, 0); - if (Render.DrawBox) - DrawBox(); - DrawEngine(Engines + CurEngine, Theta); - glPopMatrix(); - - glPopMatrix(); - - fps = ComputeFPS(); - if (Render.ShowInfo) { - GLboolean lit = glIsEnabled(GL_LIGHTING); - GLboolean tex = glIsEnabled(GL_TEXTURE_2D); - char s[100]; - sprintf(s, "%s %d FPS %s", Engines[CurEngine].Name, fps, - Render.UseLists ? "Display Lists" : "Immediate mode"); - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - glColor3f(1, 1 , 1); - glWindowPos2iARB(10, 10); - PrintString(s); - if (lit) - glEnable(GL_LIGHTING); - if (tex) - glEnable(GL_TEXTURE_2D); - } - - /* also print out a periodic fps to stdout. useful for trying to - * figure out the performance impact of rendering the string above - * with glBitmap. - */ - { - static GLint T0 = 0; - static GLint Frames = 0; - GLint t = glutGet(GLUT_ELAPSED_TIME); - - Frames++; - - if (t - T0 >= 5000) { - GLfloat seconds = (t - T0) / 1000.0; - GLfloat fps = Frames / seconds; - printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); - fflush(stdout); - T0 = t; - Frames = 0; - } - } - - - glutSwapBuffers(); -} - - -/** - * Handle window resize. - */ -static void -Reshape(int width, int height) -{ - float ar = (float) width / height; - float s = 0.5; - glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-ar * s, ar * s, -s, s, 2.0, 50.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - WinWidth = width; - WinHeight = height; -} - - -/** - * Handle mouse button. - */ -static void -Mouse(int button, int state, int x, int y) -{ - if (button == GLUT_LEFT_BUTTON) { - if (state == GLUT_DOWN) { - View.StartX = x; - View.StartY = y; - View.Rotating = GL_TRUE; - } - else if (state == GLUT_UP) { - View.Rotating = GL_FALSE; - } - } - else if (button == GLUT_MIDDLE_BUTTON) { - if (state == GLUT_DOWN) { - View.StartX = x; - View.StartY = y; - View.StartDistance = View.Distance; - View.Translating = GL_TRUE; - } - else if (state == GLUT_UP) { - View.Translating = GL_FALSE; - } - } -} - - -/** - * Handle mouse motion - */ -static void -Motion(int x, int y) -{ - int i; - if (View.Rotating) { - float x0 = (2.0 * View.StartX - WinWidth) / WinWidth; - float y0 = (WinHeight - 2.0 * View.StartY) / WinHeight; - float x1 = (2.0 * x - WinWidth) / WinWidth; - float y1 = (WinHeight - 2.0 * y) / WinHeight; - float q[4]; - - trackball(q, x0, y0, x1, y1); - View.StartX = x; - View.StartY = y; - for (i = 0; i < 1; i++) - add_quats(q, View.CurQuat, View.CurQuat); - - glutPostRedisplay(); - } - else if (View.Translating) { - float dz = 0.01 * (y - View.StartY); - View.Distance = View.StartDistance + dz; - glutPostRedisplay(); - } -} - - -/** - ** Menu Callbacks - **/ - -static void -OptAnimation(void) -{ - Render.Anim = !Render.Anim; - if (Render.Anim) - glutIdleFunc(Idle); - else - glutIdleFunc(NULL); -} - -static void -OptChangeEngine(void) -{ - CurEngine = (CurEngine + 1) % NUM_ENGINES; -} - -static void -OptRenderMode(void) -{ - Render.Mode++; - if (Render.Mode > TEXTURED) - Render.Mode = 0; - SetRenderState(Render.Mode); -} - -static void -OptDisplayLists(void) -{ - int i; - Render.UseLists = !Render.UseLists; - if (Render.UseLists) { - for (i = 0; i < NUM_ENGINES; i++) { - GenerateDisplayLists(Engines + i); - } - } - else { - for (i = 0; i < NUM_ENGINES; i++) { - FreeDisplayLists(Engines + i); - } - } -} - -static void -OptShowBlock(void) -{ - Render.ShowBlock = !Render.ShowBlock; -} - -static void -OptShowInfo(void) -{ - Render.ShowInfo = !Render.ShowInfo; -} - -static void -OptShowBox(void) -{ - Render.DrawBox = !Render.DrawBox; -} - -static void -OptRotate(void) -{ - Theta += 5.0; -} - -static void -OptExit(void) -{ - glutDestroyWindow(Win); - exit(0); -} - - -/** - * Define menu entries (w/ keyboard shortcuts) - */ - -typedef struct -{ - const char *Text; - const char Key; - void (*Function)(void); -} MenuInfo; - -static const MenuInfo MenuItems[] = { - { "Animation", 'a', OptAnimation }, - { "Change Engine", 'e', OptChangeEngine }, - { "Rendering Style", 'm', OptRenderMode }, - { "Display Lists", 'd', OptDisplayLists }, - { "Show Block", 'b', OptShowBlock }, - { "Show Info", 'i', OptShowInfo }, - { "Show Box", 'x', OptShowBox }, - { "Exit", 27, OptExit }, - { NULL, 'r', OptRotate }, - { NULL, 0, NULL } -}; - - -/** - * Handle menu selection. - */ -static void -MenuHandler(int entry) -{ - MenuItems[entry].Function(); - glutPostRedisplay(); -} - - -/** - * Make pop-up menu. - */ -static void -MakeMenu(void) -{ - int i; - glutCreateMenu(MenuHandler); - for (i = 0; MenuItems[i].Text; i++) { - glutAddMenuEntry(MenuItems[i].Text, i); - } - glutAttachMenu(GLUT_RIGHT_BUTTON); -} - - -/** - * Handle keyboard event. - */ -static void -Key(unsigned char key, int x, int y) -{ - int i; - (void) x; (void) y; - for (i = 0; MenuItems[i].Key; i++) { - if (MenuItems[i].Key == key) { - MenuItems[i].Function(); - glutPostRedisplay(); - break; - } - } -} - - -static -void LoadTexture(void) -{ - GLboolean convolve = GL_FALSE; - - glGenTextures(1, &TextureObj); - glBindTexture(GL_TEXTURE_2D, TextureObj); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - - if (convolve) { -#define FILTER_SIZE 7 - /* use convolution to blur the texture to simulate a dull finish - * on the object. - */ - GLubyte *img; - GLenum format; - GLint w, h; - GLfloat filter[FILTER_SIZE][FILTER_SIZE][4]; - - for (h = 0; h < FILTER_SIZE; h++) { - for (w = 0; w < FILTER_SIZE; w++) { - const GLfloat k = 1.0 / (FILTER_SIZE * FILTER_SIZE); - filter[h][w][0] = k; - filter[h][w][1] = k; - filter[h][w][2] = k; - filter[h][w][3] = k; - } - } - - glEnable(GL_CONVOLUTION_2D); - glConvolutionParameteri(GL_CONVOLUTION_2D, - GL_CONVOLUTION_BORDER_MODE, GL_CONSTANT_BORDER); - glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_RGBA, - FILTER_SIZE, FILTER_SIZE, - GL_RGBA, GL_FLOAT, filter); - - img = LoadRGBImage(TEXTURE_FILE, &w, &h, &format); - if (!img) { - printf("Error: couldn't load texture image file %s\n", TEXTURE_FILE); - exit(1); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, - format, GL_UNSIGNED_BYTE, img); - free(img); - } - else { - if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) { - printf("Error: couldn't load texture image file %s\n", TEXTURE_FILE); - exit(1); - } - } -} - - -static void -Init(void) -{ - const GLfloat lightColor[4] = { 0.7, 0.7, 0.7, 1.0 }; - const GLfloat specular[4] = { 0.8, 0.8, 0.8, 1.0 }; - const GLfloat backColor[4] = { 1, 1, 0, 0 }; - - Q = gluNewQuadric(); - gluQuadricNormals(Q, GLU_SMOOTH); - - LoadTexture(); - - glClearColor(0.3, 0.3, 0.3, 0.0); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); - glMaterialf(GL_FRONT, GL_SHININESS, 40); - glMaterialfv(GL_FRONT, GL_SPECULAR, specular); - glEnable(GL_NORMALIZE); - - glMaterialfv(GL_BACK, GL_DIFFUSE, backColor); -#if 0 - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); -#endif - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - InitViewInfo(&View); - InitRenderInfo(&Render); -} - - -int -main(int argc, char *argv[]) -{ - glutInitWindowSize(WinWidth, WinHeight); - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); - Win = glutCreateWindow("OpenGL Engine Demo"); - glewInit(); - glutReshapeFunc(Reshape); - glutMouseFunc(Mouse); - glutMotionFunc(Motion); - glutKeyboardFunc(Key); - glutDisplayFunc(Draw); - MakeMenu(); - Init(); - if (Render.Anim) - glutIdleFunc(Idle); - glutMainLoop(); - return 0; -} |