Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3097 was 3097, checked in by bensch, 21 years ago

orxonox/branches/images: doxygen-tags, comments, etc.

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