/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #include "material.h" /** \brief creates a default Material with no Name normally you call this to create a material List (for an obj-file) and then append with addMaterial() */ Material::Material() { init(); setName (""); } /** \brief creates a Material. \param mtlName Name of the Material to be added to the Material List */ Material::Material (char* mtlName) { init(); setName (mtlName); } /** \brief deletes a Material */ Material::~Material() { if (name) delete []name; if (verbose >= 2) printf ("delete Material %s.\n", name); if (nextMat != NULL) delete nextMat; } /** \brief adds a new Material to the List. this Function will append a new Material to the end of a Material List. \param mtlName The name of the Material to be added. */ Material* Material::addMaterial(char* mtlName) { if (verbose >=2) printf ("adding Material %s.\n", mtlName); Material* newMat = new Material(mtlName); Material* tmpMat = this; while (tmpMat->nextMat != NULL) { tmpMat = tmpMat->nextMat; } tmpMat->nextMat = newMat; return newMat; } /** \brief initializes a new Material with its default Values */ void Material::init(void) { if (verbose >= 3) printf ("initializing new Material.\n"); nextMat = NULL; setIllum(1); setDiffuse(0,0,0); setAmbient(0,0,0); setSpecular(0,0,0); setShininess(2.0); setTransparency(0.0); diffuseTextureSet = false; ambientTextureSet = false; specularTextureSet = false; } /** \brief Search for a Material called mtlName \param mtlName the Name of the Material to search for \returns Material named mtlName if it is found. NULL otherwise. */ Material* Material::search (char* mtlName) { if (verbose >=3) printf ("Searching for material %s", mtlName); Material* searcher = this; while (searcher != NULL) { if (verbose >= 3) printf ("."); if (!strcmp (searcher->getName(), mtlName)) { if (verbose >= 3) printf ("found.\n"); return searcher; } searcher = searcher->nextMat; } if (verbose >=3) printf ("not found\n"); return NULL; } /** \brief sets the material with which the following Faces will be painted */ bool Material::select (void) { // setting diffuse color // glColor3f (diffuse[0], diffuse[1], diffuse[2]); glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse); // setting ambient color glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); // setting up Sprecular glMaterialfv(GL_FRONT, GL_SPECULAR, specular); // setting up Shininess glMaterialf(GL_FRONT, GL_SHININESS, shininess); // setting illumination Model if (illumModel == 1) glShadeModel(GL_FLAT); else if (illumModel >= 2) glShadeModel(GL_SMOOTH); if (diffuseTextureSet) glBindTexture(GL_TEXTURE_2D, diffuseTexture); } /** \brief Set the Name of the Material. (Important for searching) \param mtlName the Name of the Material to be set. */ void Material::setName (char* mtlName) { // if (verbose >= 3) printf("setting Material Name to %s.\n", mtlName); name = new char [strlen(mtlName)]; strcpy(name, mtlName); // printf ("adding new Material: %s, %p\n", this->getName(), this); } /** \returns The Name of The Material */ char* Material::getName (void) { return name; } /** \brief Sets the Material Illumination Model. \brief illu illumination Model in int form */ void Material::setIllum (int illum) { if (verbose >= 3) printf("setting illumModel of Material %s to %i", name, illum); illumModel = illum; // printf ("setting illumModel to: %i\n", illumModel); } /** \brief Sets the Material Illumination Model. \brief illu illumination Model in char* form */void Material::setIllum (char* illum) { setIllum (atoi(illum)); } /** \brief Sets the Material Diffuse Color. \param r Red Color Channel. \param g Green Color Channel. \param b Blue Color Channel. */ void Material::setDiffuse (float r, float g, float b) { if (verbose >= 3) printf ("setting Diffuse Color of Material %s to r=%f g=%f b=%f.\n", name, r, g, b); diffuse[0] = r; diffuse[1] = g; diffuse[2] = b; diffuse[3] = 1.0; } /** \brief Sets the Material Diffuse Color. \param rgb The red, green, blue channel in char format (with spaces between them) */ void Material::setDiffuse (char* rgb) { char r[20],g[20],b[20]; sscanf (rgb, "%s %s %s", r, g, b); setDiffuse (atof(r), atof(g), atof(b)); } /** \brief Sets the Material Ambient Color. \param r Red Color Channel. \param g Green Color Channel. \param b Blue Color Channel. */ void Material::setAmbient (float r, float g, float b) { if (verbose >=3) printf ("setting Ambient Color of Material %s to r=%f g=%f b=%f.\n", name, r, g, b); ambient[0] = r; ambient[1] = g; ambient[2] = b; ambient[3] = 1.0; } /** \brief Sets the Material Ambient Color. \param rgb The red, green, blue channel in char format (with spaces between them) */ void Material::setAmbient (char* rgb) { char r[20],g[20],b[20]; sscanf (rgb, "%s %s %s", r, g, b); setAmbient (atof(r), atof(g), atof(b)); } /** \brief Sets the Material Specular Color. \param r Red Color Channel. \param g Green Color Channel. \param b Blue Color Channel. */ void Material::setSpecular (float r, float g, float b) { if (verbose >= 3) printf ("setting Specular Color of Material %s to r=%f g=%f b=%f.\n", name, r, g, b); specular[0] = r; specular[1] = g; specular[2] = b; specular[3] = 1.0; } /** \brief Sets the Material Specular Color. \param rgb The red, green, blue channel in char format (with spaces between them) */ void Material::setSpecular (char* rgb) { char r[20],g[20],b[20]; sscanf (rgb, "%s %s %s", r, g, b); setSpecular (atof(r), atof(g), atof(b)); } /** \brief Sets the Material Shininess. \param shini stes the Shininess from float. */ void Material::setShininess (float shini) { shininess = shini; } /** \brief Sets the Material Shininess. \param shini stes the Shininess from char*. */ void Material::setShininess (char* shini) { setShininess (atof(shini)); } /** \brief Sets the Material Transparency. \param trans stes the Transparency from int. */ void Material::setTransparency (float trans) { if (verbose >= 3) printf ("setting Transparency of Material %s to %f.\n", name, trans); transparency = trans; } /** \brief Sets the Material Transparency. \param trans stes the Transparency from char*. */ void Material::setTransparency (char* trans) { char tr[20]; sscanf (trans, "%s", tr); setTransparency (atof(tr)); } // MAPPING // /** \brief Sets the Materials Diffuse Map \param dMap the Name of the Image to Use */ void Material::setDiffuseMap(char* dMap) { if (verbose>=2) printf ("setting Diffuse Map %s\n", dMap); // diffuseTextureSet = loadBMP(dMap, &diffuseTexture); diffuseTextureSet = loadJPG(dMap, &diffuseTexture); } /** \brief Sets the Materials Ambient Map \param aMap the Name of the Image to Use */ void Material::setAmbientMap(char* aMap) { SDL_Surface* ambientMap; } /** \brief Sets the Materials Specular Map \param sMap the Name of the Image to Use */ void Material::setSpecularMap(char* sMap) { SDL_Surface* specularMap; } /** \brief Sets the Materials Bumpiness \param bump the Name of the Image to Use */ void Material::setBump(char* bump) { } /** \brief reads in a Windows BMP-file, and imports it to openGL. \param bmpName The name of the Image to load. \param texture A pointer to the Texture which should be read to. */ bool Material::loadBMP (char* bmpName, GLuint* texture) { SDL_Surface* map; if (map = SDL_LoadBMP(bmpName)) { glGenTextures( 1, texture ); /* Typical Texture Generation Using Data From The Bitmap */ glBindTexture( GL_TEXTURE_2D, *texture ); /* Generate The Texture */ glTexImage2D( GL_TEXTURE_2D, 0, 3, map->w, map->h, 0, GL_BGR, GL_UNSIGNED_BYTE, map->pixels ); /* Linear Filtering */ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); if ( map ) SDL_FreeSurface( map ); return true; } else return false; } bool Material::loadJPG (char* jpgName, GLuint* texture) { struct jpeg_decompress_struct cinfo; tImageJPG *pImage = NULL; FILE *pFile; // Open a file pointer to the jpeg file and check if it was found and opened if((pFile = fopen(jpgName, "rb")) == NULL) { // Display an error message saying the file was not found, then return NULL printf("Unable to load JPG File %s.\n", jpgName); return false; } // Create an error handler jpeg_error_mgr jerr; // Have our compression info object point to the error handler address cinfo.err = jpeg_std_error(&jerr); // Initialize the decompression object jpeg_create_decompress(&cinfo); // Specify the data source (Our file pointer) jpeg_stdio_src(&cinfo, pFile); // Allocate the structure that will hold our eventual jpeg data (must free it!) pImage = (tImageJPG*)malloc(sizeof(tImageJPG)); // Decode the jpeg file and fill in the image data structure to pass back decodeJPG(&cinfo, pImage); // This releases all the stored memory for reading and decoding the jpeg jpeg_destroy_decompress(&cinfo); // Close the file pointer that opened the file fclose(pFile); if(pImage == NULL) // If we can't load the file, quit! exit(0); // Generate a texture with the associative texture ID stored in the array glGenTextures(1, texture); // Bind the texture to the texture arrays index and init the texture glBindTexture(GL_TEXTURE_2D, *texture); // Build Mipmaps (builds different versions of the picture for distances - looks better) gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pImage->sizeX, pImage->sizeY, GL_RGB, GL_UNSIGNED_BYTE, pImage->data); // Lastly, we need to tell OpenGL the quality of our texture map. GL_LINEAR_MIPMAP_LINEAR // is the smoothest. GL_LINEAR_MIPMAP_NEAREST is faster than GL_LINEAR_MIPMAP_LINEAR, // but looks blochy and pixilated. Good for slower computers though. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); // Now we need to free the image data that we loaded since OpenGL stored it as a texture if (pImage) // If we loaded the image { if (pImage->data) // If there is texture data { free(pImage->data); // Free the texture data, we don't need it anymore } free(pImage); // Free the image structure } } void Material::decodeJPG(jpeg_decompress_struct* cinfo, tImageJPG *pImageData) { // Read in the header of the jpeg file jpeg_read_header(cinfo, TRUE); // Start to decompress the jpeg file with our compression info jpeg_start_decompress(cinfo); // Get the image dimensions and row span to read in the pixel data pImageData->rowSpan = cinfo->image_width * cinfo->num_components; pImageData->sizeX = cinfo->image_width; pImageData->sizeY = cinfo->image_height; // Allocate memory for the pixel buffer pImageData->data = new unsigned char[pImageData->rowSpan * pImageData->sizeY]; // Here we use the library's state variable cinfo.output_scanline as the // loop counter, so that we don't have to keep track ourselves. // Create an array of row pointers unsigned char** rowPtr = new unsigned char*[pImageData->sizeY]; for (int i = 0; i < pImageData->sizeY; i++) rowPtr[i] = &(pImageData->data[i*pImageData->rowSpan]); // Now comes the juice of our work, here we extract all the pixel data int rowsRead = 0; while (cinfo->output_scanline < cinfo->output_height) { // Read in the current row of pixels and increase the rowsRead count rowsRead += jpeg_read_scanlines(cinfo, &rowPtr[rowsRead], cinfo->output_height - rowsRead); } // Delete the temporary row pointers delete [] rowPtr; // Finish decompressing the data jpeg_finish_decompress(cinfo); }