Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

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