Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: forgot some printf's, fixed now

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