Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/importer/material.cc @ 3177

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

orxonox/trunk: finding sdl-image more flexible.

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