Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/importer/material.cc @ 3206

Last change on this file since 3206 was 3206, checked in by bensch, 20 years ago

orxonox/trunk: new PRINTF() implemented in Material and Array

File size: 30.8 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15   TGA-code: borrowed from nehe-Tutorials
16
17*/
18
19#include "material.h"
20
21// headers only for PathList
22#include <unistd.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <stdlib.h>
26#include <fstream>
27
28using namespace std;
29
30/**
31   \brief creates a ned PathList.
32   
33   It is a good idea to use this as an initial List,
34   because if you give on a name the Path will not be checked for its existence.
35*/
36PathList::PathList()
37{
38  this->pathName = NULL;
39  this->next = NULL;
40}
41
42/**
43   \brief Creates a new PathList with a Name.
44   \param pName the Name of The Path.
45
46   This function just adds the Path without checking if it exists.
47*/
48PathList::PathList(char* pName)
49{
50  this->pathName = new char [strlen(pName)+1];
51  strcpy (this->pathName, pName);
52  this->next = NULL;
53}
54
55/**
56   \brief destroys a PathList
57
58   It does this by deleting the Name and then delete its preceding PathList.
59*/
60PathList::~PathList()
61{
62  if (this->pathName)
63    delete []this->pathName;
64  if (this->next)
65    delete this->next;
66}
67
68/**
69   \brief Adds a new Pathlist Element.
70   \param pName
71   
72   Adding a Path automatically checks if the Path exists,
73   and if it does not it will not add it to the List.
74*/
75void PathList::addPath (char* pName)
76{
77  if (pName[0] == '\0')
78    {
79      PRINTF(3)("not Adding empty Path to the List.\n");
80      return;
81    }
82  char* tmpPName = new char[strlen(pName)];
83  strncpy(tmpPName, pName, strlen(pName)-1);
84  tmpPName[strlen(pName)-1] = '\0';
85  printf ("%s\n",tmpPName);
86  if (access (tmpPName, F_OK) == 0)
87    {
88      struct stat status;
89      stat(tmpPName, &status);
90      if (status.st_mode & S_IFDIR)
91        {
92          PRINTF(2)("Adding Path %s to the PathList.\n", pName);
93          PathList* tmpPathList = this;
94          while (tmpPathList->next)
95            tmpPathList = tmpPathList->next;
96          tmpPathList->next = new PathList(pName);
97        }
98      else
99        PRINTF(2)("You tried to add non-folder %s to a PathList.\n", tmpPName);
100    }
101  else
102      PRINTF(2)("You tried to add non-existing folder %s to a PathList.\n", tmpPName);
103  delete []tmpPName;
104}
105
106/**
107   \brief creates a default Material with no Name
108   normally you call this to create a material List (for an obj-file) and then append with addMaterial()
109*/
110Material::Material()
111{
112  this->init();
113 
114  this->setName ("");
115}
116
117/**
118   \brief creates a Material.
119   \param mtlName Name of the Material to be added to the Material List
120*/
121Material::Material (char* mtlName)
122{
123  this->init();
124 
125  this->setName (mtlName);
126}
127
128/**
129    \brief deletes a Material
130*/
131Material::~Material()
132{
133  PRINTF(2)("delete Material %s.\n", this->name);
134  if (this->name)
135    delete []this->name;
136  if (this->diffuseTextureSet)
137    glDeleteTextures (1, &this->diffuseTexture);
138  if (this->nextMat)
139    delete this->nextMat;
140}
141
142/**
143   \brief adds a new Material to the List.
144   this Function will append a new Material to the end of a Material List.
145   \param mtlName The name of the Material to be added.
146*/
147Material* Material::addMaterial(char* mtlName)
148{
149  PRINTF(2)("adding Material %s.\n", mtlName);
150   Material* tmpMat = this;
151  while (tmpMat->nextMat != NULL)
152    {
153      tmpMat = tmpMat->nextMat;
154    }
155  tmpMat->nextMat = new Material(mtlName);
156  return tmpMat->nextMat;
157 
158}
159
160/**
161   \brief initializes a new Material with its default Values
162*/
163void Material::init(void)
164{
165  PRINTF(2)("initializing new Material.\n");
166  this->nextMat = NULL;
167  this->name ="";
168  this->setIllum(1);
169  this->setDiffuse(0,0,0);
170  this->setAmbient(0,0,0);
171  this->setSpecular(.5,.5,.5);
172  this->setShininess(2.0);
173  this->setTransparency(0.0);
174
175  if (!this->pathList)
176    this->pathList = new PathList("");
177
178
179  this->diffuseTextureSet = false;
180  this->ambientTextureSet = false;
181  this->specularTextureSet = false;
182
183 
184}
185
186PathList *Material::pathList = NULL;
187
188/**
189   \brief Search for a Material called mtlName
190   \param mtlName the Name of the Material to search for
191   \returns Material named mtlName if it is found. NULL otherwise.
192*/
193Material* Material::search (char* mtlName)
194{
195  PRINTF(2)("Searching for material %s", mtlName);
196  Material* searcher = this;
197  while (searcher != NULL)
198    {
199      PRINTF(2)(".");
200      if (!strcmp (searcher->getName(), mtlName))
201        {
202          PRINTF(2)("found.\n");
203          return searcher;
204        }
205      searcher = searcher->nextMat;
206    }
207  PRINTF(2)("not found\n");
208  return NULL;
209}
210
211/**
212   \brief sets the material with which the following Faces will be painted
213*/
214bool Material::select (void)
215{
216  // setting diffuse color
217  //  glColor3f (diffuse[0], diffuse[1], diffuse[2]);
218  glMaterialfv(GL_FRONT, GL_DIFFUSE, this->diffuse);
219
220  // setting ambient color
221  glMaterialfv(GL_FRONT, GL_AMBIENT, this->ambient);
222
223  // setting up Sprecular
224  glMaterialfv(GL_FRONT, GL_SPECULAR, this->specular);
225
226  // setting up Shininess
227  glMaterialf(GL_FRONT, GL_SHININESS, this->shininess);
228 
229  // setting illumination Model
230  if (this->illumModel == 1) //! \todo make this work, if no vertex-normals are read.
231    glShadeModel(GL_FLAT);
232  else if (this->illumModel >= 2)
233    glShadeModel(GL_SMOOTH);
234
235  if (this->diffuseTextureSet)
236    glBindTexture(GL_TEXTURE_2D, this->diffuseTexture);
237  else
238    glBindTexture(GL_TEXTURE_2D, 0);
239 
240}
241
242
243/**
244   \brief Set the Name of the Material. (Important for searching)
245   \param mtlName the Name of the Material to be set.
246*/ 
247void Material::setName (char* mtlName)
248{
249  PRINTF(3)("setting Material Name to %s.\n", this->name);
250  this->name = new char [strlen(mtlName)+1];
251  strcpy(this->name, mtlName);
252}
253
254/**
255   \returns The Name of The Material
256*/
257char* Material::getName (void)
258{
259  return this->name;
260}
261
262/**
263   \brief Sets the Material Illumination Model.
264   \brief illu illumination Model in int form
265*/
266void Material::setIllum (int illum)
267{
268  PRINTF(3)("setting illumModel of Material %s to %i\n", this->name, illum);
269  this->illumModel = illum;
270  //  printf ("setting illumModel to: %i\n", illumModel);
271}
272/**
273   \brief Sets the Material Illumination Model.
274   \brief illu illumination Model in char* form
275*/void Material::setIllum (char* illum)
276{
277  this->setIllum (atoi(illum));
278}
279
280/**
281   \brief Sets the Material Diffuse Color.
282   \param r Red Color Channel.
283   \param g Green Color Channel.
284   \param b Blue Color Channel.
285*/
286void Material::setDiffuse (float r, float g, float b)
287{
288  PRINTF(3)("setting Diffuse Color of Material %s to r=%f g=%f b=%f.\n", this->name, r, g, b);
289  this->diffuse[0] = r;
290  this->diffuse[1] = g;
291  this->diffuse[2] = b; 
292  this->diffuse[3] = 1.0;
293
294}
295/**
296   \brief Sets the Material Diffuse Color.
297   \param rgb The red, green, blue channel in char format (with spaces between them)
298*/
299void Material::setDiffuse (char* rgb)
300{
301  float r,g,b;
302  sscanf (rgb, "%f %f %f", &r, &g, &b);
303  this->setDiffuse (r, g, b);
304}
305
306/**
307   \brief Sets the Material Ambient Color.
308   \param r Red Color Channel.
309   \param g Green Color Channel.
310   \param b Blue Color Channel.
311*/
312void Material::setAmbient (float r, float g, float b)
313{
314  PRINTF(3)("setting Ambient Color of Material %s to r=%f g=%f b=%f.\n", this->name, r, g, b);
315  this->ambient[0] = r;
316  this->ambient[1] = g;
317  this->ambient[2] = b;
318  this->ambient[3] = 1.0;
319}
320/**
321   \brief Sets the Material Ambient Color.
322   \param rgb The red, green, blue channel in char format (with spaces between them)
323*/
324void Material::setAmbient (char* rgb)
325{
326  float r,g,b;
327  sscanf (rgb, "%f %f %f", &r, &g, &b);
328  this->setAmbient (r, g, b);
329}
330
331/**
332   \brief Sets the Material Specular Color.
333   \param r Red Color Channel.
334   \param g Green Color Channel.
335   \param b Blue Color Channel.
336*/
337void Material::setSpecular (float r, float g, float b)
338{
339  PRINTF(3)("setting Specular Color of Material %s to r=%f g=%f b=%f.\n", this->name, r, g, b);
340  this->specular[0] = r;
341  this->specular[1] = g;
342  this->specular[2] = b;
343  this->specular[3] = 1.0;
344 }
345/**
346   \brief Sets the Material Specular Color.
347   \param rgb The red, green, blue channel in char format (with spaces between them)
348*/
349void Material::setSpecular (char* rgb)
350{
351  float r,g,b;
352  sscanf (rgb, "%f %f %f", &r, &g, &b);
353  this->setSpecular (r, g, b);
354}
355
356/**
357   \brief Sets the Material Shininess.
358   \param shini stes the Shininess from float.
359*/
360void Material::setShininess (float shini)
361{
362  this->shininess = shini;
363}
364/**
365   \brief Sets the Material Shininess.
366   \param shini stes the Shininess from char*.
367*/
368void Material::setShininess (char* shini)
369{
370  this->setShininess (atof(shini));
371}
372
373/**
374   \brief Sets the Material Transparency.
375   \param trans stes the Transparency from int.
376*/
377void Material::setTransparency (float trans)
378{
379  PRINTF(3)("setting Transparency of Material %s to %f.\n", this->name, trans);
380  this->transparency = trans;
381}
382/**
383   \brief Sets the Material Transparency.
384   \param trans stes the Transparency from char*.
385*/
386void Material::setTransparency (char* trans)
387{
388  this->setTransparency (atof(trans));
389}
390
391/**
392   \brief Adds a Texture Path to the List of already existing Paths
393   \param pathName The Path to add.
394*/
395void Material::addTexturePath(char* pathName)
396{
397  this->pathList->addPath (pathName);
398}
399
400/**
401   \brief Searches for a Texture inside one of the defined Paths
402   \param texName The name of the texture o search for.
403   \returns pathName+texName if texName was found in the pathList. NULL if the Texture is not found.
404*/
405char* Material::searchTextureInPaths(char* texName) const
406{
407  char* tmpName = NULL;
408  PathList* pList = pathList;
409  while (pList)
410    {
411      if (pList->pathName)
412        {
413          tmpName = new char [strlen(pList->pathName)+strlen(texName)+1];
414          strcpy(tmpName, pList->pathName);
415        }
416      else
417        {
418          tmpName = new char [strlen(texName)+1];
419          tmpName[0]='\0';
420        }
421      strcat(tmpName, texName);
422      if (access (tmpName, F_OK) == 0)
423        return tmpName;
424     
425      if (tmpName)
426        delete []tmpName;
427      tmpName = NULL;
428      pList = pList->next;
429    }
430  return NULL;
431}
432
433
434// MAPPING //
435
436/**
437   \brief Sets the Materials Diffuse Map
438   \param dMap the Name of the Image to Use
439*/
440void Material::setDiffuseMap(char* dMap)
441{
442  PRINTF(3)("setting Diffuse Map %s\n", dMap);
443
444  //  diffuseTextureSet = loadBMP(dMap, &diffuseTexture);
445  this->diffuseTextureSet = this->loadImage(dMap, &this->diffuseTexture);
446
447}
448
449/**
450   \brief Sets the Materials Ambient Map
451   \param aMap the Name of the Image to Use
452   \todo implement this
453*/
454void Material::setAmbientMap(char* aMap)
455{
456  SDL_Surface* ambientMap;
457
458}
459
460/**
461   \brief Sets the Materials Specular Map
462   \param sMap the Name of the Image to Use
463   \todo implement this
464*/
465void Material::setSpecularMap(char* sMap)
466{
467  SDL_Surface* specularMap;
468
469}
470
471/**
472   \brief Sets the Materials Bumpiness
473   \param bump the Name of the Image to Use
474   \todo implemet this
475*/
476void Material::setBump(char* bump)
477{
478
479}
480
481/**
482   \brief Loads a Texture to the openGL-environment.
483   \param pImage The Image to load to openGL
484   \param texture The Texture to apply it to.
485*/
486bool Material::loadTexToGL (Image* pImage, GLuint* texture)
487{
488  PRINTF(2)("Loading texture to OpenGL-Environment.\n");
489  glGenTextures(1, texture);
490  glBindTexture(GL_TEXTURE_2D, *texture);
491  /* not Working, and not needed.
492  glTexImage2D( GL_TEXTURE_2D, 0, 3, width,
493                height, 0, GL_BGR,
494                GL_UNSIGNED_BYTE, map->pixels );
495  */ 
496  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pImage->width, pImage->height, GL_RGB, GL_UNSIGNED_BYTE, pImage->data);
497 
498  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
499  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); 
500}
501
502
503#ifdef HAVE_SDL_SDL_IMAGE_H
504bool Material::loadImage(char* imageName, GLuint* texture)
505{
506  char* imgNameWithPath = searchTextureInPaths(imageName);
507  if (imgNameWithPath)
508    {
509      SDL_Surface* map;
510      Image* pImage = new Image;
511      map=IMG_Load(imgNameWithPath);
512      if(!map)
513        {
514          PRINTF(1)("IMG_Load: %s\n", IMG_GetError());
515          return false;
516        }
517      pImage->height = map->h;
518      pImage->width  = map->w;
519      pImage->data   = (GLubyte*)map->pixels;
520      if( !IMG_isPNG(SDL_RWFromFile(imgNameWithPath, "rb")) && !IMG_isJPG(SDL_RWFromFile(imgNameWithPath, "rb")))
521        for (int i=0;i<map->h * map->w *3;i+=3)
522          { 
523            GLuint temp = pImage->data[i];
524            pImage->data[i] = pImage->data[i+2];
525            pImage->data[i+2] = temp;
526          }
527      this->loadTexToGL (pImage, texture);
528    }
529  else
530    {
531      PRINTF(1)("Image not Found: %s\n", imgNameWithPath);
532      return false;
533    }
534}
535
536
537#else /* HAVE_SDL_SDL_IMAGE_H */
538/**
539   \brief Makes the Programm ready to Read-in a texture-File
540   1. Checks what type of Image should be imported
541   2. ToDO: Checks where to find the Image
542*/
543bool Material::loadImage(char* imageName, GLuint* texture)
544{
545  char* imgNameWithPath = searchTextureInPaths(imageName);
546  if (imgNameWithPath)
547    {
548      if (!strncmp(imgNameWithPath+strlen(imgNameWithPath)-4, ".bmp", 4))
549        {
550          PRINTF(3)("Requested bmp-image. Trying to Import.\n");
551          return this->loadBMP(imgNameWithPath, texture);
552        }
553     
554      else if (!strncmp(imgNameWithPath+strlen(imgNameWithPath)-4, ".jpg", 4) || !strncmp(imgNameWithPath+strlen(imgNameWithPath)-5, ".jpg", 5))
555        {
556          PRINTF(3)("Requested jpeg-image. Trying to Import\n");
557          return this->loadJPG(imgNameWithPath, texture);
558        }
559      else if (!strncmp(imgNameWithPath+strlen(imgNameWithPath)-4, ".tga", 4))
560        {
561          PRINTF(3)("Requested tga-image. Trying to Import\n");
562          return this->loadTGA(imgNameWithPath, texture);
563        }
564      else if (!strncmp(imgNameWithPath+strlen(imgNameWithPath)-4, ".png", 4))
565        {
566          PRINTF(3)("Requested png-image. Trying to Import\n");
567          return this->loadPNG(imgNameWithPath, texture);
568        }
569      else
570        {
571          PRINTF(1)("Requested Image was not recognized in its type. (Maybe a type-Cast-error.)\n FileName: %s", imgNameWithPath);
572          return false;
573        }
574    }
575  else
576    {
577      PRINTF(1)("Image not Found: %s\n", imgNameWithPath);
578      return false;
579    }
580}
581
582/**
583   \brief reads in a Windows BMP-file, and imports it to openGL.
584   \param bmpName The name of the Image to load.
585   \param texture A pointer to the Texture which should be read to.
586*/
587bool Material::loadBMP (char* bmpName, GLuint* texture)
588{
589  Image* pImage = new Image;
590  FILE *file;
591  unsigned long size;                 // size of the image in bytes.
592  unsigned long i;                    // standard counter.
593  unsigned short int planes;          // number of planes in image (must be 1)
594  unsigned short int bpp;             // number of bits per pixel (must be 24)
595  GLuint temp;                          // temporary color storage for bgr-rgb conversion.
596
597  // make sure the file is there.
598  if ((file = fopen(bmpName, "rb"))==NULL)
599    {
600      PRINTF(1)("File Not Found : %s\n",bmpName);
601      return false;
602    }
603  // seek through the bmp header, up to the width/height:
604  fseek(file, 18, SEEK_CUR);
605 
606  // read the width
607  if ((i = fread(&pImage->width, 4, 1, file)) != 1) 
608    {
609      PRINTF(1)("Error reading width from %s.\n", bmpName);
610      return false;
611    }
612  // read the height
613  if ((i = fread(&pImage->height, 4, 1, file)) != 1) 
614    {
615      PRINTF(1)("Error reading height from %s.\n", bmpName);
616      return false;
617    }
618 
619  // calculate the size (assuming 24 bits or 3 bytes per pixel).
620  size = pImage->width * pImage->height * 3;
621 
622  // read the planes
623  if ((fread(&planes, 2, 1, file)) != 1) 
624    {
625      PRINTF(1)("Error reading planes from %s.\n", bmpName);
626      return false;
627    }
628  if (planes != 1) 
629    {
630      PRINTF(1)("Planes from %s is not 1: %u\n", bmpName, planes);
631      return false;
632    }
633 
634  // read the bpp
635  if ((i = fread(&bpp, 2, 1, file)) != 1) 
636    {
637      PRINTF(1)("Error reading bpp from %s.\n", bmpName);
638      return false;
639    }
640  if (bpp != 24) 
641    {
642      PRINTF(1)("Bpp from %s is not 24: %u\n", bmpName, bpp);
643      return false;
644    }
645 
646  // seek past the rest of the bitmap header.
647  fseek(file, 24, SEEK_CUR);
648 
649  // read the data.
650  pImage->data = (GLubyte *) malloc(size);
651  if (pImage->data == NULL) 
652    {
653      PRINTF(1)("Error allocating memory for color-corrected image data");
654      return false;     
655    }
656 
657  if ((i = fread(pImage->data, size, 1, file)) != 1) 
658    {
659      PRINTF(1)("Error reading image data from %s.\n", bmpName);
660      return false;
661    }
662  fclose(file);
663
664  // reverse all of the colors. (bgr -> rgb)
665  for (i=0;i<size;i+=3) 
666    { 
667      temp = pImage->data[i];
668      pImage->data[i] = pImage->data[i+2];
669      pImage->data[i+2] = temp;
670    }
671  this->loadTexToGL (pImage, texture);
672 
673
674  if (pImage)
675    {
676      if (pImage->data)
677        {
678          free(pImage->data);
679        }
680     
681      free(pImage);
682    }
683  return true;
684
685}
686
687/**
688   \brief reads in a jpg-file
689   \param jpgName the Name of the Image to load
690   \param texture a reference to the Texture to write the image to
691*/
692bool Material::loadJPG (char* jpgName, GLuint* texture)
693{
694#ifdef HAVE_JPEGLIB_H
695  struct jpeg_decompress_struct cinfo;
696  Image *pImage = NULL;
697  FILE *pFile;
698 
699  // Open a file pointer to the jpeg file and check if it was found and opened
700  if((pFile = fopen(jpgName, "rb")) == NULL) 
701    {
702      // Display an error message saying the file was not found, then return NULL
703      PRINTF(1)("Unable to load JPG File %s.\n", jpgName);
704      return false;
705    }
706 
707  // Create an error handler
708  jpeg_error_mgr jerr;
709 
710  // Have our compression info object point to the error handler address
711  cinfo.err = jpeg_std_error(&jerr);
712 
713  // Initialize the decompression object
714  jpeg_create_decompress(&cinfo);
715 
716  // Specify the data source (Our file pointer)
717  jpeg_stdio_src(&cinfo, pFile);
718 
719  // Allocate the structure that will hold our eventual jpeg data (must free it!)
720  pImage = (Image*)malloc(sizeof(Image));
721 
722  // DECOFING
723  // Read in the header of the jpeg file
724  jpeg_read_header(&cinfo, TRUE);
725 
726  // Start to decompress the jpeg file with our compression info
727  jpeg_start_decompress(&cinfo);
728 
729  // Get the image dimensions and row span to read in the pixel data
730  pImage->rowSpan = cinfo.image_width * cinfo.num_components;
731  pImage->width   = cinfo.image_width;
732  pImage->height   = cinfo.image_height;
733 
734  // Allocate memory for the pixel buffer
735  pImage->data = new unsigned char[pImage->rowSpan * pImage->height];
736 
737  // Here we use the library's state variable cinfo.output_scanline as the
738  // loop counter, so that we don't have to keep track ourselves.
739 
740  // Create an array of row pointers
741  unsigned char** rowPtr = new unsigned char*[pImage->height];
742  for (int i = 0; i < pImage->height; i++)
743    rowPtr[i] = &(pImage->data[i*pImage->rowSpan]);
744 
745  // Now comes the juice of our work, here we extract all the pixel data
746  int rowsRead = 0;
747  while (cinfo.output_scanline < cinfo.output_height) 
748    {
749      // Read in the current row of pixels and increase the rowsRead count
750      rowsRead += jpeg_read_scanlines(&cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead);
751    }
752 
753  // Delete the temporary row pointers
754  delete [] rowPtr;
755 
756  // Finish decompressing the data
757  jpeg_finish_decompress(&cinfo);//  decodeJPG(&cinfo, pImage);
758 
759  // This releases all the stored memory for reading and decoding the jpeg
760  jpeg_destroy_decompress(&cinfo);
761 
762  // Close the file pointer that opened the file
763  fclose(pFile);
764 
765
766  if(pImage == NULL)
767    exit(0);
768 
769  this->loadTexToGL (pImage, texture);
770  if (pImage)
771    {
772      if (pImage->data)
773        {
774          free(pImage->data);
775        }
776     
777      free(pImage);
778    }
779  return true;
780#else /* HAVE_JPEGLIB_H */
781  PRINTF(1)("sorry, but you did not compile with jpeg-support.\nEither install SDL_image or jpeglib, and recompile to see the image\n");
782  return false;
783#endif /* HAVE_JPEGLIB_H */
784
785}
786
787/**
788   \brief reads in a tga-file
789   \param tgaName the Name of the Image to load
790   \param texture a reference to the Texture to write the image to
791*/
792bool Material::loadTGA(const char * tgaName, GLuint* texture)
793{
794  typedef struct
795  {
796    GLubyte Header[12];
797  } TGAHeader;
798  TGAHeader tgaHeader;                 
799 
800  GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
801  GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0}; // Compressed TGA Header
802  FILE * fTGA;
803  fTGA = fopen(tgaName, "rb");
804
805  if(fTGA == NULL)
806    {
807      PRINTF(1)("Error could not open texture file: %s\n", tgaName);
808      return false;
809    }
810 
811  if(fread(&tgaHeader, sizeof(TGAHeader), 1, fTGA) == 0)
812    {
813      PRINTF(1)("Error could not read file header of %s\n", tgaName);
814      if(fTGA != NULL)
815        {
816          fclose(fTGA);
817        }
818      return false;
819    }
820 
821  if(memcmp(uTGAcompare, &tgaHeader, sizeof(TGAHeader)) == 0)
822    {
823      loadUncompressedTGA(tgaName, fTGA, texture);
824      if (fTGA)
825        fclose (fTGA);
826    }
827  else if(memcmp(cTGAcompare, &tgaHeader, sizeof(TGAHeader)) == 0)
828    {
829      loadCompressedTGA(tgaName, fTGA, texture);
830        if (fTGA)
831          fclose (fTGA);
832    }
833  else
834    {
835      PRINTF(1)("Error TGA file be type 2 or type 10\n");
836      if (fTGA)
837        fclose(fTGA);
838      return false;
839    }
840  return true;
841}
842
843/**
844   \brief reads in an uncompressed tga-file
845   \param filename the Name of the Image to load
846   \param fTGA a Pointer to a File, that should be read
847   \param texture a reference to the Texture to write the image to
848*/
849bool Material::loadUncompressedTGA(const char * filename, FILE * fTGA, GLuint* texture)
850{
851  GLubyte header[6];      // First 6 Useful Bytes From The Header
852  GLuint  bytesPerPixel;  // Holds Number Of Bytes Per Pixel Used In The TGA File
853  GLuint  imageSize;      // Used To Store The Image Size When Setting Aside Ram
854  GLuint  temp;           // Temporary Variable
855  GLuint  type;
856  GLuint  Height;         // Height of Image
857  GLuint  Width;          // Width of Image
858  GLuint  Bpp;            // Bits Per Pixel
859
860  Image* pImage = new Image;
861  GLuint cswap;
862  if(fread(header, sizeof(header), 1, fTGA) == 0)
863    {
864      PRINTF(1)("Error could not read info header\n");
865      return false;
866    }
867 
868  Width = pImage->width  = header[1] * 256 + header[0];
869  Height =  pImage->height = header[3] * 256 + header[2];
870  Bpp = pImage->bpp = header[4];
871  // Make sure all information is valid
872  if((pImage->width <= 0) || (pImage->height <= 0) || ((pImage->bpp != 24) && (pImage->bpp !=32)))
873    {
874      PRINTF(1)("Error invalid texture information\n");
875      return false;
876    }
877 
878  if(pImage->bpp == 24) 
879    {
880      pImage->type = GL_RGB;
881    }
882  else
883    {
884      pImage->type = GL_RGBA;
885    }
886 
887  bytesPerPixel = (Bpp / 8);
888  imageSize = (bytesPerPixel * Width * Height);
889  pImage->data = (GLubyte*) malloc(imageSize);
890 
891  if(pImage->data == NULL)
892    {
893      PRINTF(1)("Error could not allocate memory for image\n");
894      return false;
895    }
896 
897  if(fread(pImage->data, 1, imageSize, fTGA) != imageSize)
898    {
899      PRINTF(1)("Error could not read image data\n");
900      if(pImage->data != NULL)
901        {
902          free(pImage->data);
903        }
904      return false;
905    }
906 
907  for(cswap = 0; cswap < (int)imageSize; cswap += bytesPerPixel)
908    {
909      pImage->data[cswap] ^= pImage->data[cswap+2] ^=
910        pImage->data[cswap] ^= pImage->data[cswap+2];
911    }
912 
913  this->loadTexToGL (pImage, texture);
914
915  return true;
916}
917
918/**
919   \brief reads in a compressed tga-file
920   \param filename the Name of the Image to load
921   \param fTGA a Pointer to a File, that should be read
922   \param texture a reference to the Texture to write the image to
923*/
924bool Material::loadCompressedTGA(const char * filename, FILE * fTGA, GLuint* texture)
925{
926  GLubyte header[6];      // First 6 Useful Bytes From The Header
927  GLuint  bytesPerPixel;  // Holds Number Of Bytes Per Pixel Used In The TGA File
928  GLuint  imageSize;      // Used To Store The Image Size When Setting Aside Ram
929  GLuint  temp;           // Temporary Variable
930  GLuint  type;
931  GLuint  Height;         // Height of Image
932  GLuint  Width;          // Width of Image
933  GLuint  Bpp;            // Bits Per Pixel
934
935  Image* pImage = new Image;
936
937 
938  if(fread(header, sizeof(header), 1, fTGA) == 0)
939    {
940      PRINTF(1)("Error could not read info header\n");
941      return false;
942    }
943 
944  Width = pImage->width  = header[1] * 256 + header[0];
945  Height = pImage->height = header[3] * 256 + header[2];
946  Bpp = pImage->bpp     = header[4];
947
948  GLuint pixelcount     = Height * Width;
949  GLuint currentpixel   = 0;
950  GLuint currentbyte    = 0;
951  GLubyte * colorbuffer = (GLubyte *)malloc(bytesPerPixel);
952
953  //Make sure all pImage info is ok
954  if((pImage->width <= 0) || (pImage->height <= 0) || ((pImage->bpp != 24) && (pImage->bpp !=32)))
955    {
956      PRINTF(1)("Error Invalid pImage information\n");
957      return false;
958    }
959 
960  bytesPerPixel = (Bpp / 8);
961  imageSize             = (bytesPerPixel * Width * Height);
962  pImage->data  = (GLubyte*) malloc(imageSize);
963 
964  if(pImage->data == NULL)
965    {
966      PRINTF(1)("Error could not allocate memory for image\n");
967      return false;
968    }
969 
970  do
971    {
972      GLubyte chunkheader = 0;
973     
974      if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0)
975        {
976          PRINTF(1)("Error could not read RLE header\n");
977          if(pImage->data != NULL)
978            {
979              free(pImage->data);
980            }
981          return false;
982        }
983      // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
984      if(chunkheader < 128)
985        {
986          short counter;
987          chunkheader++;
988          // Read RAW color values
989          for(counter = 0; counter < chunkheader; counter++)
990            { 
991              // Try to read 1 pixel
992              if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel)
993                {
994                  PRINTF(1)("Error could not read image data\n");
995                  if(colorbuffer != NULL)
996                    {
997                      free(colorbuffer);
998                    }
999                 
1000                  if(pImage->data != NULL)
1001                    {
1002                      free(pImage->data);
1003                    }
1004                 
1005                  return false; 
1006                }
1007              // write to memory
1008              // Flip R and B vcolor values around in the process
1009              pImage->data[currentbyte    ] = colorbuffer[2];                               
1010              pImage->data[currentbyte + 1] = colorbuffer[1];
1011              pImage->data[currentbyte + 2] = colorbuffer[0];
1012             
1013              if(bytesPerPixel == 4) // if its a 32 bpp image
1014                {
1015                  pImage->data[currentbyte + 3] = colorbuffer[3];// copy the 4th byte
1016                }
1017             
1018              currentbyte += bytesPerPixel;
1019              currentpixel++;
1020
1021              // Make sure we haven't read too many pixels
1022              if(currentpixel > pixelcount)     
1023                {
1024                  PRINTF(1)("Error too many pixels read\n");
1025                  if(colorbuffer != NULL)
1026                    {
1027                      free(colorbuffer);
1028                    }
1029                 
1030                  if(pImage->data != NULL)
1031                    {
1032                      free(pImage->data);
1033                    }
1034                 
1035                  return false;
1036                }
1037            }
1038        }
1039      // chunkheader > 128 RLE data, next color  reapeated chunkheader - 127 times
1040      else
1041        {
1042          short counter;
1043          chunkheader -= 127;   // Subteact 127 to get rid of the ID bit
1044          if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel) // Attempt to read following color values
1045            {
1046              PRINTF(1)("Error could not read from file");
1047              if(colorbuffer != NULL)
1048                {
1049                  free(colorbuffer);
1050                }
1051             
1052              if(pImage->data != NULL)
1053                {
1054                  free(pImage->data);
1055                }
1056             
1057              return false;
1058            }
1059         
1060          for(counter = 0; counter < chunkheader; counter++) //copy the color into the image data as many times as dictated
1061            {                                                   
1062              // switch R and B bytes areound while copying
1063              pImage->data[currentbyte    ] = colorbuffer[2];
1064              pImage->data[currentbyte + 1] = colorbuffer[1];
1065              pImage->data[currentbyte + 2] = colorbuffer[0];
1066             
1067              if(bytesPerPixel == 4)
1068                {
1069                  pImage->data[currentbyte + 3] = colorbuffer[3];
1070                }
1071             
1072              currentbyte += bytesPerPixel;
1073              currentpixel++;
1074             
1075              if(currentpixel > pixelcount)
1076                {
1077                  PRINTF(1)("Error too many pixels read\n");
1078                  if(colorbuffer != NULL)
1079                    {
1080                      free(colorbuffer);
1081                    }
1082                 
1083                  if(pImage->data != NULL)
1084                    {
1085                      free(pImage->data);
1086                    }
1087                 
1088                  return false;
1089                }
1090            }
1091        }
1092    }
1093 
1094  while(currentpixel < pixelcount);     // Loop while there are still pixels left
1095
1096  this->loadTexToGL (pImage, texture);
1097
1098  return true;
1099}
1100
1101
1102/*
1103static int ST_is_power_of_two(unsigned int number)
1104{
1105  return (number & (number - 1)) == 0;
1106}
1107*/
1108
1109/**
1110   \brief reads in a png-file
1111   \param pngName the Name of the Image to load
1112   \param texture a reference to the Texture to write the image to
1113*/
1114bool Material::loadPNG(const char* pngName, GLuint* texture)
1115{
1116#ifdef HAVE_PNG_H
1117  Image* pImage = new Image;
1118
1119  FILE *PNG_file = fopen(pngName, "rb");
1120  if (PNG_file == NULL)
1121    {
1122      return 0;
1123    }
1124 
1125  GLubyte PNG_header[8];
1126 
1127  fread(PNG_header, 1, 8, PNG_file);
1128  if (png_sig_cmp(PNG_header, 0, 8) != 0)
1129    {
1130      PRINTF(2)("Not Recognized as a pngFile\n");
1131      fclose (PNG_file);
1132      return 0;
1133    }
1134 
1135  png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1136  if (PNG_reader == NULL)
1137    {
1138      fclose(PNG_file);
1139      return 0;
1140    }
1141 
1142  png_infop PNG_info = png_create_info_struct(PNG_reader);
1143  if (PNG_info == NULL)
1144    {
1145      png_destroy_read_struct(&PNG_reader, NULL, NULL);
1146      fclose(PNG_file);
1147      return 0;
1148    }
1149 
1150  png_infop PNG_end_info = png_create_info_struct(PNG_reader);
1151  if (PNG_end_info == NULL)
1152    {
1153      png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
1154      fclose(PNG_file);
1155      return 0;
1156    }
1157 
1158  if (setjmp(png_jmpbuf(PNG_reader)))
1159    {
1160      png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
1161      fclose(PNG_file);
1162      return (0);
1163    }
1164 
1165  png_init_io(PNG_reader, PNG_file);
1166  png_set_sig_bytes(PNG_reader, 8);
1167 
1168  png_read_info(PNG_reader, PNG_info);
1169 
1170  pImage->width = png_get_image_width(PNG_reader, PNG_info);
1171  pImage->height = png_get_image_height(PNG_reader, PNG_info);
1172 
1173  png_uint_32 bit_depth, color_type;
1174  bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
1175  color_type = png_get_color_type(PNG_reader, PNG_info);
1176 
1177  if (color_type == PNG_COLOR_TYPE_PALETTE)
1178    {
1179      png_set_palette_to_rgb(PNG_reader);
1180    }
1181 
1182  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1183    {
1184      png_set_gray_1_2_4_to_8(PNG_reader);
1185    }
1186 
1187  if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1188    {
1189      png_set_gray_to_rgb(PNG_reader);
1190    }
1191 
1192  if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
1193    {
1194      png_set_tRNS_to_alpha(PNG_reader);
1195    }
1196  else
1197    {
1198      png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
1199    }
1200 
1201  if (bit_depth == 16)
1202    {
1203      png_set_strip_16(PNG_reader);
1204    }
1205 
1206  png_read_update_info(PNG_reader, PNG_info);
1207 
1208  pImage->data = (png_byte*)malloc(4 * pImage->width * pImage->height);
1209  png_byte** PNG_rows = (png_byte**)malloc(pImage->height * sizeof(png_byte*));
1210 
1211  unsigned int row;
1212  for (row = 0; row < pImage->height; ++row)
1213    {
1214      PNG_rows[pImage->height - 1 - row] = pImage->data + (row * 4 * pImage->width);
1215    }
1216 
1217  png_read_image(PNG_reader, PNG_rows);
1218 
1219  free(PNG_rows);
1220 
1221  png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
1222  fclose(PNG_file);
1223 
1224  /*  if (!ST_is_power_of_two(pImage->width) || !ST_is_power_of_two(pImage->height))
1225    {
1226      free(pImage->data);
1227      return 0;
1228    }
1229  */
1230  this->loadTexToGL (pImage, texture); 
1231 
1232  free(pImage->data);
1233 
1234  return true;
1235#else /* HAVE_PNG_H */
1236  PRINTF(1)("sorry, but you did not compile with png-support.\nEither install SDL_image or libpng, and recompile to see the image\n");
1237  return false;
1238#endif /* HAVE_PNG_H */
1239
1240}
1241
1242#endif /* HAVE_SDL_SDL_IMAGE_H */
Note: See TracBrowser for help on using the repository browser.