Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/images: efficiency fixes

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