Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/images: faster-fix

File size: 29.3 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  float r,g,b;
291  sscanf (rgb, "%f %f %f", &r, &g, &b);
292  setDiffuse (r, g, 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  float r,g,b;
317  sscanf (rgb, "%f %f %f", &r, &g, &b);
318  setAmbient (r, g, 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  float r,g,b;
343  sscanf (rgb, "%f %f %f", &r, &g, &b);
344  setSpecular (r, g, 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  setTransparency (atof(trans));
381}
382
383void Material::addTexturePath(char* pathName)
384{
385  pathList->addPath (pathName);
386}
387char* Material::searchTextureInPaths(char* texName) const
388{
389  char* tmpName = NULL;
390  PathList* pList = pathList;
391  while (pList)
392    {
393      if (pList->pathName)
394        {
395          tmpName = new char [strlen(pList->pathName)+strlen(texName)+1];
396          strcpy(tmpName, pList->pathName);
397        }
398      else
399        {
400          tmpName = new char [strlen(texName)+1];
401          tmpName[0]='\0';
402        }
403      strcat(tmpName, texName);
404      printf("%s\n", tmpName);
405      if (access (tmpName, F_OK) == 0)
406        return tmpName;
407     
408      if (tmpName)
409        delete []tmpName;
410      tmpName = NULL;
411      pList = pList->next;
412    }
413  return NULL;
414}
415
416
417// MAPPING //
418
419/**
420   \brief Sets the Materials Diffuse Map
421   \param dMap the Name of the Image to Use
422*/
423void Material::setDiffuseMap(char* dMap)
424{
425  if (verbose>=2)
426    printf ("setting Diffuse Map %s\n", dMap);
427
428  //  diffuseTextureSet = loadBMP(dMap, &diffuseTexture);
429  diffuseTextureSet = loadImage(dMap, &diffuseTexture);
430
431}
432
433/**
434   \brief Sets the Materials Ambient Map
435   \param aMap the Name of the Image to Use
436*/
437void Material::setAmbientMap(char* aMap)
438{
439  SDL_Surface* ambientMap;
440
441}
442
443/**
444   \brief Sets the Materials Specular Map
445   \param sMap the Name of the Image to Use
446*/
447void Material::setSpecularMap(char* sMap)
448{
449  SDL_Surface* specularMap;
450
451}
452
453/**
454   \brief Sets the Materials Bumpiness
455   \param bump the Name of the Image to Use
456*/
457void Material::setBump(char* bump)
458{
459
460}
461
462bool Material::loadTexToGL (Image* pImage, GLuint* texture)
463{
464  if (verbose >=3)
465    printf ("Loading texture to OpenGL-Environment.\n");
466  glGenTextures(1, texture);
467  glBindTexture(GL_TEXTURE_2D, *texture);
468  /* not Working, and not needed.
469  glTexImage2D( GL_TEXTURE_2D, 0, 3, width,
470                height, 0, GL_BGR,
471                GL_UNSIGNED_BYTE, map->pixels );
472  */ 
473  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pImage->width, pImage->height, GL_RGB, GL_UNSIGNED_BYTE, pImage->data);
474 
475  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
476  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); 
477}
478
479
480#ifdef HAVE_SDL_SDL_IMAGE_H
481bool Material::loadImage(char* imageName, GLuint* texture)
482{
483  char* imgNameWithPath= searchTextureInPaths(imageName);
484  if (imgNameWithPath)
485    {
486      SDL_Surface* map;
487      Image* pImage = new Image;
488      map=IMG_Load(imgNameWithPath);
489      if(!map)
490        {
491          printf("IMG_Load: %s\n", IMG_GetError());
492          return false;
493        }
494      pImage->height = map->h;
495      pImage->width  = map->w;
496      pImage->data   = (GLubyte*)map->pixels;
497      if( !IMG_isPNG(SDL_RWFromFile(imgNameWithPath, "rb")) && !IMG_isJPG(SDL_RWFromFile(imgNameWithPath, "rb")))
498        for (int i=0;i<map->h * map->w *3;i+=3)
499          { 
500            GLuint temp = pImage->data[i];
501            pImage->data[i] = pImage->data[i+2];
502            pImage->data[i+2] = temp;
503          }
504      loadTexToGL (pImage, texture);
505    }
506  else
507    {
508      if (verbose >=2)
509        printf ("Image not Found: %s\n", imageName);
510      return false;
511    }
512}
513#else
514/**
515   \brief Makes the Programm ready to Read-in a texture-File
516   1. Checks what type of Image should be imported
517   2. ToDO: Checks where to find the Image
518*/
519bool Material::loadImage(char* imageName, GLuint* texture)
520{
521  if (!strncmp(imageName+strlen(imageName)-4, ".bmp", 4))
522    {
523      if (verbose >=2)
524        printf ("Requested bmp-image. Trying to Import.\n");
525      return loadBMP(imageName, texture);
526    }
527
528  else if (!strncmp(imageName+strlen(imageName)-4, ".jpg", 4) || !strncmp(imageName+strlen(imageName)-5, ".jpg", 5))
529    {
530      if (verbose >=2)
531        printf ("Requested jpeg-image. Trying to Import\n");
532      return loadJPG(imageName, texture);
533    }
534  else if (!strncmp(imageName+strlen(imageName)-4, ".tga", 4))
535    {
536      if (verbose >=2)
537        printf ("Requested tga-image. Trying to Import\n");
538      return loadTGA(imageName, texture);
539    }
540  else if (!strncmp(imageName+strlen(imageName)-4, ".png", 4))
541    {
542      if (verbose >=2)
543        printf ("Requested png-image. Trying to Import\n");
544      return loadPNG(imageName, texture);
545    }
546  else
547    {
548      if (verbose >=1)
549        printf ("Requested Image was not recognized in its type. (Maybe a type-Cast-error.)\n FileName: %s", imageName);
550      return false;
551    }
552
553}
554
555/**
556   \brief reads in a Windows BMP-file, and imports it to openGL.
557   \param bmpName The name of the Image to load.
558   \param texture A pointer to the Texture which should be read to.
559*/
560bool Material::loadBMP (char* bmpName, GLuint* texture)
561{
562  Image* pImage = new Image;
563  FILE *file;
564  unsigned long size;                 // size of the image in bytes.
565  unsigned long i;                    // standard counter.
566  unsigned short int planes;          // number of planes in image (must be 1)
567  unsigned short int bpp;             // number of bits per pixel (must be 24)
568  GLuint temp;                          // temporary color storage for bgr-rgb conversion.
569
570  // make sure the file is there.
571  if ((file = fopen(bmpName, "rb"))==NULL)
572    {
573      if (verbose >=1)
574        printf("File Not Found : %s\n",bmpName);
575      return false;
576    }
577  // seek through the bmp header, up to the width/height:
578  fseek(file, 18, SEEK_CUR);
579 
580  // read the width
581  if ((i = fread(&pImage->width, 4, 1, file)) != 1) 
582    {
583      if (verbose >=1)
584        printf("Error reading width from %s.\n", bmpName);
585      return false;
586    }
587  // read the height
588  if ((i = fread(&pImage->height, 4, 1, file)) != 1) 
589    {
590      if (verbose>=1)
591        printf("Error reading height from %s.\n", bmpName);
592      return false;
593    }
594 
595  // calculate the size (assuming 24 bits or 3 bytes per pixel).
596  size = pImage->width * pImage->height * 3;
597 
598  // read the planes
599  if ((fread(&planes, 2, 1, file)) != 1) 
600    {
601      if (verbose>=1)
602        printf("Error reading planes from %s.\n", bmpName);
603      return false;
604    }
605  if (planes != 1) 
606    {
607      if (verbose>=1)
608        printf("Planes from %s is not 1: %u\n", bmpName, planes);
609      return false;
610    }
611 
612  // read the bpp
613  if ((i = fread(&bpp, 2, 1, file)) != 1) 
614    {
615      if (verbose>=1)
616        printf("Error reading bpp from %s.\n", bmpName);
617      return false;
618    }
619  if (bpp != 24) 
620    {
621      if (verbose>=1)
622        printf("Bpp from %s is not 24: %u\n", bmpName, bpp);
623      return false;
624    }
625 
626  // seek past the rest of the bitmap header.
627  fseek(file, 24, SEEK_CUR);
628 
629  // read the data.
630  pImage->data = (GLubyte *) malloc(size);
631  if (pImage->data == NULL) 
632    {
633      if (verbose>=1)
634        printf("Error allocating memory for color-corrected image data");
635      return false;     
636    }
637 
638  if ((i = fread(pImage->data, size, 1, file)) != 1) 
639    {
640      if (verbose>=1)
641        printf("Error reading image data from %s.\n", bmpName);
642      return false;
643    }
644  fclose(file);
645
646  // reverse all of the colors. (bgr -> rgb)
647  for (i=0;i<size;i+=3) 
648    { 
649      temp = pImage->data[i];
650      pImage->data[i] = pImage->data[i+2];
651      pImage->data[i+2] = temp;
652    }
653  loadTexToGL (pImage, texture);
654 
655  return true;
656
657  if (pImage)
658    {
659      if (pImage->data)
660        {
661          free(pImage->data);
662        }
663     
664      free(pImage);
665    }
666
667}
668
669/**
670   \brief reads in a jpg-file
671   \param jpgName the Name of the Image to load
672   \param texture a reference to the Texture to write the image to
673*/
674bool Material::loadJPG (char* jpgName, GLuint* texture)
675{
676#ifdef HAVE_JPEGLIB_H
677  struct jpeg_decompress_struct cinfo;
678  Image *pImage = NULL;
679  FILE *pFile;
680 
681  // Open a file pointer to the jpeg file and check if it was found and opened
682  if((pFile = fopen(jpgName, "rb")) == NULL) 
683    {
684      // Display an error message saying the file was not found, then return NULL
685      printf("Unable to load JPG File %s.\n", jpgName);
686      return false;
687    }
688 
689  // Create an error handler
690  jpeg_error_mgr jerr;
691 
692  // Have our compression info object point to the error handler address
693  cinfo.err = jpeg_std_error(&jerr);
694 
695  // Initialize the decompression object
696  jpeg_create_decompress(&cinfo);
697 
698  // Specify the data source (Our file pointer)
699  jpeg_stdio_src(&cinfo, pFile);
700 
701  // Allocate the structure that will hold our eventual jpeg data (must free it!)
702  pImage = (Image*)malloc(sizeof(Image));
703 
704  // DECOFING
705  // Read in the header of the jpeg file
706  jpeg_read_header(&cinfo, TRUE);
707 
708  // Start to decompress the jpeg file with our compression info
709  jpeg_start_decompress(&cinfo);
710 
711  // Get the image dimensions and row span to read in the pixel data
712  pImage->rowSpan = cinfo.image_width * cinfo.num_components;
713  pImage->width   = cinfo.image_width;
714  pImage->height   = cinfo.image_height;
715 
716  // Allocate memory for the pixel buffer
717  pImage->data = new unsigned char[pImage->rowSpan * pImage->height];
718 
719  // Here we use the library's state variable cinfo.output_scanline as the
720  // loop counter, so that we don't have to keep track ourselves.
721 
722  // Create an array of row pointers
723  unsigned char** rowPtr = new unsigned char*[pImage->height];
724  for (int i = 0; i < pImage->height; i++)
725    rowPtr[i] = &(pImage->data[i*pImage->rowSpan]);
726 
727  // Now comes the juice of our work, here we extract all the pixel data
728  int rowsRead = 0;
729  while (cinfo.output_scanline < cinfo.output_height) 
730    {
731      // Read in the current row of pixels and increase the rowsRead count
732      rowsRead += jpeg_read_scanlines(&cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead);
733    }
734 
735  // Delete the temporary row pointers
736  delete [] rowPtr;
737 
738  // Finish decompressing the data
739  jpeg_finish_decompress(&cinfo);//  decodeJPG(&cinfo, pImage);
740 
741  // This releases all the stored memory for reading and decoding the jpeg
742  jpeg_destroy_decompress(&cinfo);
743 
744  // Close the file pointer that opened the file
745  fclose(pFile);
746 
747
748  if(pImage == NULL)
749    exit(0);
750 
751  loadTexToGL (pImage, texture);
752  if (pImage)
753    {
754      if (pImage->data)
755        {
756          free(pImage->data);
757        }
758     
759      free(pImage);
760    }
761  return true;
762#else /* HAVE_JPEGLIB_H */
763  if (verbose >=1)
764    printf ("sorry, but you did not compile with jpeg-support.\nEither install SDL_image or jpeglib, and recompile to see the image\n");
765  return false;
766#endif /* HAVE_JPEGLIB_H */
767
768}
769
770/**
771   \brief reads in a tga-file
772   \param tgaName the Name of the Image to load
773   \param texture a reference to the Texture to write the image to
774*/
775bool Material::loadTGA(const char * tgaName, GLuint* texture)
776{
777  typedef struct
778  {
779    GLubyte Header[12];
780  } TGAHeader;
781  TGAHeader tgaHeader;                 
782 
783  GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
784  GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0}; // Compressed TGA Header
785  FILE * fTGA;
786  fTGA = fopen(tgaName, "rb");
787
788  if(fTGA == NULL)
789    {
790      printf("Error could not open texture file: %s\n", tgaName);
791      return false;
792    }
793 
794  if(fread(&tgaHeader, sizeof(TGAHeader), 1, fTGA) == 0)
795    {
796      printf("Error could not read file header of %s\n", tgaName);
797      if(fTGA != NULL)
798        {
799          fclose(fTGA);
800        }
801      return false;
802    }
803 
804  if(memcmp(uTGAcompare, &tgaHeader, sizeof(TGAHeader)) == 0)
805    {
806      loadUncompressedTGA(tgaName, fTGA, texture);
807      if (fTGA)
808        fclose (fTGA);
809    }
810  else if(memcmp(cTGAcompare, &tgaHeader, sizeof(TGAHeader)) == 0)
811    {
812      loadCompressedTGA(tgaName, fTGA, texture);
813        if (fTGA)
814          fclose (fTGA);
815    }
816  else
817    {
818      printf("Error TGA file be type 2 or type 10\n");
819      if (fTGA)
820        fclose(fTGA);
821      return false;
822    }
823  return true;
824}
825
826/**
827   \brief reads in an uncompressed tga-file
828   \param filename the Name of the Image to load
829   \param fTGA a Pointer to a File, that should be read
830   \param texture a reference to the Texture to write the image to
831*/
832bool Material::loadUncompressedTGA(const char * filename, FILE * fTGA, GLuint* texture)
833{
834  GLubyte header[6];      // First 6 Useful Bytes From The Header
835  GLuint  bytesPerPixel;  // Holds Number Of Bytes Per Pixel Used In The TGA File
836  GLuint  imageSize;      // Used To Store The Image Size When Setting Aside Ram
837  GLuint  temp;           // Temporary Variable
838  GLuint  type;
839  GLuint  Height;         // Height of Image
840  GLuint  Width;          // Width of Image
841  GLuint  Bpp;            // Bits Per Pixel
842
843  Image* pImage = new Image;
844  GLuint cswap;
845  if(fread(header, sizeof(header), 1, fTGA) == 0)
846    {
847      printf("Error could not read info header\n");
848      return false;
849    }
850 
851  Width = pImage->width  = header[1] * 256 + header[0];
852  Height =  pImage->height = header[3] * 256 + header[2];
853  Bpp = pImage->bpp = header[4];
854  // Make sure all information is valid
855  if((pImage->width <= 0) || (pImage->height <= 0) || ((pImage->bpp != 24) && (pImage->bpp !=32)))
856    {
857      printf("Error invalid texture information\n");
858      return false;
859    }
860 
861  if(pImage->bpp == 24) 
862    {
863      pImage->type = GL_RGB;
864    }
865  else
866    {
867      pImage->type = GL_RGBA;
868    }
869 
870  bytesPerPixel = (Bpp / 8);
871  imageSize = (bytesPerPixel * Width * Height);
872  pImage->data = (GLubyte*) malloc(imageSize);
873 
874  if(pImage->data == NULL)
875    {
876      printf("Error could not allocate memory for image\n");
877      return false;
878    }
879 
880  if(fread(pImage->data, 1, imageSize, fTGA) != imageSize)
881    {
882      printf("Error could not read image data\n");
883      if(pImage->data != NULL)
884        {
885          free(pImage->data);
886        }
887      return false;
888    }
889 
890  for(cswap = 0; cswap < (int)imageSize; cswap += bytesPerPixel)
891    {
892      pImage->data[cswap] ^= pImage->data[cswap+2] ^=
893        pImage->data[cswap] ^= pImage->data[cswap+2];
894    }
895 
896  loadTexToGL (pImage, texture);
897
898  return true;
899}
900
901/**
902   \brief reads in a compressed tga-file
903   \param filename the Name of the Image to load
904   \param fTGA a Pointer to a File, that should be read
905   \param texture a reference to the Texture to write the image to
906*/
907bool Material::loadCompressedTGA(const char * filename, FILE * fTGA, GLuint* texture)
908{
909  GLubyte header[6];      // First 6 Useful Bytes From The Header
910  GLuint  bytesPerPixel;  // Holds Number Of Bytes Per Pixel Used In The TGA File
911  GLuint  imageSize;      // Used To Store The Image Size When Setting Aside Ram
912  GLuint  temp;           // Temporary Variable
913  GLuint  type;
914  GLuint  Height;         // Height of Image
915  GLuint  Width;          // Width of Image
916  GLuint  Bpp;            // Bits Per Pixel
917
918  Image* pImage = new Image;
919
920 
921  if(fread(header, sizeof(header), 1, fTGA) == 0)
922    {
923      printf("Error could not read info header\n");
924      return false;
925    }
926 
927  Width = pImage->width  = header[1] * 256 + header[0];
928  Height = pImage->height = header[3] * 256 + header[2];
929  Bpp = pImage->bpp     = header[4];
930
931  GLuint pixelcount     = Height * Width;
932  GLuint currentpixel   = 0;
933  GLuint currentbyte    = 0;
934  GLubyte * colorbuffer = (GLubyte *)malloc(bytesPerPixel);
935
936  //Make sure all pImage info is ok
937  if((pImage->width <= 0) || (pImage->height <= 0) || ((pImage->bpp != 24) && (pImage->bpp !=32)))
938    {
939      printf("Error Invalid pImage information\n");
940      return false;
941    }
942 
943  bytesPerPixel = (Bpp / 8);
944  imageSize             = (bytesPerPixel * Width * Height);
945  pImage->data  = (GLubyte*) malloc(imageSize);
946 
947  if(pImage->data == NULL)
948    {
949      printf("Error could not allocate memory for image\n");
950      return false;
951    }
952 
953  do
954    {
955      GLubyte chunkheader = 0;
956     
957      if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0)
958        {
959          printf("Error could not read RLE header\n");
960          if(pImage->data != NULL)
961            {
962              free(pImage->data);
963            }
964          return false;
965        }
966      // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
967      if(chunkheader < 128)
968        {
969          short counter;
970          chunkheader++;
971          // Read RAW color values
972          for(counter = 0; counter < chunkheader; counter++)
973            { 
974              // Try to read 1 pixel
975              if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel)
976                {
977                  printf("Error could not read image data\n");
978                  if(colorbuffer != NULL)
979                    {
980                      free(colorbuffer);
981                    }
982                 
983                  if(pImage->data != NULL)
984                    {
985                      free(pImage->data);
986                    }
987                 
988                  return false; 
989                }
990              // write to memory
991              // Flip R and B vcolor values around in the process
992              pImage->data[currentbyte    ] = colorbuffer[2];                               
993              pImage->data[currentbyte + 1] = colorbuffer[1];
994              pImage->data[currentbyte + 2] = colorbuffer[0];
995             
996              if(bytesPerPixel == 4) // if its a 32 bpp image
997                {
998                  pImage->data[currentbyte + 3] = colorbuffer[3];// copy the 4th byte
999                }
1000             
1001              currentbyte += bytesPerPixel;
1002              currentpixel++;
1003
1004              // Make sure we haven't read too many pixels
1005              if(currentpixel > pixelcount)     
1006                {
1007                  printf("Error too many pixels read\n");
1008                  if(colorbuffer != NULL)
1009                    {
1010                      free(colorbuffer);
1011                    }
1012                 
1013                  if(pImage->data != NULL)
1014                    {
1015                      free(pImage->data);
1016                    }
1017                 
1018                  return false;
1019                }
1020            }
1021        }
1022      // chunkheader > 128 RLE data, next color  reapeated chunkheader - 127 times
1023      else
1024        {
1025          short counter;
1026          chunkheader -= 127;   // Subteact 127 to get rid of the ID bit
1027          if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel) // Attempt to read following color values
1028            {
1029              printf("Error could not read from file");
1030              if(colorbuffer != NULL)
1031                {
1032                  free(colorbuffer);
1033                }
1034             
1035              if(pImage->data != NULL)
1036                {
1037                  free(pImage->data);
1038                }
1039             
1040              return false;
1041            }
1042         
1043          for(counter = 0; counter < chunkheader; counter++) //copy the color into the image data as many times as dictated
1044            {                                                   
1045              // switch R and B bytes areound while copying
1046              pImage->data[currentbyte    ] = colorbuffer[2];
1047              pImage->data[currentbyte + 1] = colorbuffer[1];
1048              pImage->data[currentbyte + 2] = colorbuffer[0];
1049             
1050              if(bytesPerPixel == 4)
1051                {
1052                  pImage->data[currentbyte + 3] = colorbuffer[3];
1053                }
1054             
1055              currentbyte += bytesPerPixel;
1056              currentpixel++;
1057             
1058              if(currentpixel > pixelcount)
1059                {
1060                  printf("Error too many pixels read\n");
1061                  if(colorbuffer != NULL)
1062                    {
1063                      free(colorbuffer);
1064                    }
1065                 
1066                  if(pImage->data != NULL)
1067                    {
1068                      free(pImage->data);
1069                    }
1070                 
1071                  return false;
1072                }
1073            }
1074        }
1075    }
1076 
1077  while(currentpixel < pixelcount);     // Loop while there are still pixels left
1078
1079  loadTexToGL (pImage, texture);
1080
1081  return true;
1082}
1083
1084
1085/*
1086static int ST_is_power_of_two(unsigned int number)
1087{
1088  return (number & (number - 1)) == 0;
1089}
1090*/
1091
1092/**
1093   \brief reads in a png-file
1094   \param pngName the Name of the Image to load
1095   \param texture a reference to the Texture to write the image to
1096*/
1097bool Material::loadPNG(const char* pngName, GLuint* texture)
1098{
1099#ifdef HAVE_PNG_H
1100  Image* pImage = new Image;
1101
1102  FILE *PNG_file = fopen(pngName, "rb");
1103  if (PNG_file == NULL)
1104    {
1105      return 0;
1106    }
1107 
1108  GLubyte PNG_header[8];
1109 
1110  fread(PNG_header, 1, 8, PNG_file);
1111  if (png_sig_cmp(PNG_header, 0, 8) != 0)
1112    {
1113      if (verbose >=2)
1114        printf ("Not Recognized as a pngFile\n");
1115      fclose (PNG_file);
1116      return 0;
1117    }
1118 
1119  png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1120  if (PNG_reader == NULL)
1121    {
1122      fclose(PNG_file);
1123      return 0;
1124    }
1125 
1126  png_infop PNG_info = png_create_info_struct(PNG_reader);
1127  if (PNG_info == NULL)
1128    {
1129      png_destroy_read_struct(&PNG_reader, NULL, NULL);
1130      fclose(PNG_file);
1131      return 0;
1132    }
1133 
1134  png_infop PNG_end_info = png_create_info_struct(PNG_reader);
1135  if (PNG_end_info == NULL)
1136    {
1137      png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
1138      fclose(PNG_file);
1139      return 0;
1140    }
1141 
1142  if (setjmp(png_jmpbuf(PNG_reader)))
1143    {
1144      png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
1145      fclose(PNG_file);
1146      return (0);
1147    }
1148 
1149  png_init_io(PNG_reader, PNG_file);
1150  png_set_sig_bytes(PNG_reader, 8);
1151 
1152  png_read_info(PNG_reader, PNG_info);
1153 
1154  pImage->width = png_get_image_width(PNG_reader, PNG_info);
1155  pImage->height = png_get_image_height(PNG_reader, PNG_info);
1156 
1157  png_uint_32 bit_depth, color_type;
1158  bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
1159  color_type = png_get_color_type(PNG_reader, PNG_info);
1160 
1161  if (color_type == PNG_COLOR_TYPE_PALETTE)
1162    {
1163      png_set_palette_to_rgb(PNG_reader);
1164    }
1165 
1166  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1167    {
1168      png_set_gray_1_2_4_to_8(PNG_reader);
1169    }
1170 
1171  if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1172    {
1173      png_set_gray_to_rgb(PNG_reader);
1174    }
1175 
1176  if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
1177    {
1178      png_set_tRNS_to_alpha(PNG_reader);
1179    }
1180  else
1181    {
1182      png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
1183    }
1184 
1185  if (bit_depth == 16)
1186    {
1187      png_set_strip_16(PNG_reader);
1188    }
1189 
1190  png_read_update_info(PNG_reader, PNG_info);
1191 
1192  pImage->data = (png_byte*)malloc(4 * pImage->width * pImage->height);
1193  png_byte** PNG_rows = (png_byte**)malloc(pImage->height * sizeof(png_byte*));
1194 
1195  unsigned int row;
1196  for (row = 0; row < pImage->height; ++row)
1197    {
1198      PNG_rows[pImage->height - 1 - row] = pImage->data + (row * 4 * pImage->width);
1199    }
1200 
1201  png_read_image(PNG_reader, PNG_rows);
1202 
1203  free(PNG_rows);
1204 
1205  png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
1206  fclose(PNG_file);
1207 
1208  /*  if (!ST_is_power_of_two(pImage->width) || !ST_is_power_of_two(pImage->height))
1209    {
1210      free(pImage->data);
1211      return 0;
1212    }
1213  */
1214  loadTexToGL (pImage, texture); 
1215 
1216  free(pImage->data);
1217 
1218  return true;
1219#else /* HAVE_PNG_H */
1220  if (verbose >=1)
1221    printf ("sorry, but you did not compile with png-support.\nEither install SDL_image or libpng, and recompile to see the image\n");
1222  return false;
1223#endif /* HAVE_PNG_H */
1224
1225}
1226
1227#endif /* HAVE_SDL_SDL_IMAGE_H */
Note: See TracBrowser for help on using the repository browser.