Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/images/importer/material.cc @ 3127

Last change on this file since 3127 was 3127, checked in by bensch, 19 years ago

orxonox/branches/images: Implemented a Way to read in the Files from any Directory.

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