diff options
author | David Nusinow <[email protected]> | 2006-09-24 21:29:21 +0000 |
---|---|---|
committer | David Nusinow <[email protected]> | 2006-09-24 21:29:21 +0000 |
commit | a0b2543ba165f77ed4764dd0c53956f1b2a0f92f (patch) | |
tree | a6fb278cada5b130396da8b8309ec78a42ca2199 | |
parent | 387acaac6925e42f47031f26360e33a3f30e7312 (diff) |
Add mesa demos
30 files changed, 4549 insertions, 155 deletions
diff --git a/debian/changelog b/debian/changelog index e58dd19e9f9..db79d842e2a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ mesa (6.5.1-0.1) UNRELEASED; urgency=low * New upstream version + * Build-dep on x11proto-gl-dev >= 1.4.8 - -- David Nusinow <[email protected]> Sun, 24 Sep 2006 17:19:55 -0400 + -- David Nusinow <[email protected]> Sun, 24 Sep 2006 17:23:23 -0400 mesa (6.5.0.cvs.20060524-1.1) unstable; urgency=medium diff --git a/debian/control b/debian/control index fd91268235b..63834ba2e0f 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: Mesa package maintainers <[email protected]> Uploaders: Marcelo E. Magallon <[email protected]> Standards-Version: 3.7.2 -Build-Depends: lesstif2-dev, grep-dctrl, debhelper (>> 4), build-essential (>= 11), libdrm-dev (>> 2) [!hurd-i386], libdirectfb-dev, xutils, libexpat-dev, libxxf86vm-dev, libx11-dev, libxext-dev, pkg-config, x11proto-gl-dev, dpkg-dev (>= 1.13.19) +Build-Depends: lesstif2-dev, grep-dctrl, debhelper (>> 4), build-essential (>= 11), libdrm-dev (>> 2) [!hurd-i386], libdirectfb-dev, xutils, libexpat-dev, libxxf86vm-dev, libx11-dev, libxext-dev, pkg-config, x11proto-gl-dev (>= 1.4.8) , dpkg-dev (>= 1.13.19) Package: libgl1-mesa-swx11 Section: libs diff --git a/progs/beos/demo.cpp b/progs/beos/demo.cpp index 42f316a71f1..6b0b9576d66 100644 --- a/progs/beos/demo.cpp +++ b/progs/beos/demo.cpp @@ -1,4 +1,4 @@ -// $Id: demo.cpp,v 1.2 2004-08-14 09:59:16 phoudoin Exp $ +// $Id: demo.cpp,v 1.2 2004/08/14 09:59:16 phoudoin Exp $ // Simple BeOS GLView demo // Written by Brian Paul diff --git a/progs/demos/Makefile b/progs/demos/Makefile index c7a4cc7b828..43d0f17c85f 100644 --- a/progs/demos/Makefile +++ b/progs/demos/Makefile @@ -5,13 +5,13 @@ include $(TOP)/configs/current INCDIR = $(TOP)/include -OSMESA_LIBS = -L$(LIB_DIR) -lglut -lOSMesa -lGLU -lGL $(APP_LIB_DEPS) +OSMESA_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa -lGLU -lGL $(APP_LIB_DEPS) -OSMESA16_LIBS = -L$(LIB_DIR) -lglut -lOSMesa16 -lGLU -lGL $(APP_LIB_DEPS) +OSMESA16_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa16 -lGLU -lGL $(APP_LIB_DEPS) -OSMESA32_LIBS = -L$(LIB_DIR) -lglut -lOSMesa32 -lGLU -lGL $(APP_LIB_DEPS) +OSMESA32_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa32 -lGLU -lGL $(APP_LIB_DEPS) -LIB_DEP = $(LIB_DIR)/$(GL_LIB_NAME) $(LIB_DIR)/$(GLU_LIB_NAME) $(LIB_DIR)/$(GLUT_LIB_NAME) +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME) PROGS = \ arbfplight \ @@ -21,6 +21,7 @@ PROGS = \ clearspd \ cubemap \ drawpix \ + engine \ fire \ fogcoord \ fplight \ @@ -38,7 +39,6 @@ PROGS = \ lodbias \ morph3d \ multiarb \ - occlude \ paltex \ pointblast \ ray \ @@ -60,6 +60,7 @@ PROGS = \ trispd \ tunnel \ tunnel2 \ + vao_demo \ winpos @@ -100,6 +101,16 @@ showbuffer.o: showbuffer.c showbuffer.h $(CC) -c -I$(INCDIR) $(CFLAGS) showbuffer.c +trackball.c: $(TOP)/progs/util/trackball.c + cp $< . + +trackball.h: $(TOP)/progs/util/trackball.h + cp $< . + +trackball.o: trackball.c trackball.h + $(CC) -c -I$(INCDIR) $(CFLAGS) trackball.c + + reflect: reflect.o showbuffer.o readtex.o $(CC) -I$(INCDIR) $(CFLAGS) reflect.o showbuffer.o readtex.o $(APP_LIB_DEPS) -o $@ @@ -113,6 +124,21 @@ shadowtex: shadowtex.o showbuffer.o shadowtex.o: shadowtex.c showbuffer.h $(CC) -c -I$(INCDIR) $(CFLAGS) shadowtex.c + +gloss: gloss.o trackball.o readtex.o + $(CC) -I$(INCDIR) $(CFLAGS) gloss.o trackball.o readtex.o $(APP_LIB_DEPS) -o $@ + +gloss.o: gloss.c trackball.h + $(CC) -c -I$(INCDIR) $(CFLAGS) gloss.c + + +engine: engine.o trackball.o readtex.o + $(CC) -I$(INCDIR) $(CFLAGS) engine.o trackball.o readtex.o $(APP_LIB_DEPS) -o $@ + +engine.o: engine.c trackball.h + $(CC) -c -I$(INCDIR) $(CFLAGS) engine.c + + clean: -rm -f $(PROGS) -rm -f *.o *~ diff --git a/progs/demos/arbfslight.c b/progs/demos/arbfslight.c index 30332a3f641..374de568872 100644 --- a/progs/demos/arbfslight.c +++ b/progs/demos/arbfslight.c @@ -16,6 +16,7 @@ #include <stdio.h> #include <stdlib.h> +#include <math.h> #include <GL/gl.h> #include <GL/glut.h> #include <GL/glext.h> @@ -56,7 +57,16 @@ static PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL; static PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL; static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL; static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL; -static PFNGLUNIFORM4FVARBPROC glUniform4fvARB = NULL; +static PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL; +static PFNGLUNIFORM3FVARBPROC glUniform4fvARB = NULL; + +static void normalize (GLfloat *dst, const GLfloat *src) +{ + GLfloat len = sqrtf (src[0] * src[0] + src[1] * src[1] + src[2] * src[2]); + dst[0] = src[0] / len; + dst[1] = src[1] / len; + dst[2] = src[2] / len; +} static void Redisplay (void) { @@ -64,8 +74,11 @@ static void Redisplay (void) if (pixelLight) { + GLfloat vec[3]; + glUseProgramObjectARB (program); - glUniform4fvARB (uLightPos, 1, lightPos); + normalize (vec, lightPos); + glUniform3fvARB (uLightPos, 1, vec); glDisable(GL_LIGHTING); } else @@ -186,24 +199,25 @@ static void SpecialKey (int key, int x, int y) static void Init (void) { - static const char *fragShaderText = - "uniform vec4 lightPos;\n" - "uniform vec4 diffuse;\n" - "uniform vec4 specular;\n" - "void main () {\n" - " // Compute dot product of light direction and normal vector\n" - " float dotProd;\n" - " dotProd = clamp (dot (normalize (lightPos).xyz, normalize (gl_TexCoord[0]).xyz), 0.0, 1.0);\n" - " // Compute diffuse and specular contributions\n" - " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n" - "}\n" - ; - static const char *vertShaderText = - "void main () {\n" - " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" - " gl_TexCoord[0] = vec4 (gl_NormalMatrix * gl_Normal, 1.0);\n" - "}\n" - ; + static const char *fragShaderText = + "uniform vec3 lightPos;\n" + "uniform vec4 diffuse;\n" + "uniform vec4 specular;\n" + "varying vec3 normal;\n" + "void main () {\n" + " // Compute dot product of light direction and normal vector\n" + " float dotProd = max (dot (lightPos, normalize (normal)), 0.0);\n" + " // Compute diffuse and specular contributions\n" + " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n" + "}\n" + ; + static const char *vertShaderText = + "varying vec3 normal;\n" + "void main () {\n" + " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " normal = gl_NormalMatrix * gl_Normal;\n" + "}\n" + ; if (!glutExtensionSupported ("GL_ARB_fragment_shader")) { @@ -234,7 +248,8 @@ static void Init (void) glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GETPROCADDRESS ("glLinkProgramARB"); glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glUseProgramObjectARB"); glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GETPROCADDRESS ("glGetUniformLocationARB"); - glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GETPROCADDRESS ("glUniform4fvARB"); + glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform3fvARB"); + glUniform4fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform4fvARB"); fragShader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB); glShaderSourceARB (fragShader, 1, &fragShaderText, NULL); @@ -254,8 +269,8 @@ static void Init (void) uDiffuse = glGetUniformLocationARB (program, "diffuse"); uSpecular = glGetUniformLocationARB (program, "specular"); - glUniform4fvARB (uDiffuse, 1, diffuse); - glUniform4fvARB (uSpecular, 1, specular); + glUniform4fvARB (uDiffuse, 1, diffuse); + glUniform4fvARB (uSpecular, 1, specular); glClearColor (0.3f, 0.3f, 0.3f, 0.0f); glEnable (GL_DEPTH_TEST); diff --git a/progs/demos/engine.c b/progs/demos/engine.c new file mode 100644 index 00000000000..143b02a8894 --- /dev/null +++ b/progs/demos/engine.c @@ -0,0 +1,1293 @@ +/** + * Simple engine demo (crankshaft, pistons, connecting rods) + * + * Brian Paul + * June 2006 + */ + +#define GL_GLEXT_PROTOTYPES + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <GL/glut.h> +#include "readtex.h" +#include "trackball.h" + + +#define DEG_TO_RAD(DEG) ((DEG) * M_PI / 180.0) + +#define TEXTURE_FILE "../images/reflect.rgb" + +/* Target engine speed: */ +const int RPM = 100.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 */ + }, + { + "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 */ + }, + { + "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 */ + } +}; + +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); + 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], z0); + glVertex3f(points[j][0], points[j][1], z1); + } + 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, y2; + 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_AND_BACK, 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_AND_BACK, GL_AMBIENT_AND_DIFFUSE, PistonColor); + glColor4fv(PistonColor); + DrawPositionedPiston(eng, rot); + + /* connecting rod */ + glMaterialfv(GL_FRONT_AND_BACK, 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_AND_BACK, 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); + + 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); + } + + 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) +{ + 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 }; + + 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_AND_BACK, GL_SHININESS, 40); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); + glEnable(GL_NORMALIZE); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + InitViewInfo(&View); + InitRenderInfo(&Render); +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowSize(WinWidth, WinHeight); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + glutCreateWindow("OpenGL Engine Demo"); + glutReshapeFunc(Reshape); + glutMouseFunc(Mouse); + glutMotionFunc(Motion); + glutKeyboardFunc(Key); + glutDisplayFunc(Draw); + MakeMenu(); + Init(); + if (Render.Anim) + glutIdleFunc(Idle); + glutMainLoop(); + return 0; +} diff --git a/progs/demos/gloss.c b/progs/demos/gloss.c index 0b2e7426d53..9974f0dab2e 100644 --- a/progs/demos/gloss.c +++ b/progs/demos/gloss.c @@ -25,6 +25,8 @@ #include <GL/glut.h> #include "readtex.h" +#include "trackball.h" + #define SPECULAR_TEXTURE_FILE "../images/reflect.rgb" #define BASE_TEXTURE_FILE "../images/tile.rgb" @@ -44,8 +46,7 @@ static GLuint TeapotObj = 0; static GLuint Object = 0; static GLboolean Animate = GL_TRUE; -static GLfloat Xrot = 0.0, Yrot = 0.0, Zrot = 0.0; -static GLfloat DXrot = 20.0, DYrot = 50.; +static float CurQuat[4] = { 0, 0, 0, 1 }; static GLfloat Black[4] = { 0, 0, 0, 0 }; static GLfloat White[4] = { 1, 1, 1, 1 }; @@ -57,7 +58,6 @@ static GLboolean DoSpecTexture = GL_TRUE; static GLboolean ButtonDown = GL_FALSE; static GLint ButtonX, ButtonY; -static GLfloat Xrot0, Yrot0; /* performance info */ @@ -67,29 +67,31 @@ static GLint Frames = 0; static void Idle( void ) { + static const float yAxis[3] = {0, 1, 0}; static double t0 = -1.; + float quat[4]; double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; if (t0 < 0.0) t0 = t; dt = t - t0; t0 = t; - if (Animate) { - Xrot += DXrot*dt; - Yrot += DYrot*dt; - glutPostRedisplay(); - } + axis_to_quat(yAxis, 2.0 * dt, quat); + add_quats(quat, CurQuat, CurQuat); + + glutPostRedisplay(); } static void Display( void ) { + GLfloat rot[4][4]; + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); - glRotatef(Xrot, 1.0, 0.0, 0.0); - glRotatef(Yrot, 0.0, 1.0, 0.0); - glRotatef(Zrot, 0.0, 0.0, 1.0); + build_rotmatrix(rot, CurQuat); + glMultMatrixf(&rot[0][0]); /* First pass: diffuse lighting with base texture */ glMaterialfv(GL_FRONT, GL_DIFFUSE, Diffuse); @@ -218,39 +220,21 @@ static void Key( unsigned char key, int x, int y ) } -static void SpecialKey( int key, int x, int y ) -{ - float step = 3.0; - (void) x; - (void) y; - - switch (key) { - case GLUT_KEY_UP: - Xrot += step; - break; - case GLUT_KEY_DOWN: - Xrot -= step; - break; - case GLUT_KEY_LEFT: - Yrot += step; - break; - case GLUT_KEY_RIGHT: - Yrot -= step; - break; - } - glutPostRedisplay(); -} - - static void MouseMotion(int x, int y) { - const float k = 300.0; if (ButtonDown) { - float dx = x - ButtonX; - float dy = y - ButtonY; - Xrot = Xrot0 + k * dy / WinWidth; - Yrot = Yrot0 + k * dx / WinHeight; + float x0 = (2.0 * ButtonX - WinWidth) / WinWidth; + float y0 = (WinHeight - 2.0 * ButtonY) / WinHeight; + float x1 = (2.0 * x - WinWidth) / WinWidth; + float y1 = (WinHeight - 2.0 * y) / WinHeight; + float q[4]; + + trackball(q, x0, y0, x1, y1); + ButtonX = x; + ButtonY = y; + add_quats(q, CurQuat, CurQuat); + glutPostRedisplay(); } } @@ -263,8 +247,6 @@ MouseButton(int button, int state, int x, int y) ButtonDown = GL_TRUE; ButtonX = x; ButtonY = y; - Xrot0 = Xrot; - Yrot0 = Yrot; } else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { ButtonDown = GL_FALSE; @@ -453,18 +435,11 @@ static void Init( int argc, char *argv[] ) int main( int argc, char *argv[] ) { glutInit( &argc, argv ); - glutInitWindowPosition(0, 0); glutInitWindowSize(WinWidth, WinHeight); - glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); - glutCreateWindow(argv[0] ); - - Init(argc, argv); - glutReshapeFunc( Reshape ); glutKeyboardFunc( Key ); - glutSpecialFunc( SpecialKey ); glutDisplayFunc( Display ); glutMotionFunc(MouseMotion); glutMouseFunc(MouseButton); @@ -478,6 +453,8 @@ int main( int argc, char *argv[] ) glutAddMenuEntry("Quit", QUIT); glutAttachMenu(GLUT_RIGHT_BUTTON); + Init(argc, argv); + glutMainLoop(); return 0; } diff --git a/progs/demos/glslnoise.c b/progs/demos/glslnoise.c index 2adb114e668..4ee12928164 100755 --- a/progs/demos/glslnoise.c +++ b/progs/demos/glslnoise.c @@ -30,6 +30,9 @@ static GLhandleARB program; static GLint uTime; +static GLint t0 = 0; +static GLint frames = 0; + static GLfloat u_time = 0.0f; static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL; @@ -44,15 +47,27 @@ static PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL; static void Redisplay (void) { + GLint t; + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glUniform1fARB (uTime, u_time); + glUniform1fARB (uTime, 0.5f * u_time); glPushMatrix (); glutSolidSphere (2.0, 20, 10); glPopMatrix (); glutSwapBuffers(); + frames++; + + t = glutGet (GLUT_ELAPSED_TIME); + if (t - t0 >= 5000) { + GLfloat seconds = (GLfloat) (t - t0) / 1000.0f; + GLfloat fps = frames / seconds; + printf ("%d frames in %6.3f seconds = %6.3f FPS\n", frames, seconds, fps); + t0 = t; + frames = 0; + } } static void Idle (void) @@ -88,20 +103,20 @@ static void Key (unsigned char key, int x, int y) static void Init (void) { - static const char *fragShaderText = - "uniform float time;\n" - "void main () {\n" - " gl_FragColor = gl_Color * vec4 ((0.5 + 0.5 * vec3 (noise1 (\n" - " vec4 (4.0 * gl_TexCoord[0].xyz, 0.5 * time)))), 1.0);\n" - "}\n" - ; - static const char *vertShaderText = - "void main () {\n" - " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" - " gl_TexCoord[0] = gl_Vertex;\n" - " gl_FrontColor = gl_Color;\n" - "}\n" - ; + static const char *fragShaderText = + "uniform float time;\n" + "varying vec3 position;\n" + "void main () {\n" + " gl_FragColor = vec4 (vec3 (0.5 + 0.5 * noise1 (vec4 (position, time))), 1.0);\n" + "}\n" + ; + static const char *vertShaderText = + "varying vec3 position;\n" + "void main () {\n" + " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " position = 4.0 * gl_Vertex.xyz;\n" + "}\n" + ; if (!glutExtensionSupported ("GL_ARB_fragment_shader")) { diff --git a/progs/demos/pointblast.c b/progs/demos/pointblast.c index 715813f1763..dbbe2f35a28 100644 --- a/progs/demos/pointblast.c +++ b/progs/demos/pointblast.c @@ -471,6 +471,11 @@ main(int argc, char **argv) glutAddMenuEntry("Quit", 666); glutAttachMenu(GLUT_RIGHT_BUTTON); + if (!glutExtensionSupported("GL_ARB_point_parameters")) { + fprintf(stderr, "Sorry, GL_ARB_point_parameters is not supported.\n"); + return -1; + } + glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glEnable(GL_POINT_SMOOTH); diff --git a/progs/demos/readtex.c b/progs/demos/readtex.c new file mode 100644 index 00000000000..37d5fcd0d3a --- /dev/null +++ b/progs/demos/readtex.c @@ -0,0 +1,454 @@ +/* readtex.c */ + +/* + * Read an SGI .rgb image file and generate a mipmap texture set. + * Much of this code was borrowed from SGI's tk OpenGL toolkit. + */ + + + +#include <GL/gl.h> +#include <GL/glu.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "readtex.h" + + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + + +/* +** RGB Image Structure +*/ + +typedef struct _TK_RGBImageRec { + GLint sizeX, sizeY; + GLint components; + unsigned char *data; +} TK_RGBImageRec; + + + +/******************************************************************************/ + +typedef struct _rawImageRec { + unsigned short imagic; + unsigned short type; + unsigned short dim; + unsigned short sizeX, sizeY, sizeZ; + unsigned long min, max; + unsigned long wasteBytes; + char name[80]; + unsigned long colorMap; + FILE *file; + unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA; + unsigned long rleEnd; + GLuint *rowStart; + GLint *rowSize; +} rawImageRec; + +/******************************************************************************/ + +static void ConvertShort(unsigned short *array, long length) +{ + unsigned long b1, b2; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + *array++ = (unsigned short) ((b1 << 8) | (b2)); + } +} + +static void ConvertLong(GLuint *array, long length) +{ + unsigned long b1, b2, b3, b4; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + b3 = *ptr++; + b4 = *ptr++; + *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); + } +} + +static rawImageRec *RawImageOpen(const char *fileName) +{ + union { + int testWord; + char testByte[4]; + } endianTest; + rawImageRec *raw; + GLenum swapFlag; + int x; + + endianTest.testWord = 1; + if (endianTest.testByte[0] == 1) { + swapFlag = GL_TRUE; + } else { + swapFlag = GL_FALSE; + } + + raw = (rawImageRec *)calloc(1, sizeof(rawImageRec)); + if (raw == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + if ((raw->file = fopen(fileName, "rb")) == NULL) { + perror(fileName); + return NULL; + } + + fread(raw, 1, 12, raw->file); + + if (swapFlag) { + ConvertShort(&raw->imagic, 6); + } + + raw->tmp = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpR = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpG = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpB = (unsigned char *)malloc(raw->sizeX*256); + if (raw->sizeZ==4) { + raw->tmpA = (unsigned char *)malloc(raw->sizeX*256); + } + if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL || + raw->tmpB == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + + if ((raw->type & 0xFF00) == 0x0100) { + x = raw->sizeY * raw->sizeZ * sizeof(GLuint); + raw->rowStart = (GLuint *)malloc(x); + raw->rowSize = (GLint *)malloc(x); + if (raw->rowStart == NULL || raw->rowSize == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + raw->rleEnd = 512 + (2 * x); + fseek(raw->file, 512, SEEK_SET); + fread(raw->rowStart, 1, x, raw->file); + fread(raw->rowSize, 1, x, raw->file); + if (swapFlag) { + ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint))); + ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint))); + } + } + return raw; +} + +static void RawImageClose(rawImageRec *raw) +{ + fclose(raw->file); + free(raw->tmp); + free(raw->tmpR); + free(raw->tmpG); + free(raw->tmpB); + if (raw->rowStart) + free(raw->rowStart); + if (raw->rowSize) + free(raw->rowSize); + if (raw->sizeZ>3) { + free(raw->tmpA); + } + free(raw); +} + +static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) +{ + unsigned char *iPtr, *oPtr, pixel; + int count, done = 0; + + if ((raw->type & 0xFF00) == 0x0100) { + fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET); + fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY], + raw->file); + + iPtr = raw->tmp; + oPtr = buf; + while (!done) { + pixel = *iPtr++; + count = (int)(pixel & 0x7F); + if (!count) { + done = 1; + return; + } + if (pixel & 0x80) { + while (count--) { + *oPtr++ = *iPtr++; + } + } else { + pixel = *iPtr++; + while (count--) { + *oPtr++ = pixel; + } + } + } + } else { + fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY), + SEEK_SET); + fread(buf, 1, raw->sizeX, raw->file); + } +} + + +static void RawImageGetData(rawImageRec *raw, TK_RGBImageRec *final) +{ + unsigned char *ptr; + int i, j; + + final->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4); + if (final->data == NULL) { + fprintf(stderr, "Out of memory!\n"); + } + + ptr = final->data; + for (i = 0; i < (int)(raw->sizeY); i++) { + RawImageGetRow(raw, raw->tmpR, i, 0); + RawImageGetRow(raw, raw->tmpG, i, 1); + RawImageGetRow(raw, raw->tmpB, i, 2); + if (raw->sizeZ>3) { + RawImageGetRow(raw, raw->tmpA, i, 3); + } + for (j = 0; j < (int)(raw->sizeX); j++) { + *ptr++ = *(raw->tmpR + j); + *ptr++ = *(raw->tmpG + j); + *ptr++ = *(raw->tmpB + j); + if (raw->sizeZ>3) { + *ptr++ = *(raw->tmpA + j); + } + } + } +} + + +static TK_RGBImageRec *tkRGBImageLoad(const char *fileName) +{ + rawImageRec *raw; + TK_RGBImageRec *final; + + raw = RawImageOpen(fileName); + if (!raw) { + fprintf(stderr, "File not found\n"); + return NULL; + } + final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec)); + if (final == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + final->sizeX = raw->sizeX; + final->sizeY = raw->sizeY; + final->components = raw->sizeZ; + RawImageGetData(raw, final); + RawImageClose(raw); + return final; +} + + +static void FreeImage( TK_RGBImageRec *image ) +{ + free(image->data); + free(image); +} + + +/* + * Load an SGI .rgb file and generate a set of 2-D mipmaps from it. + * Input: imageFile - name of .rgb to read + * intFormat - internal texture format to use, or number of components + * Return: GL_TRUE if success, GL_FALSE if error. + */ +GLboolean LoadRGBMipmaps( const char *imageFile, GLint intFormat ) +{ + GLint w, h; + return LoadRGBMipmaps2( imageFile, GL_TEXTURE_2D, intFormat, &w, &h ); +} + + + +GLboolean LoadRGBMipmaps2( const char *imageFile, GLenum target, + GLint intFormat, GLint *width, GLint *height ) +{ + GLint error; + GLenum format; + TK_RGBImageRec *image; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return GL_FALSE; + } + + if (image->components==3) { + format = GL_RGB; + } + else if (image->components==4) { + format = GL_RGBA; + } + else { + /* not implemented */ + fprintf(stderr, + "Error in LoadRGBMipmaps %d-component images not implemented\n", + image->components ); + return GL_FALSE; + } + + error = gluBuild2DMipmaps( target, + intFormat, + image->sizeX, image->sizeY, + format, + GL_UNSIGNED_BYTE, + image->data ); + + *width = image->sizeX; + *height = image->sizeY; + + FreeImage(image); + + return error ? GL_FALSE : GL_TRUE; +} + + + +/* + * Load an SGI .rgb file and return a pointer to the image data. + * Input: imageFile - name of .rgb to read + * Output: width - width of image + * height - height of image + * format - format of image (GL_RGB or GL_RGBA) + * Return: pointer to image data or NULL if error + */ +GLubyte *LoadRGBImage( const char *imageFile, GLint *width, GLint *height, + GLenum *format ) +{ + TK_RGBImageRec *image; + GLint bytes; + GLubyte *buffer; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return NULL; + } + + if (image->components==3) { + *format = GL_RGB; + } + else if (image->components==4) { + *format = GL_RGBA; + } + else { + /* not implemented */ + fprintf(stderr, + "Error in LoadRGBImage %d-component images not implemented\n", + image->components ); + return NULL; + } + + *width = image->sizeX; + *height = image->sizeY; + + bytes = image->sizeX * image->sizeY * image->components; + buffer = (GLubyte *) malloc(bytes); + if (!buffer) + return NULL; + + memcpy( (void *) buffer, (void *) image->data, bytes ); + + FreeImage(image); + + return buffer; +} + +#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) + + +static void ConvertRGBtoYUV(GLint w, GLint h, GLint texel_bytes, + const GLubyte *src, + GLushort *dest) +{ + GLint i, j; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + const GLfloat r = (src[0]) / 255.0; + const GLfloat g = (src[1]) / 255.0; + const GLfloat b = (src[2]) / 255.0; + GLfloat y, cr, cb; + GLint iy, icr, icb; + + y = r * 65.481 + g * 128.553 + b * 24.966 + 16; + cb = r * -37.797 + g * -74.203 + b * 112.0 + 128; + cr = r * 112.0 + g * -93.786 + b * -18.214 + 128; + /*printf("%f %f %f -> %f %f %f\n", r, g, b, y, cb, cr);*/ + iy = (GLint) CLAMP(y, 0, 254); + icb = (GLint) CLAMP(cb, 0, 254); + icr = (GLint) CLAMP(cr, 0, 254); + + if (j & 1) { + /* odd */ + *dest = (iy << 8) | icr; + } + else { + /* even */ + *dest = (iy << 8) | icb; + } + dest++; + src += texel_bytes; + } + } +} + + +/* + * Load an SGI .rgb file and return a pointer to the image data, converted + * to 422 yuv. + * + * Input: imageFile - name of .rgb to read + * Output: width - width of image + * height - height of image + * Return: pointer to image data or NULL if error + */ +GLushort *LoadYUVImage( const char *imageFile, GLint *width, GLint *height ) +{ + TK_RGBImageRec *image; + GLushort *buffer; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return NULL; + } + + if (image->components != 3 && image->components !=4 ) { + /* not implemented */ + fprintf(stderr, + "Error in LoadYUVImage %d-component images not implemented\n", + image->components ); + return NULL; + } + + *width = image->sizeX; + *height = image->sizeY; + + buffer = (GLushort *) malloc( image->sizeX * image->sizeY * 2 ); + + if (buffer) + ConvertRGBtoYUV( image->sizeX, + image->sizeY, + image->components, + image->data, + buffer ); + + + FreeImage(image); + return buffer; +} + diff --git a/progs/demos/readtex.h b/progs/demos/readtex.h new file mode 100644 index 00000000000..6c9a3828d38 --- /dev/null +++ b/progs/demos/readtex.h @@ -0,0 +1,26 @@ +/* readtex.h */ + +#ifndef READTEX_H +#define READTEX_H + + +#include <GL/gl.h> + + +extern GLboolean +LoadRGBMipmaps( const char *imageFile, GLint intFormat ); + + +extern GLboolean +LoadRGBMipmaps2( const char *imageFile, GLenum target, + GLint intFormat, GLint *width, GLint *height ); + + +extern GLubyte * +LoadRGBImage( const char *imageFile, + GLint *width, GLint *height, GLenum *format ); + +extern GLushort * +LoadYUVImage( const char *imageFile, GLint *width, GLint *height ); + +#endif diff --git a/progs/demos/showbuffer.c b/progs/demos/showbuffer.c new file mode 100644 index 00000000000..17f84dc62bd --- /dev/null +++ b/progs/demos/showbuffer.c @@ -0,0 +1,192 @@ +/* showbuffer.c */ + + +/* + * Copy the depth buffer to the color buffer as a grayscale image. + * Useful for inspecting the depth buffer values. + * + * This program is in the public domain. + * + * Brian Paul November 4, 1998 + */ + + +#include <assert.h> +#include <stdlib.h> +#include <GL/gl.h> +#include "showbuffer.h" + + + +/* + * Copy the depth buffer values into the current color buffer as a + * grayscale image. + * Input: winWidth, winHeight - size of the window + * zBlack - the Z value which should map to black (usually 1) + * zWhite - the Z value which should map to white (usually 0) + */ +void +ShowDepthBuffer( GLsizei winWidth, GLsizei winHeight, + GLfloat zBlack, GLfloat zWhite ) +{ + GLfloat *depthValues; + + assert(zBlack >= 0.0); + assert(zBlack <= 1.0); + assert(zWhite >= 0.0); + assert(zWhite <= 1.0); + assert(zBlack != zWhite); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + /* Read depth values */ + depthValues = (GLfloat *) malloc(winWidth * winHeight * sizeof(GLfloat)); + assert(depthValues); + glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, + GL_FLOAT, depthValues); + + /* Map Z values from [zBlack, zWhite] to gray levels in [0, 1] */ + /* Not using glPixelTransfer() because it's broke on some systems! */ + if (zBlack != 0.0 || zWhite != 1.0) { + GLfloat scale = 1.0 / (zWhite - zBlack); + GLfloat bias = -zBlack * scale; + int n = winWidth * winHeight; + int i; + for (i = 0; i < n; i++) + depthValues[i] = depthValues[i] * scale + bias; + } + + /* save GL state */ + glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | + GL_TRANSFORM_BIT | GL_VIEWPORT_BIT); + + /* setup raster pos for glDrawPixels */ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0.0, (GLdouble) winWidth, 0.0, (GLdouble) winHeight, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glRasterPos2f(0, 0); + + glDrawPixels(winWidth, winHeight, GL_LUMINANCE, GL_FLOAT, depthValues); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + free(depthValues); + + glPopAttrib(); +} + + + + +/* + * Copy the alpha channel values into the current color buffer as a + * grayscale image. + * Input: winWidth, winHeight - size of the window + */ +void +ShowAlphaBuffer( GLsizei winWidth, GLsizei winHeight ) +{ + GLubyte *alphaValues; + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + /* Read alpha values */ + alphaValues = (GLubyte *) malloc(winWidth * winHeight * sizeof(GLubyte)); + assert(alphaValues); + glReadPixels(0, 0, winWidth, winHeight, GL_ALPHA, GL_UNSIGNED_BYTE, alphaValues); + + /* save GL state */ + glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL | + GL_TRANSFORM_BIT | GL_VIEWPORT_BIT); + + /* setup raster pos for glDrawPixels */ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0.0, (GLdouble) winWidth, 0.0, (GLdouble) winHeight, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glRasterPos2f(0, 0); + + glDrawPixels(winWidth, winHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, alphaValues); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + free(alphaValues); + + glPopAttrib(); +} + + + +/* + * Copy the stencil buffer values into the current color buffer as a + * grayscale image. + * Input: winWidth, winHeight - size of the window + * scale, bias - scale and bias to apply to stencil values for display + */ +void +ShowStencilBuffer( GLsizei winWidth, GLsizei winHeight, + GLfloat scale, GLfloat bias ) +{ + GLubyte *stencilValues; + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + /* Read stencil values */ + stencilValues = (GLubyte *) malloc(winWidth * winHeight * sizeof(GLubyte)); + assert(stencilValues); + glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilValues); + + /* save GL state */ + glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | + GL_PIXEL_MODE_BIT | GL_TRANSFORM_BIT | GL_VIEWPORT_BIT); + + /* setup raster pos for glDrawPixels */ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0.0, (GLdouble) winWidth, 0.0, (GLdouble) winHeight, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glRasterPos2f(0, 0); + + glPixelTransferf(GL_RED_SCALE, scale); + glPixelTransferf(GL_RED_BIAS, bias); + glPixelTransferf(GL_GREEN_SCALE, scale); + glPixelTransferf(GL_GREEN_BIAS, bias); + glPixelTransferf(GL_BLUE_SCALE, scale); + glPixelTransferf(GL_BLUE_BIAS, bias); + + glDrawPixels(winWidth, winHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, stencilValues); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + free(stencilValues); + + glPopAttrib(); +} diff --git a/progs/demos/showbuffer.h b/progs/demos/showbuffer.h new file mode 100644 index 00000000000..63533d8e9b5 --- /dev/null +++ b/progs/demos/showbuffer.h @@ -0,0 +1,36 @@ +/* showbuffer. h*/ + +/* + * Copy the depth buffer to the color buffer as a grayscale image. + * Useful for inspecting the depth buffer values. + * + * This program is in the public domain. + * + * Brian Paul November 4, 1998 + */ + + +#ifndef SHOWBUFFER_H +#define SHOWBUFFER_H + + +#include <GL/gl.h> + + + +extern void +ShowDepthBuffer( GLsizei winWidth, GLsizei winHeight, + GLfloat zBlack, GLfloat zWhite ); + + +extern void +ShowAlphaBuffer( GLsizei winWidth, GLsizei winHeight ); + + +extern void +ShowStencilBuffer( GLsizei winWidth, GLsizei winHeight, + GLfloat scale, GLfloat bias ); + + + +#endif diff --git a/progs/demos/spriteblast.c b/progs/demos/spriteblast.c index d6e9a4de2fd..f0d3d0dfd41 100644 --- a/progs/demos/spriteblast.c +++ b/progs/demos/spriteblast.c @@ -537,6 +537,9 @@ main(int argc, char **argv) glutAddMenuEntry("Quit", 666); glutAttachMenu(GLUT_RIGHT_BUTTON); + makePointList(); + makeSprite(); + glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glEnable(GL_POINT_SMOOTH); @@ -546,9 +549,6 @@ main(int argc, char **argv) glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad); #endif - makePointList(); - makeSprite(); - glutMainLoop(); return 0; /* ANSI C requires main to return int. */ } diff --git a/progs/demos/stex3d.c b/progs/demos/stex3d.c index e4554d071f3..83ae3684ae2 100644 --- a/progs/demos/stex3d.c +++ b/progs/demos/stex3d.c @@ -342,19 +342,19 @@ parseCmdLine(int argc, char **argv) GLint i; for (i = 1; i < argc; i++) { - if (strstr(argv[i], "-w") == 0) { + if (strcmp(argv[i], "-help") == 0) { + printHelp(); + return GL_FALSE; + } + else if (strstr(argv[i], "-w") != NULL) { tex_width = atoi((argv[i]) + 2); } - else if (strstr(argv[i], "-h") == 0) { + else if (strstr(argv[i], "-h") != NULL) { tex_height = atoi((argv[i]) + 2); } - else if (strstr(argv[i], "-d") == 0) { + else if (strstr(argv[i], "-d") != NULL) { tex_depth = atoi((argv[i]) + 2); } - else if (strcmp(argv[i], "-help") == 0) { - printHelp(); - return GL_FALSE; - } else { printf("%s (Bad option).\n", argv[i]); printHelp(); diff --git a/progs/demos/trackball.c b/progs/demos/trackball.c new file mode 100644 index 00000000000..a6c4c60d06b --- /dev/null +++ b/progs/demos/trackball.c @@ -0,0 +1,338 @@ +#include <stdio.h> +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ +#if defined(_WIN32) +#pragma warning (disable:4244) /* disable bogus conversion warnings */ +#endif +#include <math.h> +#include "trackball.h" + +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (0.8f) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static float tb_project_to_sphere(float, float, float); +static void normalize_quat(float [4]); + +static void +vzero(float v[3]) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +static void +vset(float v[3], float x, float y, float z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +static void +vsub(const float src1[3], const float src2[3], float dst[3]) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +static void +vcopy(const float v1[3], float v2[3]) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +static void +vcross(const float v1[3], const float v2[3], float cross[3]) +{ + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +static float +vlength(const float v[3]) +{ + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +static void +vscale(float v[3], float div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +static void +vnormal(float v[3]) +{ + vscale(v,1.0/vlength(v)); +} + +static float +vdot(const float v1[3], const float v2[3]) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +static void +vadd(const float src1[3], const float src2[3], float dst[3]) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y) +{ + float a[3]; /* Axis of rotation */ + float phi; /* how much to rotate about axis */ + float p1[3], p2[3], d[3]; + float t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + t = vlength(d) / (2.0*TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = 2.0 * asin(t); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void +axis_to_quat(const float a[3], float phi, float q[4]) +{ + vcopy(a,q); + vnormal(q); + vscale(q, sin(phi/2.0)); + q[3] = cos(phi/2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static float +tb_project_to_sphere(float r, float x, float y) +{ + float d, t, z; + + d = sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440) { /* Inside sphere */ + z = sqrt(r*r - d*d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880; + z = t*t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(const float q1[4], const float q2[4], float dest[4]) +{ + static int count=0; + float t1[4], t2[4], t3[4]; + float tf[4]; + +#if 0 +printf("q1 = %f %f %f %f\n", q1[0], q1[1], q1[2], q1[3]); +printf("q2 = %f %f %f %f\n", q2[0], q2[1], q2[2], q2[3]); +#endif + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + +#if 0 +printf("tf = %f %f %f %f\n", tf[0], tf[1], tf[2], tf[3]); +#endif + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void +normalize_quat(float q[4]) +{ + int i; + float mag; + + mag = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) + q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void +build_rotmatrix(float m[4][4], const float q[4]) +{ + m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0; + + m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); + m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0; + + m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0; + + m[3][0] = 0.0; + m[3][1] = 0.0; + m[3][2] = 0.0; + m[3][3] = 1.0; +} + diff --git a/progs/demos/trackball.h b/progs/demos/trackball.h new file mode 100644 index 00000000000..9b278640e10 --- /dev/null +++ b/progs/demos/trackball.h @@ -0,0 +1,84 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +#ifndef TRACKBALL_H +#define TRACKBALL_H + + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void +add_quats(const float q1[4], const float q2[4], float dest[4]); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void +build_rotmatrix(float m[4][4], const float q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void +axis_to_quat(const float a[3], float phi, float q[4]); + + +#endif /* TRACKBALL_H */ diff --git a/progs/demos/vao_demo.c b/progs/demos/vao_demo.c new file mode 100644 index 00000000000..ce416712fe2 --- /dev/null +++ b/progs/demos/vao_demo.c @@ -0,0 +1,330 @@ +/* + * (C) Copyright IBM Corporation 2006 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#ifdef __darwin__ +#include <GLUT/glut.h> + +typedef void (* PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (* PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); +typedef void (* PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); +typedef GLboolean (* PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); + +#else +#include <GL/glut.h> +#endif + +static PFNGLBINDVERTEXARRAYAPPLEPROC bind_vertex_array = NULL; +static PFNGLGENVERTEXARRAYSAPPLEPROC gen_vertex_arrays = NULL; +static PFNGLDELETEVERTEXARRAYSAPPLEPROC delete_vertex_arrays = NULL; +static PFNGLISVERTEXARRAYAPPLEPROC is_vertex_array = NULL; + +static int Width = 400; +static int Height = 200; +static int Win = 0; +static const GLfloat Near = 5.0, Far = 25.0; +static GLfloat angle = 0.0; + +static GLuint cube_array_obj = 0; +static GLuint oct_array_obj = 0; + +static const GLfloat cube_vert[] = { + -0.5, -0.5, -0.5, 1.0, + 0.5, -0.5, -0.5, 1.0, + 0.5, 0.5, -0.5, 1.0, + -0.5, 0.5, -0.5, 1.0, + + -0.5, -0.5, 0.5, 1.0, + 0.5, -0.5, 0.5, 1.0, + 0.5, 0.5, 0.5, 1.0, + -0.5, 0.5, 0.5, 1.0, + + -0.5, 0.5, -0.5, 1.0, + 0.5, 0.5, -0.5, 1.0, + 0.5, 0.5, 0.5, 1.0, + -0.5, 0.5, 0.5, 1.0, + + -0.5, -0.5, -0.5, 1.0, + 0.5, -0.5, -0.5, 1.0, + 0.5, -0.5, 0.5, 1.0, + -0.5, -0.5, 0.5, 1.0, + + 0.5, -0.5, -0.5, 1.0, + 0.5, -0.5, 0.5, 1.0, + 0.5, 0.5, 0.5, 1.0, + 0.5, 0.5, -0.5, 1.0, + + -0.5, -0.5, -0.5, 1.0, + -0.5, -0.5, 0.5, 1.0, + -0.5, 0.5, 0.5, 1.0, + -0.5, 0.5, -0.5, 1.0, + +}; + +static const GLfloat cube_color[] = { + 1.0, 0.0, 0.0, 1.0, + 1.0, 0.0, 0.0, 1.0, + 1.0, 0.0, 0.0, 1.0, + 1.0, 0.0, 0.0, 1.0, + + 0.0, 1.0, 0.0, 1.0, + 0.0, 1.0, 0.0, 1.0, + 0.0, 1.0, 0.0, 1.0, + 0.0, 1.0, 0.0, 1.0, + + 0.0, 0.0, 1.0, 1.0, + 0.0, 0.0, 1.0, 1.0, + 0.0, 0.0, 1.0, 1.0, + 0.0, 0.0, 1.0, 1.0, + + 1.0, 0.0, 1.0, 1.0, + 1.0, 0.0, 1.0, 1.0, + 1.0, 0.0, 1.0, 1.0, + 1.0, 0.0, 1.0, 1.0, + + 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + + 0.5, 0.5, 0.5, 1.0, + 0.5, 0.5, 0.5, 1.0, + 0.5, 0.5, 0.5, 1.0, + 0.5, 0.5, 0.5, 1.0, +}; + +static const GLfloat oct_vert[] = { + 0.0, 0.0, 0.7071, 1.0, + 0.5, 0.5, 0.0, 1.0, + -0.5, 0.5, 0.0, 1.0, + + 0.0, 0.0, 0.7071, 1.0, + 0.5, -0.5, 0.0, 1.0, + -0.5, -0.5, 0.0, 1.0, + + 0.0, 0.0, 0.7071, 1.0, + -0.5, -0.5, 0.0, 1.0, + -0.5, 0.5, 0.0, 1.0, + + 0.0, 0.0, 0.7071, 1.0, + 0.5, 0.5, 0.0, 1.0, + 0.5, -0.5, 0.0, 1.0, + + + 0.0, 0.0, -0.7071, 1.0, + 0.5, 0.5, 0.0, 1.0, + -0.5, 0.5, 0.0, 1.0, + + 0.0, 0.0, -0.7071, 1.0, + 0.5, -0.5, 0.0, 1.0, + -0.5, -0.5, 0.0, 1.0, + + 0.0, 0.0, -0.7071, 1.0, + -0.5, -0.5, 0.0, 1.0, + -0.5, 0.5, 0.0, 1.0, + + 0.0, 0.0, -0.7071, 1.0, + 0.5, 0.5, 0.0, 1.0, + 0.5, -0.5, 0.0, 1.0, +}; + +static const GLfloat oct_color[] = { + 1.0, 0.64, 0.0, 1.0, + 1.0, 0.64, 0.0, 1.0, + 1.0, 0.64, 0.0, 1.0, + + 0.8, 0.51, 0.0, 1.0, + 0.8, 0.51, 0.0, 1.0, + 0.8, 0.51, 0.0, 1.0, + + 0.5, 0.32, 0.0, 1.0, + 0.5, 0.32, 0.0, 1.0, + 0.5, 0.32, 0.0, 1.0, + + 0.2, 0.13, 0.0, 1.0, + 0.2, 0.13, 0.0, 1.0, + 0.2, 0.13, 0.0, 1.0, + + 0.2, 0.13, 0.0, 1.0, + 0.2, 0.13, 0.0, 1.0, + 0.2, 0.13, 0.0, 1.0, + + 0.5, 0.32, 0.0, 1.0, + 0.5, 0.32, 0.0, 1.0, + 0.5, 0.32, 0.0, 1.0, + + 0.8, 0.51, 0.0, 1.0, + 0.8, 0.51, 0.0, 1.0, + 0.8, 0.51, 0.0, 1.0, + + 1.0, 0.64, 0.0, 1.0, + 1.0, 0.64, 0.0, 1.0, + 1.0, 0.64, 0.0, 1.0, +}; + +static void Display( void ) +{ + glClearColor(0.1, 0.1, 0.4, 0); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, -15.0 ); + glRotatef( angle, 0.0 * angle , 0.0 * angle, 1.0 ); + + + (*bind_vertex_array)( cube_array_obj ); + glPushMatrix(); + glTranslatef(-1.5, 0, 0); + glRotatef( angle, 0.3 * angle , 0.8 * angle, 1.0 ); + glDrawArrays( GL_QUADS, 0, 4 * 6 ); + glPopMatrix(); + + + (*bind_vertex_array)( oct_array_obj ); + glPushMatrix(); + glTranslatef(1.5, 0, 0); + glRotatef( angle, 0.3 * angle , 0.8 * angle, 1.0 ); + glDrawArrays( GL_TRIANGLES, 0, 3 * 8 ); + glPopMatrix(); + + glutSwapBuffers(); +} + + +static void Idle( void ) +{ + static double t0 = -1.; + double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; + if (t0 < 0.0) + t0 = t; + dt = t - t0; + t0 = t; + + angle += 70.0 * dt; /* 70 degrees per second */ + angle = fmod(angle, 360.0); /* prevents eventual overflow */ + + glutPostRedisplay(); +} + + +static void Visible( int vis ) +{ + if ( vis == GLUT_VISIBLE ) { + glutIdleFunc( Idle ); + } + else { + glutIdleFunc( NULL ); + } +} +static void Reshape( int width, int height ) +{ + GLfloat ar = (float) width / (float) height; + Width = width; + Height = height; + glViewport( 0, 0, width, height ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glFrustum( -ar, ar, -1.0, 1.0, Near, Far ); +} + + +static void Key( unsigned char key, int x, int y ) +{ + (void) x; + (void) y; + switch (key) { + case 27: + glutDestroyWindow(Win); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void Init( void ) +{ + const char * const ver_string = (const char * const) + glGetString( GL_VERSION ); + + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + printf("GL_VERSION = %s\n", ver_string); + + if ( !glutExtensionSupported("GL_APPLE_vertex_array_object") ) { + printf("Sorry, this program requires GL_APPLE_vertex_array_object\n"); + exit(1); + } + + bind_vertex_array = (PFNGLBINDVERTEXARRAYAPPLEPROC) glutGetProcAddress( "glBindVertexArrayAPPLE" ); + gen_vertex_arrays = (PFNGLGENVERTEXARRAYSAPPLEPROC) glutGetProcAddress( "glGenVertexArraysAPPLE" ); + delete_vertex_arrays = (PFNGLDELETEVERTEXARRAYSAPPLEPROC) glutGetProcAddress( "glDeleteVertexArraysAPPLE" ); + is_vertex_array = (PFNGLISVERTEXARRAYAPPLEPROC) glutGetProcAddress( "glIsVertexArrayAPPLE" ); + + assert(bind_vertex_array); + assert(gen_vertex_arrays); + assert(delete_vertex_arrays); + assert(is_vertex_array); + + glEnable( GL_DEPTH_TEST ); + + (*gen_vertex_arrays)( 1, & cube_array_obj ); + (*bind_vertex_array)( cube_array_obj ); + glVertexPointer( 4, GL_FLOAT, sizeof(GLfloat) * 4, cube_vert); + glColorPointer( 4, GL_FLOAT, sizeof(GLfloat) * 4, cube_color); + glEnableClientState( GL_VERTEX_ARRAY ); + glEnableClientState( GL_COLOR_ARRAY ); + + (*gen_vertex_arrays)( 1, & oct_array_obj ); + (*bind_vertex_array)( oct_array_obj ); + glVertexPointer( 4, GL_FLOAT, sizeof(GLfloat) * 4, oct_vert); + glColorPointer( 4, GL_FLOAT, sizeof(GLfloat) * 4, oct_color); + glEnableClientState( GL_VERTEX_ARRAY ); + glEnableClientState( GL_COLOR_ARRAY ); + + (*bind_vertex_array)( 0 ); + glVertexPointer( 4, GL_FLOAT, sizeof(GLfloat) * 4, (void *) 0xDEADBEEF ); + glColorPointer( 4, GL_FLOAT, sizeof(GLfloat) * 4, (void *) 0xBADDC0DE ); +} + + +int main( int argc, char *argv[] ) +{ + glutInit( &argc, argv ); + glutInitWindowPosition( 0, 0 ); + glutInitWindowSize( Width, Height ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); + Win = glutCreateWindow( "GL_APPLE_vertex_array_object demo" ); + glutReshapeFunc( Reshape ); + glutKeyboardFunc( Key ); + glutDisplayFunc( Display ); + glutVisibilityFunc( Visible ); + Init(); + glutMainLoop(); + return 0; +} diff --git a/progs/ggi/gears.c b/progs/ggi/gears.c index 56711f5d544..ac2e9f2a6ea 100644 --- a/progs/ggi/gears.c +++ b/progs/ggi/gears.c @@ -1,4 +1,4 @@ -/* $Id: gears.c,v 1.3 1999-08-22 08:56:50 jtaylor Exp $ */ +/* $Id: gears.c,v 1.3 1999/08/22 08:56:50 jtaylor Exp $ */ /* * 3-D gear wheels. This program is in the public domain. diff --git a/progs/osdemos/Makefile b/progs/osdemos/Makefile index 7d1bc08a4e0..f8cba9ee99a 100644 --- a/progs/osdemos/Makefile +++ b/progs/osdemos/Makefile @@ -5,13 +5,13 @@ include $(TOP)/configs/current INCDIR = $(TOP)/include -OSMESA_LIBS = -L$(LIB_DIR) -lglut -lOSMesa -lGLU -lGL $(APP_LIB_DEPS) +OSMESA_LIBS = -L$(TOP)/$(LIB_DIR) -lOSMesa $(APP_LIB_DEPS) -OSMESA16_LIBS = -L$(LIB_DIR) -lglut -lOSMesa16 -lGLU -lGL $(APP_LIB_DEPS) +OSMESA16_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa16 -lGLU -lGL $(APP_LIB_DEPS) -OSMESA32_LIBS = -L$(LIB_DIR) -lglut -lOSMesa32 -lGLU -lGL $(APP_LIB_DEPS) +OSMESA32_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa32 -lGLU -lGL $(APP_LIB_DEPS) -LIB_DEP = $(LIB_DIR)/$(GL_LIB_NAME) $(LIB_DIR)/$(GLU_LIB_NAME) $(LIB_DIR)/$(GLUT_LIB_NAME) +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME) PROGS = \ osdemo \ @@ -76,3 +76,7 @@ clean: -rm -f $(PROGS) -rm -f *.o *~ -rm -f readtex.[ch] showbuffer.[ch] + -rm -f *.ppm + -rm -f osdemo16 osdemo32 + + diff --git a/progs/osdemos/osdemo.c b/progs/osdemos/osdemo.c index 95e2ff97875..f7ce121f702 100644 --- a/progs/osdemos/osdemo.c +++ b/progs/osdemos/osdemo.c @@ -1,4 +1,3 @@ - /* * Demo of off-screen Mesa rendering * @@ -14,31 +13,88 @@ * PPM output provided by Joerg Schmalzl. * ASCII PPM output added by Brian Paul. * - * Usage: osdemo [-perf] [filename] - * - * -perf: Redraws the image 1000 times, displaying the FPS every 5 secs. - * filename: file to store the TGA or PPM output + * Usage: osdemo [filename] */ +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "GL/osmesa.h" -#include "GL/glut.h" +#include "GL/glu.h" #define SAVE_TARGA - #define WIDTH 400 #define HEIGHT 400 -static GLint T0 = 0; -static GLint Frames = 0; -static int perf = 0; -static void render_image( void ) +static void +Sphere(float radius, int slices, int stacks) +{ + GLUquadric *q = gluNewQuadric(); + gluQuadricNormals(q, GLU_SMOOTH); + gluSphere(q, radius, slices, stacks); + gluDeleteQuadric(q); +} + + +static void +Cone(float base, float height, int slices, int stacks) +{ + GLUquadric *q = gluNewQuadric(); + gluQuadricDrawStyle(q, GLU_FILL); + gluQuadricNormals(q, GLU_SMOOTH); + gluCylinder(q, base, 0.0, height, slices, stacks); + gluDeleteQuadric(q); +} + + +static void +Torus(float innerRadius, float outerRadius, int sides, int rings) +{ + /* from GLUT... */ + int i, j; + GLfloat theta, phi, theta1; + GLfloat cosTheta, sinTheta; + GLfloat cosTheta1, sinTheta1; + const GLfloat ringDelta = 2.0 * M_PI / rings; + const GLfloat sideDelta = 2.0 * M_PI / sides; + + theta = 0.0; + cosTheta = 1.0; + sinTheta = 0.0; + for (i = rings - 1; i >= 0; i--) { + theta1 = theta + ringDelta; + cosTheta1 = cos(theta1); + sinTheta1 = sin(theta1); + glBegin(GL_QUAD_STRIP); + phi = 0.0; + for (j = sides; j >= 0; j--) { + GLfloat cosPhi, sinPhi, dist; + + phi += sideDelta; + cosPhi = cos(phi); + sinPhi = sin(phi); + dist = outerRadius + innerRadius * cosPhi; + + glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); + glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, innerRadius * sinPhi); + glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); + glVertex3f(cosTheta * dist, -sinTheta * dist, innerRadius * sinPhi); + } + glEnd(); + theta = theta1; + cosTheta = cosTheta1; + sinTheta = sinTheta1; + } +} + + +static void +render_image(void) { GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; @@ -72,20 +128,20 @@ static void render_image( void ) glTranslatef(-0.75, 0.5, 0.0); glRotatef(90.0, 1.0, 0.0, 0.0); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat ); - glutSolidTorus(0.275, 0.85, 20, 20); + Torus(0.275, 0.85, 20, 20); glPopMatrix(); glPushMatrix(); glTranslatef(-0.75, -0.5, 0.0); glRotatef(270.0, 1.0, 0.0, 0.0); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat ); - glutSolidCone(1.0, 2.0, 16, 1); + Cone(1.0, 2.0, 16, 1); glPopMatrix(); glPushMatrix(); glTranslatef(0.75, 0.0, -1.0); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat ); - glutSolidSphere(1.0, 20, 20); + Sphere(1.0, 20, 20); glPopMatrix(); glPopMatrix(); @@ -94,18 +150,6 @@ static void render_image( void ) * Make sure buffered commands are finished!!! */ glFinish(); - - Frames++; - if (perf) { - GLint t = glutGet(GLUT_ELAPSED_TIME); - 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); - T0 = t; - Frames = 0; - } - } } @@ -201,7 +245,8 @@ write_ppm(const char *filename, const GLubyte *buffer, int width, int height) -int main( int argc, char *argv[] ) +int +main(int argc, char *argv[]) { void *buffer; int i; @@ -219,9 +264,9 @@ int main( int argc, char *argv[] ) return 0; } - for ( i=1; i<argc; i++ ) { - if (argv[i][0] != '-') filename = argv[i]; - if (strcmp(argv[i], "-perf")==0) perf = 1; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') + filename = argv[i]; } /* Allocate the image buffer */ @@ -247,9 +292,6 @@ int main( int argc, char *argv[] ) } render_image(); - if (perf) - for(i=0; i< 1000; i++) - render_image(); if (filename != NULL) { #ifdef SAVE_TARGA diff --git a/progs/osdemos/ostest1.c b/progs/osdemos/ostest1.c index 61f0f3da29c..001e3686162 100644 --- a/progs/osdemos/ostest1.c +++ b/progs/osdemos/ostest1.c @@ -9,11 +9,12 @@ */ #include <assert.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "GL/osmesa.h" -#include "GL/glut.h" +#include "GL/glu.h" #define WIDTH 600 @@ -23,6 +24,120 @@ static GLboolean WriteFiles = GL_FALSE; static GLboolean Gradient = GL_FALSE; +static void +Sphere(float radius, int slices, int stacks) +{ + GLUquadric *q = gluNewQuadric(); + gluQuadricNormals(q, GLU_SMOOTH); + gluSphere(q, radius, slices, stacks); + gluDeleteQuadric(q); +} + + +static void +Cone(float base, float height, int slices, int stacks) +{ + GLUquadric *q = gluNewQuadric(); + gluQuadricDrawStyle(q, GLU_FILL); + gluQuadricNormals(q, GLU_SMOOTH); + gluCylinder(q, base, 0.0, height, slices, stacks); + gluDeleteQuadric(q); +} + + +static void +Torus(float innerRadius, float outerRadius, int sides, int rings) +{ + /* from GLUT... */ + int i, j; + GLfloat theta, phi, theta1; + GLfloat cosTheta, sinTheta; + GLfloat cosTheta1, sinTheta1; + const GLfloat ringDelta = 2.0 * M_PI / rings; + const GLfloat sideDelta = 2.0 * M_PI / sides; + + theta = 0.0; + cosTheta = 1.0; + sinTheta = 0.0; + for (i = rings - 1; i >= 0; i--) { + theta1 = theta + ringDelta; + cosTheta1 = cos(theta1); + sinTheta1 = sin(theta1); + glBegin(GL_QUAD_STRIP); + phi = 0.0; + for (j = sides; j >= 0; j--) { + GLfloat cosPhi, sinPhi, dist; + + phi += sideDelta; + cosPhi = cos(phi); + sinPhi = sin(phi); + dist = outerRadius + innerRadius * cosPhi; + + glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); + glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, innerRadius * sinPhi); + glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); + glVertex3f(cosTheta * dist, -sinTheta * dist, innerRadius * sinPhi); + } + glEnd(); + theta = theta1; + cosTheta = cosTheta1; + sinTheta = sinTheta1; + } +} + + +static void Cube(float size) +{ + size = 0.5 * size; + + glBegin(GL_QUADS); + /* +X face */ + glNormal3f(1, 0, 0); + glVertex3f(size, -size, size); + glVertex3f(size, -size, -size); + glVertex3f(size, size, -size); + glVertex3f(size, size, size); + + /* -X face */ + glNormal3f(-1, 0, 0); + glVertex3f(-size, size, size); + glVertex3f(-size, size, -size); + glVertex3f(-size, -size, -size); + glVertex3f(-size, -size, size); + + /* +Y face */ + glNormal3f(0, 1, 0); + glVertex3f(-size, size, size); + glVertex3f( size, size, size); + glVertex3f( size, size, -size); + glVertex3f(-size, size, -size); + + /* -Y face */ + glNormal3f(0, -1, 0); + glVertex3f(-size, -size, -size); + glVertex3f( size, -size, -size); + glVertex3f( size, -size, size); + glVertex3f(-size, -size, size); + + /* +Z face */ + glNormal3f(0, 0, 1); + glVertex3f(-size, -size, size); + glVertex3f( size, -size, size); + glVertex3f( size, size, size); + glVertex3f(-size, size, size); + + /* -Z face */ + glNormal3f(0, 0, -1); + glVertex3f(-size, size, -size); + glVertex3f( size, size, -size); + glVertex3f( size, -size, -size); + glVertex3f(-size, -size, -size); + + glEnd(); +} + + + /** * Draw red/green gradient across bottom of image. * Read pixels to check deltas. @@ -66,7 +181,9 @@ render_image(void) static const GLfloat red_mat[4] = { 1.0, 0.2, 0.2, 1.0 }; static const GLfloat green_mat[4] = { 0.2, 1.0, 0.2, 1.0 }; static const GLfloat blue_mat[4] = { 0.2, 0.2, 1.0, 1.0 }; +#if 0 static const GLfloat yellow_mat[4] = { 0.8, 0.8, 0.0, 1.0 }; +#endif static const GLfloat purple_mat[4] = { 0.8, 0.4, 0.8, 0.6 }; glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); @@ -106,36 +223,41 @@ render_image(void) glTranslatef(-1.5, 0.5, 0.0); glRotatef(90.0, 1.0, 0.0, 0.0); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat ); - glutSolidTorus(0.275, 0.85, 20, 20); + Torus(0.275, 0.85, 20, 20); glPopMatrix(); glPushMatrix(); glTranslatef(-1.5, -0.5, 0.0); glRotatef(270.0, 1.0, 0.0, 0.0); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat ); - glutSolidCone(1.0, 2.0, 16, 1); + Cone(1.0, 2.0, 16, 1); glPopMatrix(); glPushMatrix(); - glTranslatef(0.75, 0.0, -1.0); + glTranslatef(0.95, 0.0, -0.8); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat ); - glutSolidSphere(1.0, 20, 20); + glLineWidth(2.0); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + Sphere(1.2, 20, 20); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPopMatrix(); +#if 0 glPushMatrix(); glTranslatef(0.75, 0.0, 1.3); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, yellow_mat ); glutWireTeapot(1.0); glPopMatrix(); +#endif glPushMatrix(); - glTranslatef(-0.5, 0.0, 2.5); + glTranslatef(-0.25, 0.0, 2.5); glRotatef(40, 0, 1, 0); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, purple_mat ); - glutSolidCube(1.0); + Cube(1.0); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glPopMatrix(); @@ -270,6 +392,8 @@ test(GLenum type, GLint bits, const char *filename) /* Bind the buffer to the context and make it current */ if (!OSMesaMakeCurrent( ctx, buffer, type, WIDTH, HEIGHT )) { printf("OSMesaMakeCurrent (%d bits/channel) failed!\n", bits); + free(buffer); + OSMesaDestroyContext(ctx); return 0; } @@ -320,6 +444,8 @@ test(GLenum type, GLint bits, const char *filename) OSMesaDestroyContext(ctx); + free(buffer); + return 1; } diff --git a/progs/osdemos/readtex.c b/progs/osdemos/readtex.c new file mode 100644 index 00000000000..37d5fcd0d3a --- /dev/null +++ b/progs/osdemos/readtex.c @@ -0,0 +1,454 @@ +/* readtex.c */ + +/* + * Read an SGI .rgb image file and generate a mipmap texture set. + * Much of this code was borrowed from SGI's tk OpenGL toolkit. + */ + + + +#include <GL/gl.h> +#include <GL/glu.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "readtex.h" + + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + + +/* +** RGB Image Structure +*/ + +typedef struct _TK_RGBImageRec { + GLint sizeX, sizeY; + GLint components; + unsigned char *data; +} TK_RGBImageRec; + + + +/******************************************************************************/ + +typedef struct _rawImageRec { + unsigned short imagic; + unsigned short type; + unsigned short dim; + unsigned short sizeX, sizeY, sizeZ; + unsigned long min, max; + unsigned long wasteBytes; + char name[80]; + unsigned long colorMap; + FILE *file; + unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA; + unsigned long rleEnd; + GLuint *rowStart; + GLint *rowSize; +} rawImageRec; + +/******************************************************************************/ + +static void ConvertShort(unsigned short *array, long length) +{ + unsigned long b1, b2; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + *array++ = (unsigned short) ((b1 << 8) | (b2)); + } +} + +static void ConvertLong(GLuint *array, long length) +{ + unsigned long b1, b2, b3, b4; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + b3 = *ptr++; + b4 = *ptr++; + *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); + } +} + +static rawImageRec *RawImageOpen(const char *fileName) +{ + union { + int testWord; + char testByte[4]; + } endianTest; + rawImageRec *raw; + GLenum swapFlag; + int x; + + endianTest.testWord = 1; + if (endianTest.testByte[0] == 1) { + swapFlag = GL_TRUE; + } else { + swapFlag = GL_FALSE; + } + + raw = (rawImageRec *)calloc(1, sizeof(rawImageRec)); + if (raw == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + if ((raw->file = fopen(fileName, "rb")) == NULL) { + perror(fileName); + return NULL; + } + + fread(raw, 1, 12, raw->file); + + if (swapFlag) { + ConvertShort(&raw->imagic, 6); + } + + raw->tmp = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpR = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpG = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpB = (unsigned char *)malloc(raw->sizeX*256); + if (raw->sizeZ==4) { + raw->tmpA = (unsigned char *)malloc(raw->sizeX*256); + } + if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL || + raw->tmpB == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + + if ((raw->type & 0xFF00) == 0x0100) { + x = raw->sizeY * raw->sizeZ * sizeof(GLuint); + raw->rowStart = (GLuint *)malloc(x); + raw->rowSize = (GLint *)malloc(x); + if (raw->rowStart == NULL || raw->rowSize == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + raw->rleEnd = 512 + (2 * x); + fseek(raw->file, 512, SEEK_SET); + fread(raw->rowStart, 1, x, raw->file); + fread(raw->rowSize, 1, x, raw->file); + if (swapFlag) { + ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint))); + ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint))); + } + } + return raw; +} + +static void RawImageClose(rawImageRec *raw) +{ + fclose(raw->file); + free(raw->tmp); + free(raw->tmpR); + free(raw->tmpG); + free(raw->tmpB); + if (raw->rowStart) + free(raw->rowStart); + if (raw->rowSize) + free(raw->rowSize); + if (raw->sizeZ>3) { + free(raw->tmpA); + } + free(raw); +} + +static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) +{ + unsigned char *iPtr, *oPtr, pixel; + int count, done = 0; + + if ((raw->type & 0xFF00) == 0x0100) { + fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET); + fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY], + raw->file); + + iPtr = raw->tmp; + oPtr = buf; + while (!done) { + pixel = *iPtr++; + count = (int)(pixel & 0x7F); + if (!count) { + done = 1; + return; + } + if (pixel & 0x80) { + while (count--) { + *oPtr++ = *iPtr++; + } + } else { + pixel = *iPtr++; + while (count--) { + *oPtr++ = pixel; + } + } + } + } else { + fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY), + SEEK_SET); + fread(buf, 1, raw->sizeX, raw->file); + } +} + + +static void RawImageGetData(rawImageRec *raw, TK_RGBImageRec *final) +{ + unsigned char *ptr; + int i, j; + + final->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4); + if (final->data == NULL) { + fprintf(stderr, "Out of memory!\n"); + } + + ptr = final->data; + for (i = 0; i < (int)(raw->sizeY); i++) { + RawImageGetRow(raw, raw->tmpR, i, 0); + RawImageGetRow(raw, raw->tmpG, i, 1); + RawImageGetRow(raw, raw->tmpB, i, 2); + if (raw->sizeZ>3) { + RawImageGetRow(raw, raw->tmpA, i, 3); + } + for (j = 0; j < (int)(raw->sizeX); j++) { + *ptr++ = *(raw->tmpR + j); + *ptr++ = *(raw->tmpG + j); + *ptr++ = *(raw->tmpB + j); + if (raw->sizeZ>3) { + *ptr++ = *(raw->tmpA + j); + } + } + } +} + + +static TK_RGBImageRec *tkRGBImageLoad(const char *fileName) +{ + rawImageRec *raw; + TK_RGBImageRec *final; + + raw = RawImageOpen(fileName); + if (!raw) { + fprintf(stderr, "File not found\n"); + return NULL; + } + final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec)); + if (final == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + final->sizeX = raw->sizeX; + final->sizeY = raw->sizeY; + final->components = raw->sizeZ; + RawImageGetData(raw, final); + RawImageClose(raw); + return final; +} + + +static void FreeImage( TK_RGBImageRec *image ) +{ + free(image->data); + free(image); +} + + +/* + * Load an SGI .rgb file and generate a set of 2-D mipmaps from it. + * Input: imageFile - name of .rgb to read + * intFormat - internal texture format to use, or number of components + * Return: GL_TRUE if success, GL_FALSE if error. + */ +GLboolean LoadRGBMipmaps( const char *imageFile, GLint intFormat ) +{ + GLint w, h; + return LoadRGBMipmaps2( imageFile, GL_TEXTURE_2D, intFormat, &w, &h ); +} + + + +GLboolean LoadRGBMipmaps2( const char *imageFile, GLenum target, + GLint intFormat, GLint *width, GLint *height ) +{ + GLint error; + GLenum format; + TK_RGBImageRec *image; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return GL_FALSE; + } + + if (image->components==3) { + format = GL_RGB; + } + else if (image->components==4) { + format = GL_RGBA; + } + else { + /* not implemented */ + fprintf(stderr, + "Error in LoadRGBMipmaps %d-component images not implemented\n", + image->components ); + return GL_FALSE; + } + + error = gluBuild2DMipmaps( target, + intFormat, + image->sizeX, image->sizeY, + format, + GL_UNSIGNED_BYTE, + image->data ); + + *width = image->sizeX; + *height = image->sizeY; + + FreeImage(image); + + return error ? GL_FALSE : GL_TRUE; +} + + + +/* + * Load an SGI .rgb file and return a pointer to the image data. + * Input: imageFile - name of .rgb to read + * Output: width - width of image + * height - height of image + * format - format of image (GL_RGB or GL_RGBA) + * Return: pointer to image data or NULL if error + */ +GLubyte *LoadRGBImage( const char *imageFile, GLint *width, GLint *height, + GLenum *format ) +{ + TK_RGBImageRec *image; + GLint bytes; + GLubyte *buffer; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return NULL; + } + + if (image->components==3) { + *format = GL_RGB; + } + else if (image->components==4) { + *format = GL_RGBA; + } + else { + /* not implemented */ + fprintf(stderr, + "Error in LoadRGBImage %d-component images not implemented\n", + image->components ); + return NULL; + } + + *width = image->sizeX; + *height = image->sizeY; + + bytes = image->sizeX * image->sizeY * image->components; + buffer = (GLubyte *) malloc(bytes); + if (!buffer) + return NULL; + + memcpy( (void *) buffer, (void *) image->data, bytes ); + + FreeImage(image); + + return buffer; +} + +#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) + + +static void ConvertRGBtoYUV(GLint w, GLint h, GLint texel_bytes, + const GLubyte *src, + GLushort *dest) +{ + GLint i, j; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + const GLfloat r = (src[0]) / 255.0; + const GLfloat g = (src[1]) / 255.0; + const GLfloat b = (src[2]) / 255.0; + GLfloat y, cr, cb; + GLint iy, icr, icb; + + y = r * 65.481 + g * 128.553 + b * 24.966 + 16; + cb = r * -37.797 + g * -74.203 + b * 112.0 + 128; + cr = r * 112.0 + g * -93.786 + b * -18.214 + 128; + /*printf("%f %f %f -> %f %f %f\n", r, g, b, y, cb, cr);*/ + iy = (GLint) CLAMP(y, 0, 254); + icb = (GLint) CLAMP(cb, 0, 254); + icr = (GLint) CLAMP(cr, 0, 254); + + if (j & 1) { + /* odd */ + *dest = (iy << 8) | icr; + } + else { + /* even */ + *dest = (iy << 8) | icb; + } + dest++; + src += texel_bytes; + } + } +} + + +/* + * Load an SGI .rgb file and return a pointer to the image data, converted + * to 422 yuv. + * + * Input: imageFile - name of .rgb to read + * Output: width - width of image + * height - height of image + * Return: pointer to image data or NULL if error + */ +GLushort *LoadYUVImage( const char *imageFile, GLint *width, GLint *height ) +{ + TK_RGBImageRec *image; + GLushort *buffer; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return NULL; + } + + if (image->components != 3 && image->components !=4 ) { + /* not implemented */ + fprintf(stderr, + "Error in LoadYUVImage %d-component images not implemented\n", + image->components ); + return NULL; + } + + *width = image->sizeX; + *height = image->sizeY; + + buffer = (GLushort *) malloc( image->sizeX * image->sizeY * 2 ); + + if (buffer) + ConvertRGBtoYUV( image->sizeX, + image->sizeY, + image->components, + image->data, + buffer ); + + + FreeImage(image); + return buffer; +} + diff --git a/progs/redbook/Makefile b/progs/redbook/Makefile index 4cfbb9aeacd..febc74441b9 100644 --- a/progs/redbook/Makefile +++ b/progs/redbook/Makefile @@ -5,7 +5,7 @@ include $(TOP)/configs/current INCDIR = $(TOP)/include -LIB_DEP = $(LIB_DIR)/$(GL_LIB_NAME) $(LIB_DIR)/$(GLU_LIB_NAME) $(LIB_DIR)/$(GLUT_LIB_NAME) +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME) PROGS = aaindex aapoly aargb accanti accpersp alpha alpha3D anti \ bezcurve bezmesh checker clip colormat cube depthcue dof \ diff --git a/progs/samples/Makefile b/progs/samples/Makefile index f14b7dfc009..063008dccff 100644 --- a/progs/samples/Makefile +++ b/progs/samples/Makefile @@ -5,7 +5,7 @@ include $(TOP)/configs/current INCDIR = $(TOP)/include -LIB_DEP = $(LIB_DIR)/$(GL_LIB_NAME) $(LIB_DIR)/$(GLU_LIB_NAME) $(LIB_DIR)/$(GLUT_LIB_NAME) +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME) PROGS = accum bitmap1 bitmap2 blendeq blendxor copy cursor depth eval fog \ font line logo nurb olympic overlay point prim quad select \ diff --git a/progs/samples/readtex.c b/progs/samples/readtex.c new file mode 100644 index 00000000000..37d5fcd0d3a --- /dev/null +++ b/progs/samples/readtex.c @@ -0,0 +1,454 @@ +/* readtex.c */ + +/* + * Read an SGI .rgb image file and generate a mipmap texture set. + * Much of this code was borrowed from SGI's tk OpenGL toolkit. + */ + + + +#include <GL/gl.h> +#include <GL/glu.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "readtex.h" + + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + + +/* +** RGB Image Structure +*/ + +typedef struct _TK_RGBImageRec { + GLint sizeX, sizeY; + GLint components; + unsigned char *data; +} TK_RGBImageRec; + + + +/******************************************************************************/ + +typedef struct _rawImageRec { + unsigned short imagic; + unsigned short type; + unsigned short dim; + unsigned short sizeX, sizeY, sizeZ; + unsigned long min, max; + unsigned long wasteBytes; + char name[80]; + unsigned long colorMap; + FILE *file; + unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA; + unsigned long rleEnd; + GLuint *rowStart; + GLint *rowSize; +} rawImageRec; + +/******************************************************************************/ + +static void ConvertShort(unsigned short *array, long length) +{ + unsigned long b1, b2; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + *array++ = (unsigned short) ((b1 << 8) | (b2)); + } +} + +static void ConvertLong(GLuint *array, long length) +{ + unsigned long b1, b2, b3, b4; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + b3 = *ptr++; + b4 = *ptr++; + *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); + } +} + +static rawImageRec *RawImageOpen(const char *fileName) +{ + union { + int testWord; + char testByte[4]; + } endianTest; + rawImageRec *raw; + GLenum swapFlag; + int x; + + endianTest.testWord = 1; + if (endianTest.testByte[0] == 1) { + swapFlag = GL_TRUE; + } else { + swapFlag = GL_FALSE; + } + + raw = (rawImageRec *)calloc(1, sizeof(rawImageRec)); + if (raw == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + if ((raw->file = fopen(fileName, "rb")) == NULL) { + perror(fileName); + return NULL; + } + + fread(raw, 1, 12, raw->file); + + if (swapFlag) { + ConvertShort(&raw->imagic, 6); + } + + raw->tmp = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpR = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpG = (unsigned char *)malloc(raw->sizeX*256); + raw->tmpB = (unsigned char *)malloc(raw->sizeX*256); + if (raw->sizeZ==4) { + raw->tmpA = (unsigned char *)malloc(raw->sizeX*256); + } + if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL || + raw->tmpB == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + + if ((raw->type & 0xFF00) == 0x0100) { + x = raw->sizeY * raw->sizeZ * sizeof(GLuint); + raw->rowStart = (GLuint *)malloc(x); + raw->rowSize = (GLint *)malloc(x); + if (raw->rowStart == NULL || raw->rowSize == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + raw->rleEnd = 512 + (2 * x); + fseek(raw->file, 512, SEEK_SET); + fread(raw->rowStart, 1, x, raw->file); + fread(raw->rowSize, 1, x, raw->file); + if (swapFlag) { + ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint))); + ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint))); + } + } + return raw; +} + +static void RawImageClose(rawImageRec *raw) +{ + fclose(raw->file); + free(raw->tmp); + free(raw->tmpR); + free(raw->tmpG); + free(raw->tmpB); + if (raw->rowStart) + free(raw->rowStart); + if (raw->rowSize) + free(raw->rowSize); + if (raw->sizeZ>3) { + free(raw->tmpA); + } + free(raw); +} + +static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) +{ + unsigned char *iPtr, *oPtr, pixel; + int count, done = 0; + + if ((raw->type & 0xFF00) == 0x0100) { + fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET); + fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY], + raw->file); + + iPtr = raw->tmp; + oPtr = buf; + while (!done) { + pixel = *iPtr++; + count = (int)(pixel & 0x7F); + if (!count) { + done = 1; + return; + } + if (pixel & 0x80) { + while (count--) { + *oPtr++ = *iPtr++; + } + } else { + pixel = *iPtr++; + while (count--) { + *oPtr++ = pixel; + } + } + } + } else { + fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY), + SEEK_SET); + fread(buf, 1, raw->sizeX, raw->file); + } +} + + +static void RawImageGetData(rawImageRec *raw, TK_RGBImageRec *final) +{ + unsigned char *ptr; + int i, j; + + final->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4); + if (final->data == NULL) { + fprintf(stderr, "Out of memory!\n"); + } + + ptr = final->data; + for (i = 0; i < (int)(raw->sizeY); i++) { + RawImageGetRow(raw, raw->tmpR, i, 0); + RawImageGetRow(raw, raw->tmpG, i, 1); + RawImageGetRow(raw, raw->tmpB, i, 2); + if (raw->sizeZ>3) { + RawImageGetRow(raw, raw->tmpA, i, 3); + } + for (j = 0; j < (int)(raw->sizeX); j++) { + *ptr++ = *(raw->tmpR + j); + *ptr++ = *(raw->tmpG + j); + *ptr++ = *(raw->tmpB + j); + if (raw->sizeZ>3) { + *ptr++ = *(raw->tmpA + j); + } + } + } +} + + +static TK_RGBImageRec *tkRGBImageLoad(const char *fileName) +{ + rawImageRec *raw; + TK_RGBImageRec *final; + + raw = RawImageOpen(fileName); + if (!raw) { + fprintf(stderr, "File not found\n"); + return NULL; + } + final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec)); + if (final == NULL) { + fprintf(stderr, "Out of memory!\n"); + return NULL; + } + final->sizeX = raw->sizeX; + final->sizeY = raw->sizeY; + final->components = raw->sizeZ; + RawImageGetData(raw, final); + RawImageClose(raw); + return final; +} + + +static void FreeImage( TK_RGBImageRec *image ) +{ + free(image->data); + free(image); +} + + +/* + * Load an SGI .rgb file and generate a set of 2-D mipmaps from it. + * Input: imageFile - name of .rgb to read + * intFormat - internal texture format to use, or number of components + * Return: GL_TRUE if success, GL_FALSE if error. + */ +GLboolean LoadRGBMipmaps( const char *imageFile, GLint intFormat ) +{ + GLint w, h; + return LoadRGBMipmaps2( imageFile, GL_TEXTURE_2D, intFormat, &w, &h ); +} + + + +GLboolean LoadRGBMipmaps2( const char *imageFile, GLenum target, + GLint intFormat, GLint *width, GLint *height ) +{ + GLint error; + GLenum format; + TK_RGBImageRec *image; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return GL_FALSE; + } + + if (image->components==3) { + format = GL_RGB; + } + else if (image->components==4) { + format = GL_RGBA; + } + else { + /* not implemented */ + fprintf(stderr, + "Error in LoadRGBMipmaps %d-component images not implemented\n", + image->components ); + return GL_FALSE; + } + + error = gluBuild2DMipmaps( target, + intFormat, + image->sizeX, image->sizeY, + format, + GL_UNSIGNED_BYTE, + image->data ); + + *width = image->sizeX; + *height = image->sizeY; + + FreeImage(image); + + return error ? GL_FALSE : GL_TRUE; +} + + + +/* + * Load an SGI .rgb file and return a pointer to the image data. + * Input: imageFile - name of .rgb to read + * Output: width - width of image + * height - height of image + * format - format of image (GL_RGB or GL_RGBA) + * Return: pointer to image data or NULL if error + */ +GLubyte *LoadRGBImage( const char *imageFile, GLint *width, GLint *height, + GLenum *format ) +{ + TK_RGBImageRec *image; + GLint bytes; + GLubyte *buffer; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return NULL; + } + + if (image->components==3) { + *format = GL_RGB; + } + else if (image->components==4) { + *format = GL_RGBA; + } + else { + /* not implemented */ + fprintf(stderr, + "Error in LoadRGBImage %d-component images not implemented\n", + image->components ); + return NULL; + } + + *width = image->sizeX; + *height = image->sizeY; + + bytes = image->sizeX * image->sizeY * image->components; + buffer = (GLubyte *) malloc(bytes); + if (!buffer) + return NULL; + + memcpy( (void *) buffer, (void *) image->data, bytes ); + + FreeImage(image); + + return buffer; +} + +#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) + + +static void ConvertRGBtoYUV(GLint w, GLint h, GLint texel_bytes, + const GLubyte *src, + GLushort *dest) +{ + GLint i, j; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + const GLfloat r = (src[0]) / 255.0; + const GLfloat g = (src[1]) / 255.0; + const GLfloat b = (src[2]) / 255.0; + GLfloat y, cr, cb; + GLint iy, icr, icb; + + y = r * 65.481 + g * 128.553 + b * 24.966 + 16; + cb = r * -37.797 + g * -74.203 + b * 112.0 + 128; + cr = r * 112.0 + g * -93.786 + b * -18.214 + 128; + /*printf("%f %f %f -> %f %f %f\n", r, g, b, y, cb, cr);*/ + iy = (GLint) CLAMP(y, 0, 254); + icb = (GLint) CLAMP(cb, 0, 254); + icr = (GLint) CLAMP(cr, 0, 254); + + if (j & 1) { + /* odd */ + *dest = (iy << 8) | icr; + } + else { + /* even */ + *dest = (iy << 8) | icb; + } + dest++; + src += texel_bytes; + } + } +} + + +/* + * Load an SGI .rgb file and return a pointer to the image data, converted + * to 422 yuv. + * + * Input: imageFile - name of .rgb to read + * Output: width - width of image + * height - height of image + * Return: pointer to image data or NULL if error + */ +GLushort *LoadYUVImage( const char *imageFile, GLint *width, GLint *height ) +{ + TK_RGBImageRec *image; + GLushort *buffer; + + image = tkRGBImageLoad( imageFile ); + if (!image) { + return NULL; + } + + if (image->components != 3 && image->components !=4 ) { + /* not implemented */ + fprintf(stderr, + "Error in LoadYUVImage %d-component images not implemented\n", + image->components ); + return NULL; + } + + *width = image->sizeX; + *height = image->sizeY; + + buffer = (GLushort *) malloc( image->sizeX * image->sizeY * 2 ); + + if (buffer) + ConvertRGBtoYUV( image->sizeX, + image->sizeY, + image->components, + image->data, + buffer ); + + + FreeImage(image); + return buffer; +} + diff --git a/progs/windml/ugldrawpix.c b/progs/windml/ugldrawpix.c index f511a92ff56..b33be2c6aee 100644 --- a/progs/windml/ugldrawpix.c +++ b/progs/windml/ugldrawpix.c @@ -8,7 +8,7 @@ /* * $Log: ugldrawpix.c,v $ - * Revision 1.2 2001-09-10 19:21:13 brianp + * Revision 1.2 2001/09/10 19:21:13 brianp * WindML updates (Stephane Raimbault) * * Revision 1.1 2001/08/20 16:07:11 brianp diff --git a/progs/windml/ugltexcyl.c b/progs/windml/ugltexcyl.c index cd453a3407f..d2fe687b926 100644 --- a/progs/windml/ugltexcyl.c +++ b/progs/windml/ugltexcyl.c @@ -8,7 +8,7 @@ /* * $Log: ugltexcyl.c,v $ - * Revision 1.2 2001-09-10 19:21:13 brianp + * Revision 1.2 2001/09/10 19:21:13 brianp * WindML updates (Stephane Raimbault) * * Revision 1.1 2001/08/20 16:07:11 brianp diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile index 37b9504e55d..4ca8b107a24 100644 --- a/progs/xdemos/Makefile +++ b/progs/xdemos/Makefile @@ -6,7 +6,7 @@ include $(TOP)/configs/current INCDIR = $(TOP)/include -LIB_DEP = $(LIB_DIR)/$(GL_LIB_NAME) $(LIB_DIR)/$(GLU_LIB_NAME) +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) PROGS = glthreads \ glxdemo \ diff --git a/progs/xdemos/glxgears2.c b/progs/xdemos/glxgears2.c new file mode 100644 index 00000000000..5de5601240e --- /dev/null +++ b/progs/xdemos/glxgears2.c @@ -0,0 +1,522 @@ +/* + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) + * Port by Brian Paul 23 March 2001 + * + * Command line options: + * -info print GL implementation information + * + */ + + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <GL/gl.h> +#include <GL/glx.h> + + +#define BENCHMARK + +#ifdef BENCHMARK + +/* XXX this probably isn't very portable */ + +#include <sys/time.h> +#include <unistd.h> + +/* return current time (in seconds) */ +static int +current_time(void) +{ + struct timeval tv; +#ifdef __VMS + (void) gettimeofday(&tv, NULL ); +#else + struct timezone tz; + (void) gettimeofday(&tv, &tz); +#endif + return (int) tv.tv_sec; +} + +#else /*BENCHMARK*/ + +/* dummy */ +static int +current_time(void) +{ + return 0; +} + +#endif /*BENCHMARK*/ + + + +#ifndef M_PI +#define M_PI 3.14159265 +#endif + + +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; +static GLint gear1, gear2, gear3; +static GLfloat angle = 0.0; +static GLint WinWidth = 300, WinHeight = 300; + +/* + * + * Draw a gear wheel. You'll probably want to call this function when + * building a display list since we do a lot of trig here. + * + * Input: inner_radius - radius of hole at center + * outer_radius - radius at center of teeth + * width - width of gear + * teeth - number of teeth + * tooth_depth - depth of tooth + */ +static void +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, + GLint teeth, GLfloat tooth_depth) +{ + GLint i; + GLfloat r0, r1, r2; + GLfloat angle, da; + GLfloat u, v, len; + + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0; + r2 = outer_radius + tooth_depth / 2.0; + + da = 2.0 * M_PI / teeth / 4.0; + + glShadeModel(GL_FLAT); + + glNormal3f(0.0, 0.0, 1.0); + + /* draw front face */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + if (i < teeth) { + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + width * 0.5); + } + } + glEnd(); + + /* draw front sides of teeth */ + glBegin(GL_QUADS); + da = 2.0 * M_PI / teeth / 4.0; + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + width * 0.5); + } + glEnd(); + + glNormal3f(0.0, 0.0, -1.0); + + /* draw back face */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + if (i < teeth) { + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + } + } + glEnd(); + + /* draw back sides of teeth */ + glBegin(GL_QUADS); + da = 2.0 * M_PI / teeth / 4.0; + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + -width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + -width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + } + glEnd(); + + /* draw outward faces of teeth */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + u = r2 * cos(angle + da) - r1 * cos(angle); + v = r2 * sin(angle + da) - r1 * sin(angle); + len = sqrt(u * u + v * v); + u /= len; + v /= len; + glNormal3f(v, -u, 0.0); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + -width * 0.5); + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); + glNormal3f(v, -u, 0.0); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + -width * 0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + } + + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); + + glEnd(); + + glShadeModel(GL_SMOOTH); + + /* draw inside radius cylinder */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glNormal3f(-cos(angle), -sin(angle), 0.0); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + } + glEnd(); +} + + +static void +draw(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(view_rotx, 1.0, 0.0, 0.0); + glRotatef(view_roty, 0.0, 1.0, 0.0); + glRotatef(view_rotz, 0.0, 0.0, 1.0); + + glPushMatrix(); + glTranslatef(-3.0, -2.0, 0.0); + glRotatef(angle, 0.0, 0.0, 1.0); + glCallList(gear1); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(3.1, -2.0, 0.0); + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); + glCallList(gear2); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(-3.1, 4.2, 0.0); + glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); + glCallList(gear3); + glPopMatrix(); + + glPopMatrix(); +} + + +/* new window size or exposure */ +static void +reshape(int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); + WinWidth = width; + WinHeight = height; +} + + +static void +init(void) +{ + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; + static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; + static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; + + glClearColor(1, 0, 0, 0); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + /* make the gears */ + gear1 = glGenLists(1); + glNewList(gear1, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + gear(1.0, 4.0, 1.0, 20, 0.7); + glEndList(); + + gear2 = glGenLists(1); + glNewList(gear2, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); + gear(0.5, 2.0, 2.0, 10, 0.7); + glEndList(); + + gear3 = glGenLists(1); + glNewList(gear3, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); + gear(1.3, 2.0, 0.5, 10, 0.7); + glEndList(); + + glEnable(GL_NORMALIZE); +} + + +/* + * Create an RGB, double-buffered window. + * Return the window and context handles. + */ +static void +make_window( Display *dpy, const char *name, + int x, int y, int width, int height, + Window *winRet, GLXContext *ctxRet) +{ + int attrib[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None }; + int scrnum; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + Window win; + GLXContext ctx; + XVisualInfo *visinfo; + + scrnum = DefaultScreen( dpy ); + root = RootWindow( dpy, scrnum ); + + visinfo = glXChooseVisual( dpy, scrnum, attrib ); + if (!visinfo) { + printf("Error: couldn't get an RGB, Double-buffered visual\n"); + exit(1); + } + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow( dpy, root, 0, 0, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, mask, &attr ); + + /* set hints and properties */ + { + XSizeHints sizehints; + sizehints.x = x; + sizehints.y = y; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize | USPosition; + XSetNormalHints(dpy, win, &sizehints); + XSetStandardProperties(dpy, win, name, name, + None, (char **)NULL, 0, &sizehints); + } + + ctx = glXCreateContext( dpy, visinfo, NULL, True ); + if (!ctx) { + printf("Error: glXCreateContext failed\n"); + exit(1); + } + + XFree(visinfo); + + *winRet = win; + *ctxRet = ctx; +} + + +static void +event_loop(Display *dpy, Window win) +{ + while (1) { + while (XPending(dpy) > 0) { + XEvent event; + XNextEvent(dpy, &event); + switch (event.type) { + case Expose: + /* we'll redraw below */ + break; + case ConfigureNotify: + reshape(event.xconfigure.width, event.xconfigure.height); + break; + case KeyPress: + { + char buffer[10]; + int r, code; + code = XLookupKeysym(&event.xkey, 0); + if (code == XK_Left) { + view_roty += 5.0; + } + else if (code == XK_Right) { + view_roty -= 5.0; + } + else if (code == XK_Up) { + view_rotx += 5.0; + } + else if (code == XK_Down) { + view_rotx -= 5.0; + } + else { + r = XLookupString(&event.xkey, buffer, sizeof(buffer), + NULL, NULL); + if (buffer[0] == 27) { + /* escape */ + return; + } + } + } + } + } + + /* next frame */ + angle += 2.0; + + draw(); + +#if 0 + glXSwapBuffers(dpy, win); +#else + { + GLfloat c[4]; + + glReadBuffer(GL_BACK); + + glReadPixels(WinWidth-1, 0, 1, 1, GL_RGB, GL_FLOAT, c); + printf("Bottom right pixel color: %g, %g, %g\n", c[0], c[1], c[2]); + + glDrawBuffer(GL_FRONT); + glWindowPos2iARB(0,0); + glCopyPixels(WinWidth/2, 0, WinWidth/2, WinHeight, GL_COLOR); + glDrawBuffer(GL_BACK); + } +#endif + + /* calc framerate */ + { + static int t0 = -1; + static int frames = 0; + int t = current_time(); + + if (t0 < 0) + t0 = t; + + frames++; + + if (t - t0 >= 5.0) { + GLfloat seconds = t - t0; + GLfloat fps = frames / seconds; + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, + fps); + t0 = t; + frames = 0; + } + } + } +} + + +int +main(int argc, char *argv[]) +{ + Display *dpy; + Window win; + GLXContext ctx; + char *dpyName = ":0"; + GLboolean printInfo = GL_FALSE; + int i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-display") == 0) { + dpyName = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "-info") == 0) { + printInfo = GL_TRUE; + } + } + + dpy = XOpenDisplay(dpyName); + if (!dpy) { + printf("Error: couldn't open display %s\n", dpyName); + return -1; + } + + make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win, &ctx); + XMapWindow(dpy, win); + glXMakeCurrent(dpy, win, ctx); + + if (printInfo) { + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); + } + + init(); + + event_loop(dpy, win); + + glXDestroyContext(dpy, ctx); + XDestroyWindow(dpy, win); + XCloseDisplay(dpy); + + return 0; +} |