Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/images: pathlist now also accepts Paths from Windows.

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