Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/importer/material.cc @ 3205

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

orxonox/trunk/importer: this→pointers implemented in classes object, material, array, pathlist

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