/* gltools.c * * OpenGL Tools * * notes: some function modify current color, just fyi * */ #include "gltools.h" GLint gltWriteTGA(const char *szFileName) { FILE *pFile; /* file pointer */ TGAHEADER tgaHeader; /* tga file header */ unsigned long lImageSize; /* size in bytes of image */ GLbyte *pBits = NULL; /* pointer to bits */ GLint iViewport[4]; /* viewport in pixels */ GLenum lastBuffer; /* storage for the current read buffer setting */ /* get the viewport dimensions */ glGetIntegerv(GL_VIEWPORT, iViewport); /* how big is the image going to be (targas are tightly packed) */ lImageSize = iViewport[2] * 3 * iViewport[3]; /* allocate block, if this doesn't work, go home */ pBits = (GLbyte *) malloc(lImageSize); if (pBits == NULL) { perror("malloc"); return 0; } /* read bits from color buffer */ glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); /* get the current read buffer setting and save it, switch to * the front buffer and do the read operation, finally, restore * the read buffer state */ glGetIntegerv(GL_READ_BUFFER, (GLint *) &lastBuffer); glReadBuffer(GL_FRONT); glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, pBits); glReadBuffer(lastBuffer); /* initialize the targa header */ tgaHeader.identsize = 0; tgaHeader.colorMapType = 0; tgaHeader.imageType = 2; tgaHeader.colorMapStart = 0; tgaHeader.colorMapLength = 0; tgaHeader.colorMapBits = 0; tgaHeader.xstart = 0; tgaHeader.ystart = 0; tgaHeader.width = iViewport[2]; tgaHeader.height = iViewport[3]; tgaHeader.bits = 24; tgaHeader.descriptor = 0; /* attempt to open the file */ pFile = fopen(szFileName, "wb"); if (pFile == NULL) { perror("fopen"); free(pBits); /* free buffer and return error */ return 0; } /* write the header */ fwrite(&tgaHeader, sizeof(TGAHEADER), 1, pFile); /* write the image data */ fwrite(pBits, lImageSize, 1, pFile); /* free temporary buffer and close the file */ free(pBits); fclose(pFile); return 1; } GLbyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat) { FILE *pFile; /* file pointer */ TGAHEADER tgaHeader; /* TGA file header */ unsigned long lImageSize; /* size in bytes of image */ short sDepth; /* pixel depth; */ GLbyte *pBits = NULL; /* pointer to bits */ /* default/failed values */ *iWidth = 0; *iHeight = 0; *eFormat = GL_BGR_EXT; *iComponents = GL_RGB8; /* attempt to open the file */ pFile = fopen(szFileName, "rb"); if (pFile == NULL) { perror("fopen"); return 0; } /* read in header (binary) */ fread(&tgaHeader, 18 /* sizeof(TGAHEADER) */, 1, pFile); /* get width, height, and depth of texture */ *iWidth = tgaHeader.width; *iHeight = tgaHeader.height; sDepth = tgaHeader.bits / 8; /* put some validity checks here, very simply, i only understand * or care about 8, 24, or 32 bit targas */ if (tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32) return NULL; /* calculate size of image buffer */ lImageSize = tgaHeader.width * tgaHeader.height * sDepth; /* allocate memory and check for success */ pBits = (GLbyte *) malloc(lImageSize * sizeof(GLbyte)); if (pBits == NULL) { perror("malloc"); return NULL; } /* read in the bits */ /* check for read error, this should catch rle or other */ /* weird formats that i don't want to recognize */ if (fread(pBits, lImageSize, 1, pFile) != 1) { perror("fread"); free(pBits); return NULL; } /* set opengl format expected */ switch (sDepth) { case 3: /* most likely case */ *eFormat = GL_BGR_EXT; *iComponents = GL_RGB8; break; case 4: *eFormat = GL_BGRA_EXT; *iComponents = GL_RGBA8; break; case 1: *eFormat = GL_LUMINANCE; *iComponents = GL_LUMINANCE8; break; } /* done with file */ fclose(pFile); /* return pointer to image data */ return pBits; } void gltDrawSnowman(void) { GLUquadricObj *pObj; /* quadric object */ /* main body */ glPushMatrix(); pObj = gluNewQuadric(); gluQuadricNormals(pObj, GLU_SMOOTH); glPushMatrix(); glColor3f(1.0f, 1.0f, 1.0f); gluSphere(pObj, .40f, 26, 13); /* bottom */ /* mid section */ glTranslatef(0.0f, .550f, 0.0f); gluSphere(pObj, .3f, 26, 13); /* head */ glTranslatef(0.0f, 0.45f, 0.0f); gluSphere(pObj, 0.24f, 26, 13); /* eyes */ glColor3f(0.0f, 0.0f, 0.0f); glTranslatef(0.1f, 0.1f, 0.21f); gluSphere(pObj, 0.02f, 26, 13); glTranslatef(-0.2f, 0.0f, 0.0f); gluSphere(pObj, 0.02f, 26, 13); /* nose */ glColor3f(1.0f, 0.3f, 0.3f); glTranslatef(0.1f, -0.12f, 0.0f); gluCylinder(pObj, 0.04f, 0.0f, 0.3f, 26, 13); glPopMatrix(); /* hat */ glPushMatrix(); glColor3f(0.0f, 0.0f, 0.0f); glTranslatef(0.0f, 1.17f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); gluCylinder(pObj, 0.17f, 0.17f, 0.4f, 26, 13); /* hat brim */ glDisable(GL_CULL_FACE); gluDisk(pObj, 0.17f, 0.28f, 26, 13); glEnable(GL_CULL_FACE); glTranslatef(0.0f, 0.0f, 0.40f); gluDisk(pObj, 0.0f, 0.17f, 26, 13); glPopMatrix(); glPopMatrix(); /* delete the quadric */ gluDeleteQuadric(pObj); } /* this screws up the rendering, possibly becasue it's glut? */ void gltDrawFigures(void) { glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glPushMatrix(); /* scale the figures */ glScalef(0.02f, 0.02f, 0.02f); /* draw red cube */ glColor3f(1.0f, 0.0f, 0.0f); glPushMatrix(); glutSolidCube(48.0f); glPopMatrix(); /* draw green sphere */ glColor3f(0.0f, 1.0f, 0.0f); glPushMatrix(); glTranslatef(-60.0f, 0.0f, 0.0f); glutSolidSphere(25.0f, 50, 50); glPopMatrix(); /* draw magenta torus */ glColor3f(1.0f, 0.0f, 1.0f); glPushMatrix(); glTranslatef(0.0f, 0.0f, 60.0f); glutSolidTorus(8.0f, 16.0f, 50, 50); glPopMatrix(); /* draw yellow cone */ glColor3f(1.0f, 1.0f, 0.0f); glPushMatrix(); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); glTranslatef(60.0f, 0.0f, -24.0f); glutSolidCone(25.0f, 50.0f, 50, 50); glPopMatrix(); /* draw cyan teapot */ glColor3f(0.0f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(0.0f, 0.0f, -60.0f); glutSolidTeapot(25.0f); glPopMatrix(); glPopMatrix(); glEnable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); } void gltDrawTriangle(void) { M3DVector3f vNormal; M3DVector3f vCorners[5] = { { 0.0f, 0.6f, 0.0f }, /* top 0 */ { -0.5f, -0.2f, -.50f }, /* back left 1 */ { 0.5f, -0.2f, -0.50f }, /* back right 2 */ { 0.5f, -0.2f, 0.5f }, /* front right 3 */ { -0.5f, -0.2f, 0.5f } /* front left 4 */ }; glBegin(GL_TRIANGLES); /* bottom section - two triangles */ glNormal3f(0.0f, -1.0f, 0.0f); /* map texture to geometry */ glTexCoord2f(1.0f, 1.0f); glVertex3fv(vCorners[2]); glTexCoord2f(0.0f, 1.0f); glVertex3fv(vCorners[4]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vCorners[1]); glTexCoord2f(1.0f, 1.0f); glVertex3fv(vCorners[2]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vCorners[3]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vCorners[4]); /* front face */ m3dFindNormalf(vNormal, vCorners[0], vCorners[4], vCorners[3]); glNormal3fv(vNormal); glTexCoord2f(0.5f, 1.0f); glVertex3fv(vCorners[0]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vCorners[4]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vCorners[3]); /* left face */ m3dFindNormalf(vNormal, vCorners[0], vCorners[1], vCorners[4]); glNormal3fv(vNormal); glTexCoord2f(0.5f, 1.0f); glVertex3fv(vCorners[0]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vCorners[1]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vCorners[4]); /* back face */ m3dFindNormalf(vNormal, vCorners[0], vCorners[2], vCorners[1]); glNormal3fv(vNormal); glTexCoord2f(0.5f, 1.0f); glVertex3fv(vCorners[0]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vCorners[2]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vCorners[1]); /* right face */ m3dFindNormalf(vNormal, vCorners[0], vCorners[3], vCorners[2]); glNormal3fv(vNormal); glTexCoord2f(0.5f, 1.0f); glVertex3fv(vCorners[0]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vCorners[3]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vCorners[2]); glEnd(); } void gltDrawGround(void) { GLfloat fExtent = 20.0f; GLfloat fStep = 0.5f; GLfloat y = -0.4f; GLfloat iLine; glLineWidth(1.0f); glBegin(GL_LINES); for (iLine = -fExtent; iLine <= fExtent; iLine += fStep) { glVertex3f(iLine, y, fExtent); glVertex3f(iLine, y, -fExtent); glVertex3f(fExtent, y, iLine); glVertex3f(-fExtent, y, iLine); } glEnd(); } void gltDrawUnitAxes(void) { GLUquadricObj *pObj; /* temporary, used for quadrics */ /* measurements */ float fAxisRadius = 0.025f; float fAxisHeight = 1.0f; float fArrowRadius = 0.06f; float fArrowHeight = 0.1f; /* setup the quadric object */ pObj = gluNewQuadric(); gluQuadricDrawStyle(pObj, GLU_FILL); gluQuadricNormals(pObj, GLU_SMOOTH); gluQuadricOrientation(pObj, GLU_OUTSIDE); gluQuadricTexture(pObj, GLU_FALSE); /* draw the blue z axis first with arrowed head */ glColor3f(0.0f, 0.0f, 1.0f); gluCylinder(pObj, fAxisRadius, fAxisRadius, fAxisHeight, 10, 1); glPushMatrix(); glTranslatef(0.0f, 0.0f, 1.0f); gluCylinder(pObj, fArrowRadius, 0.0f, fArrowHeight, 10, 1); glRotatef(180.0f, 1.0f, 0.0f, 0.0f); gluDisk(pObj, fAxisRadius, fArrowRadius, 10, 1); glPopMatrix(); /* draw the red x axis 2nd with arrowed head */ glColor3f(1.0f, 0.0f, 0.0f); glPushMatrix(); glRotatef(90.0f, 0.0f, 1.0f, 0.0f); gluCylinder(pObj, fAxisRadius, fAxisRadius, fAxisHeight, 10, 1); glPushMatrix(); glTranslatef(0.0f, 0.0f, 1.0f); gluCylinder(pObj, fArrowRadius, 0.0f, fArrowHeight, 10, 1); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); gluDisk(pObj, fAxisRadius, fArrowRadius, 10, 1); glPopMatrix(); glPopMatrix(); /* draw the green y axis 3rd with arrowed head */ glColor3f(0.0f, 1.0f, 0.0f); glPushMatrix(); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); gluCylinder(pObj, fAxisRadius, fAxisRadius, fAxisHeight, 10, 1); glPushMatrix(); glTranslatef(0.0f, 0.0f, 1.0f); gluCylinder(pObj, fArrowRadius, 0.0f, fArrowHeight, 10, 1); glRotatef(180.0f, 1.0f, 0.0f, 0.0f); gluDisk(pObj, fAxisRadius, fArrowRadius, 10, 1); glPopMatrix(); glPopMatrix(); /* white sphere at origin */ glColor3f(1.0f, 1.0f, 1.0f); gluSphere(pObj, 0.05f, 15, 15); /* delete the quadric */ gluDeleteQuadric(pObj); } /* draw a torus (doughnut), using the current 1d texture for light shading */ /* this funct accepts 4x4 trans matrix to be applied to the vertices */ void gltDrawTorus(GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor) { M3DVector3f vNormal; double majorStep = 2.0f * M3D_PI / numMajor; double minorStep = 2.0f * M3D_PI / numMinor; int i, j; for (i = 0; i < numMajor; ++i) { double a0 = i * majorStep; double a1 = a0 + majorStep; GLfloat x0 = (GLfloat) cos(a0); GLfloat y0 = (GLfloat) sin(a0); GLfloat x1 = (GLfloat) cos(a1); GLfloat y1 = (GLfloat) sin(a1); glBegin(GL_TRIANGLE_STRIP); for (j = 0; j <= numMinor; ++j) { double b = j * minorStep; GLfloat c = (GLfloat) cos(b); GLfloat r = minorRadius * c + majorRadius; GLfloat z = minorRadius * (GLfloat) sin(b); glTexCoord2f((float) (i) / (float) (numMajor), (float) (j) \ / (float) (numMinor)); vNormal[0] = x0 * c; vNormal[1] = y0 * c; vNormal[2] = z / minorRadius; m3dNormalizeVectorf(vNormal); glNormal3fv(vNormal); glVertex3f(x0 * r, y0 * r, z); glTexCoord2f((float) (i + 1) / (float) (numMajor), (float) (j) \ / (float) (numMinor)); vNormal[0] = x1 * c; vNormal[1] = y1 * c; vNormal[2] = z / minorRadius; m3dNormalizeVectorf(vNormal); glNormal3fv(vNormal); glVertex3f(x1 * r, y1 * r, z); } glEnd(); } } void gltDrawJet(void) { M3DVector3f vNormal; /* nose cone, points straight down, set material color */ /* follow few lines use manual approach */ glBegin(GL_TRIANGLES); glNormal3f(0.0f, -1.0f, 0.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(0.0f, 0.0f, 60.0f); glVertex3f(-15.0f, 0.0f, 30.0f); glVertex3f(15.0f, 0.0f, 30.0f); /* verticies for this panel */ { M3DVector3f vPoints[3] = { { 15.0f, 0.0f, 30.0f }, { 0.0f, 15.0f, 30.0f }, { 0.0f, 0.0f, 60.0f } }; /* calculate the normal for the plane */ m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 0.0f, 0.0f, 60.0f }, { 0.0f, 15.0f, 30.0f }, { -15.0f, 0.0f, 30.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } /* body of the plane */ { M3DVector3f vPoints[3] = { { -15.0f, 0.0f, 30.0f }, { 0.0f, 15.0f, 30.0f }, { 0.0f, 0.0f, -56.0f }}; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 0.0f, 0.0f, -56.0f }, { 0.0f, 15.0f, 30.0f }, { 15.0f, 0.0f, 30.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(15.0f, 0.0f, 30.0f); glVertex3f(-15.0f, 0.0f, 30.0f); glVertex3f(0.0f, 0.0f, -56.0f); /* left wing, large triangle for bottom of wing */ { M3DVector3f vPoints[3] = { { 0.0f, 2.0f, 27.0f }, { -60.0f, 2.0f, -8.0f }, { 60.0f, 2.0f, -8.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 60.0f, 2.0f, -8.0f }, { 0.0f, 7.0f, -8.0f }, { 0.0f, 2.0f, 27.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 60.0f, 2.0f, -8.0f }, { -60.0f, 2.0f, -8.0f }, { 0.0f, 7.0f, -8.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 0.0f, 2.0f, 27.0f }, { 0.0f, 7.0f, -8.0f }, { -60.0f, 2.0f, -8.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } /* tail section */ /* bottom of back fin */ glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-30.0f, -0.50f, -57.0f); glVertex3f(30.0f, -0.50f, -57.0f); glVertex3f(0.0f, -0.50f, -40.0f); { M3DVector3f vPoints[3] = { { 0.0f, -0.5f, -40.0f }, { 30.0f, -0.5f, -57.0f }, { 0.0f, 4.0f, -57.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 0.0f, 4.0f, -57.0f }, { -30.0f, -0.5f, -57.0f }, { 0.0f, -0.5f, -40.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 30.0f, -0.5f, -57.0f }, { -30.0f, -0.5f, -57.0f }, { 0.0f, 4.0f, -57.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 0.0f, 0.5f, -40.0f }, { 3.0f, 0.5f, -57.0f }, { 0.0f, 25.0f, -65.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 0.0f, 25.0f, -65.0f }, { -3.0f, 0.5f, -57.0f }, { 0.0f, 0.5f, -40.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } { M3DVector3f vPoints[3] = { { 3.0f, 0.5f, -57.0f }, { -3.0f, 0.5f, -57.0f }, { 0.0f, 25.0f, -65.0f } }; m3dFindNormalf(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); } glEnd(); }