// texturedPolygons.cpp // // Implementation file for TexturedPolygons Class // Defines all the methods declared, but not defined, in texturedPolygons.h // // Shay Leary, March 2005 //-------------------------------------------------------------------------------------- #include "texturedPolygons.h" #include <iostream> using std::cout; //-------------------------------------------------------------------------------------- // Declares datatype to store a raw image file and calls method to load image //-------------------------------------------------------------------------------------- GLubyte* TexturedPolygons::LoadTexture(const string& filename, int imgWidth, int imgHeight) { // unsigned char* image = NULL; image = LoadRawImageFile(filename, imgWidth, imgHeight); // inform user if file loaded cout << "Loading image file " << filename << "...\n"; return image; } //-------------------------------------------------------------------------------------- // Creates memory space to store raw image file and reads in file from disk. //-------------------------------------------------------------------------------------- GLubyte* TexturedPolygons::LoadRawImageFile(const string& filename, int width, int height) { FILE* file; unsigned char* image; // create memory space w x h x 3 (3 stores RGB values) image = (unsigned char*)malloc(sizeof(unsigned char) * width * height * 3); file = fopen(filename.c_str(), "rb"); // exit program if image not found and inform user if (file == NULL) { cout << "ERROR loading image file: " << filename << "...\n"; exit(0); } auto val = fread(image, width * height * 3, 1, file); if (val == 0) { fclose(file); free(image); throw std::logic_error("Unexpected fread() error"); } fclose(file); return image; } //-------------------------------------------------------------------------------------- // Set number of textures to be used in program //-------------------------------------------------------------------------------------- void TexturedPolygons::SetTextureCount(const int& textureNo) { m_texture = new GLuint[textureNo]; glGenTextures(textureNo, &m_texture[0]); } //-------------------------------------------------------------------------------------- // Creates texture and set required values for texture mapping //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateTexture(int textureNo, unsigned char* image, int imgWidth, int imgHeight) { glBindTexture(GL_TEXTURE_2D, m_texture[textureNo]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); float anisotropicFiltering{1.0f}; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropicFiltering); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropicFiltering); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imgWidth, imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image); free(image); } //-------------------------------------------------------------------------------------- // Calls functions to create display lists, depending on parameters. // I created these functions very early on in the program before I had a full // understanding, therefore I would probably create a better function for the // purpose, but this works well. //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateDisplayList(const int& XYZ, const int& listNo, const GLdouble& xImgSize, const GLdouble& zImgSize, const GLdouble& xStart, const GLdouble& yStart, const GLdouble& zStart, const GLdouble& xTimes, const GLdouble& zTimes) { glNewList(listNo, GL_COMPILE); glBegin(GL_QUADS); switch (XYZ) { case 0: // create list where image is on X and Y axis CreateXtoYTextureList(xImgSize, zImgSize, xStart, yStart, zStart, xTimes, zTimes, false); break; case 1: // create list where image is on X and Z axis CreateXtoZTextureList(xImgSize, zImgSize, xStart, yStart, zStart, xTimes, zTimes); break; case 2: // create list where image is on Y and Z axis CreateYtoZTextureList(xImgSize, zImgSize, xStart, yStart, zStart, xTimes, zTimes, false); break; case 3: // create list where (flipped) image is on X and Z axis CreateYtoZTextureList(xImgSize, zImgSize, xStart, yStart, zStart, xTimes, zTimes, true); break; case 4: // create list where (flipped) image is on X and Y axis CreateXtoYTextureList(xImgSize, zImgSize, xStart, yStart, zStart, xTimes, zTimes, true); break; } glEnd(); glEndList(); } //-------------------------------------------------------------------------------------- // Create display list with image plotted on X to Z axis //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateXtoZTextureList(const GLdouble& xImgSize, const GLdouble& zImgSize, const GLdouble& xStart, const GLdouble& yStart, const GLdouble& zStart, const GLdouble& xTimes, const GLdouble& zTimes) { glTexCoord2f(0.0, 0.0); glVertex3d(xStart, yStart, zStart); glTexCoord2d(0.0, zTimes); glVertex3d(xStart, yStart, zStart + (zImgSize * zTimes)); glTexCoord2d(xTimes, zTimes); glVertex3d(xStart + (xImgSize * xTimes), yStart, zStart + (zImgSize * zTimes)); glTexCoord2d(xTimes, 0.0); glVertex3d(xStart + (xImgSize * xTimes), yStart, zStart); } //-------------------------------------------------------------------------------------- // Create display list with image plotted on X to Y axis //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateXtoYTextureList(const GLdouble& xImgSize, const GLdouble& yImgSize, const GLdouble& xStart, const GLdouble& yStart, const GLdouble& zStart, const GLdouble& xTimes, const GLdouble& yTimes, const bool& flip) { GLdouble flipX = 0.0; GLdouble tempX = xTimes; // if image is required to be flipped (this will be improved) if (flip) { flipX = xTimes; tempX = 0.0; } glTexCoord2d(flipX, 0.0); glVertex3d(xStart, yStart, zStart); glTexCoord2d(flipX, yTimes); glVertex3d(xStart, yStart + (yImgSize * yTimes), zStart); glTexCoord2d(tempX, yTimes); glVertex3d(xStart + (xImgSize * xTimes), yStart + (yImgSize * yTimes), zStart); glTexCoord2d(tempX, 0.0); glVertex3d(xStart + (xImgSize * xTimes), yStart, zStart); } //-------------------------------------------------------------------------------------- // Create display list with image plotted on Y to A axis //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateYtoZTextureList(const GLdouble& yImgSize, const GLdouble& zImgSize, const GLdouble& xStart, const GLdouble& yStart, const GLdouble& zStart, const GLdouble& yTimes, const GLdouble& zTimes, const bool& flip) { GLdouble flipZ = 0.0; GLdouble tempZ = zTimes; // if image is required to be flipped if (flip) { flipZ = zTimes; tempZ = 0.0; } glTexCoord2d(0.0, flipZ); glVertex3d(xStart, yStart, zStart); glTexCoord2d(0.0, tempZ); glVertex3d(xStart, yStart, zStart + (zImgSize * zTimes)); glTexCoord2d(yTimes, tempZ); glVertex3d(xStart, yStart + (yImgSize * yTimes), zStart + (zImgSize * zTimes)); glTexCoord2d(yTimes, flipZ); glVertex3d(xStart, yStart + (yImgSize * yTimes), zStart); } //-------------------------------------------------------------------------------------- // Used to create display lists where the image size is not to scale with the // world co-ordinates. This is mainly used to create lists for the larger // images (i.e. windows and doors), where they are to large to keep to scale. //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateYtoZWindowList(const int& listNo, const GLdouble& xStart, const GLdouble& yStart, const GLdouble& ySize, const GLdouble& zStart, const GLdouble& zSize, const GLdouble& yImgSize, const GLdouble& zImgSize) { glNewList(listNo, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2d(0.0, zImgSize); glVertex3d(xStart, yStart, zStart); glTexCoord2d(0.0, 0.0); glVertex3d(xStart, yStart, zStart + zSize); glTexCoord2d(yImgSize, 0.0); glVertex3d(xStart, yStart + ySize, zStart + zSize); glTexCoord2d(yImgSize, zImgSize); glVertex3d(xStart, yStart + ySize, zStart); glEnd(); glEndList(); } //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateXtoYWindowList(const int& listNo, const GLdouble& zStart, const GLdouble& xStart, const GLdouble& xSize, const GLdouble& yStart, const GLdouble& ySize, const GLdouble& xImgSize, const GLdouble& yImgSize) { glNewList(listNo, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2d(0.0, 0.0); glVertex3d(xStart, yStart, zStart); glTexCoord2d(xImgSize, 0.0); glVertex3d(xStart + xSize, yStart, zStart); glTexCoord2d(xImgSize, yImgSize); glVertex3d(xStart + xSize, yStart + ySize, zStart); glTexCoord2d(0.0, yImgSize); glVertex3d(xStart, yStart + ySize, zStart); glEnd(); glEndList(); } //-------------------------------------------------------------------------------------- // Used to create display lists where the image is on an angle. // The final two parameters are used to rotate the image so that it appears // correctly. This works by passing the number of the smallest co-ordinate. Eg, // smallestX = 1 to 4 for smallest x values (image angles on the XZ or XY axis) // smallestX = 5 to 8 for smallest y values (image angles on the YZ) // smallestZ = 1 to 4 for smallest z values (image angles on the XZ or YZ) // smallestZ = 5 to 8 for smallest y values (image angles on the XY) //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateAngledPolygon(const int& listNo, const GLdouble& imageWidth, const GLdouble& imageHeight, const GLdouble& x1, const GLdouble& x2, const GLdouble& x3, const GLdouble& x4, const GLdouble& y1, const GLdouble& y2, const GLdouble& y3, const GLdouble& y4, const GLdouble& z1, const GLdouble& z2, const GLdouble& z3, const GLdouble& z4, const int& smallestX, const int& smallestZ) { GLdouble xImage1 = x1; GLdouble xImage2 = x2; GLdouble xImage3 = x3; GLdouble xImage4 = x4; GLdouble zImage1 = z1; GLdouble zImage2 = z2; GLdouble zImage3 = z3; GLdouble zImage4 = z4; if (smallestX == 1) { CreateTextureScale(xImage1, xImage2, xImage3, xImage4, imageWidth); } else if (smallestX == 2) { CreateTextureScale(xImage2, xImage1, xImage3, xImage4, imageWidth); } else if (smallestX == 3) { CreateTextureScale(xImage3, xImage1, xImage2, xImage4, imageWidth); } else if (smallestX == 4) { CreateTextureScale(xImage4, xImage1, xImage2, xImage3, imageWidth); } else { xImage1 = y1; xImage2 = y2; xImage3 = y3; xImage4 = y4; if (smallestX == 5) { CreateTextureScale(xImage1, xImage2, xImage3, xImage4, imageWidth); } else if (smallestX == 6) { CreateTextureScale(xImage2, xImage1, xImage3, xImage4, imageWidth); } else if (smallestX == 7) { CreateTextureScale(xImage3, xImage1, xImage2, xImage4, imageWidth); } else if (smallestX == 8) { CreateTextureScale(xImage4, xImage1, xImage2, xImage3, imageWidth); } } if (smallestZ == 1) { CreateTextureScale(zImage1, zImage2, zImage3, zImage4, imageHeight); } else if (smallestZ == 2) { CreateTextureScale(zImage2, zImage1, zImage3, zImage4, imageHeight); } else if (smallestZ == 3) { CreateTextureScale(zImage3, zImage1, zImage2, zImage4, imageHeight); } else if (smallestZ == 4) { CreateTextureScale(zImage4, zImage1, zImage2, zImage3, imageHeight); } else { zImage1 = y1; zImage2 = y2; zImage3 = y3; zImage4 = y4; if (smallestZ == 5) { CreateTextureScale(zImage1, zImage2, zImage3, zImage4, imageHeight); } else if (smallestZ == 6) { CreateTextureScale(zImage2, zImage1, zImage3, zImage4, imageHeight); } else if (smallestZ == 7) { CreateTextureScale(zImage3, zImage1, zImage2, zImage4, imageHeight); } else if (smallestZ == 8) { CreateTextureScale(zImage4, zImage1, zImage2, zImage3, imageHeight); } } // create display list glNewList(listNo, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2d(xImage1, zImage1); glVertex3d(x1, y1, z1); glTexCoord2d(xImage2, zImage2); glVertex3d(x2, y2, z2); glTexCoord2d(xImage3, zImage3); glVertex3d(x3, y3, z3); glTexCoord2d(xImage4, zImage4); glVertex3d(x4, y4, z4); glEnd(); glEndList(); } //-------------------------------------------------------------------------------------- // Called from CreateAngledPolygon determine how images are displayed //-------------------------------------------------------------------------------------- void TexturedPolygons::CreateTextureScale(GLdouble& xzImage1, GLdouble& xzImage2, GLdouble& xzImage3, GLdouble& xzImage4, const GLdouble& imageSize) { xzImage2 = ((xzImage2 - xzImage1) / imageSize); xzImage3 = ((xzImage3 - xzImage1) / imageSize); xzImage4 = ((xzImage4 - xzImage1) / imageSize); xzImage1 = 0.0; } //--------------------------------------------------------------------------------------