#include #include #include #include "math3d.h" void m3dFindNormal(M3DVector3f result, const M3DVector3f point1, const M3DVector3f point2, const M3DVector3f point3) { M3DVector3f v1, v2; /* calculate two vectors from the three points, assumes * counter clockwise winding */ v1[0] = point1[0] - point2[0]; v1[1] = point1[1] - point2[1]; v1[2] = point1[2] - point2[2]; v2[0] = point2[0] - point3[0]; v2[1] = point2[1] - point3[1]; v2[2] = point2[2] - point3[2]; /* take the cross product of the two vectors to get the normal vector */ m3dCrossProduct(result, v1, v2); } void m3dLoadIdentity44(M3DMatrix44f m) /* 4x4 float */ { /* don't be fooled, this is still column major */ static M3DMatrix44f identity = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; memcpy(m, identity, sizeof(M3DMatrix44f)); } /* creates a 4x4 rotation matrix, takes radians not degrees */ void m3dRotationMatrix44(M3DMatrix44f m, float angle, float x, float y, float z) { float mag, s, c; float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c; s = (float) (sin(angle)); c = (float) (cos(angle)); mag = (float) (sqrt(x*x + y*y + z*z)); /* identity matrix */ if (mag == 0.0f) { m3dLoadIdentity44(m); return; } /* rotation matrix is normalized */ x /= mag; y /= mag; z /= mag; #define M(row,col) m[col*4+row] xx = x * x; yy = y * y; zz = z * z; xy = x * y; yz = y * z; zx = z * x; xs = x * s; ys = y * s; zs = z * s; one_c = 1.0f - c; M(0,0) = (one_c * xx) + c; M(0,1) = (one_c * xy) - zs; M(0,2) = (one_c * zx) + ys; M(0,3) = 0.0f; M(1,0) = (one_c * xy) + zs; M(1,1) = (one_c * yy) + c; M(1,2) = (one_c * yz) - xs; M(1,3) = 0.0f; M(2,0) = (one_c * zx) - ys; M(2,1) = (one_c * yz) + xs; M(2,2) = (one_c * zz) + c; M(2,3) = 0.0f; M(3,0) = 0.0f; M(3,1) = 0.0f; M(3,2) = 0.0f; M(3,3) = 1.0f; #undef M } void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b) { #define A(row,col) a[(col<<2)+row] #define B(row,col) b[(col<<2)+row] #define P(row,col) product[(col<<2)+row] int i; for (i = 0; i < 4; i++) { float ai0 = A(i, 0), ai1 = A(i, 1), ai2 = A(i, 2), ai3 = A(i, 3); P(i, 0) = ai0 * B(0, 0) + ai1 * B(1, 0) + ai2 * B(2, 0) + ai3 * B(3, 0); P(i, 1) = ai0 * B(0, 1) + ai1 * B(1, 1) + ai2 * B(2, 1) + ai3 * B(3, 1); P(i, 2) = ai0 * B(0, 2) + ai1 * B(1, 2) + ai2 * B(2, 2) + ai3 * B(3, 2); P(i, 3) = ai0 * B(0, 3) + ai1 * B(1, 3) + ai2 * B(2, 3) + ai3 * B(3, 3); } #undef A #undef B #undef P } 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; }