]> git.mxchange.org Git - simgear.git/blob - simgear/scene/sky/clouds3d/SkyTextureManager.cpp
A first attempt at making the clouds3d endian aware. Almost there.
[simgear.git] / simgear / scene / sky / clouds3d / SkyTextureManager.cpp
1 //------------------------------------------------------------------------------
2 // File : SkyTextureManager.cpp
3 //------------------------------------------------------------------------------
4 // SkyWorks : Copyright 2002 Mark J. Harris and
5 //                                              The University of North Carolina at Chapel Hill
6 //------------------------------------------------------------------------------
7 // Permission to use, copy, modify, distribute and sell this software and its 
8 // documentation for any purpose is hereby granted without fee, provided that 
9 // the above copyright notice appear in all copies and that both that copyright 
10 // notice and this permission notice appear in supporting documentation. 
11 // Binaries may be compiled with this software without any royalties or 
12 // restrictions. 
13 //
14 // The author(s) and The University of North Carolina at Chapel Hill make no 
15 // representations about the suitability of this software for any purpose. 
16 // It is provided "as is" without express or implied warranty.
17 /**
18  * @file SkyTextureManager.cpp
19  * 
20  * Implementation of a manager that keeps track of texture resource locations and sharing.
21  */
22
23 #pragma warning( disable : 4786)
24
25 #include "SkyTextureManager.hpp"
26 #include "SkyContext.hpp"
27 //#include "glvu.hpp"
28 //#include "ppm.hpp"
29 //#include "tga.hpp"
30 //#include "fileutils.hpp"
31
32 bool SkyTextureManager::s_bSlice3DTextures = false;
33
34 //------------------------------------------------------------------------------
35 // Function               : SkyTextureManager::SkyTextureManager
36 // Description      : 
37 //------------------------------------------------------------------------------
38 /**
39  * @fn SkyTextureManager::SkyTextureManager(bool bSlice3DTextures)
40  * @brief Constructor.
41  * 
42  */ 
43 SkyTextureManager::SkyTextureManager(bool bSlice3DTextures /* = false */)
44 {
45   s_bSlice3DTextures = bSlice3DTextures;
46
47   // this should be put somewhere more safe -- like done once in the functions that actually
48   // use these extensions.
49   /*GraphicsContext::InstancePtr()->InitializeExtensions("GL_ARB_texture_cube_map "
50                                                          "GL_VERSION_1_2");*/
51 }
52
53
54 //------------------------------------------------------------------------------
55 // Function               : SkyTextureManager::~SkyTextureManager
56 // Description      : 
57 //------------------------------------------------------------------------------
58 /**
59  * @fn SkyTextureManager::~SkyTextureManager()
60  * @brief destructor.
61  * 
62  * @todo <WRITE EXTENDED SkyTextureManager::~SkyTextureManager FUNCTION DOCUMENTATION>
63  */ 
64 SkyTextureManager::~SkyTextureManager()
65 {
66   _texturePaths.clear();
67   for ( TextureIterator iter = _textures.begin(); 
68         iter != _textures.end(); 
69         ++iter)
70   {
71     DestroyTextureObject(iter->second);
72   }
73   _textures.clear();
74
75   for ( TextureList::iterator uncachedIter = _uncachedTextures.begin(); 
76         uncachedIter != _uncachedTextures.end();
77         ++uncachedIter)
78   {
79     DestroyTextureObject(*uncachedIter);
80   }
81   _uncachedTextures.clear();
82 }
83
84
85 //------------------------------------------------------------------------------
86 // Function               : SkyTextureManager::AddPath
87 // Description      : 
88 //------------------------------------------------------------------------------
89 /**
90  * @fn SkyTextureManager::AddPath(const string &path)
91  * @brief Adds a texture path to the list of active search paths. 
92  * 
93  */ 
94 void  SkyTextureManager::AddPath(const string &path)
95 {
96   _texturePaths.push_back(path);
97 }
98
99
100 //------------------------------------------------------------------------------
101 // Function               : SkyTextureManager::Get2DTexture
102 // Description      : 
103 //------------------------------------------------------------------------------
104 /**
105  * @fn SkyTextureManager::Get2DTexture(const string& filename, SkyTexture& texture, bool bMipmap)
106  * @brief Returns a 2D texture object from the texture set.
107  * 
108  * If the texture is already loaded, it is returned.  If it is not, the texture is loaded from 
109  * file, added to the texture set, and returned.
110  * 
111  * If the image cannot be loaded, returns an error.  Otherwise returns success.
112  */ 
113 SKYRESULT SkyTextureManager::Get2DTexture(const string& filename, 
114                                           SkyTexture& texture,
115                                           bool bMipmap /* = false */)
116 {
117   TextureIterator iter = _textures.find(filename);
118   
119   if (iter != _textures.end())
120   { // the texture is already loaded, just return it.
121     texture = iter->second;
122   }
123   else
124   { // the texture is being requested for the first time, load and return it
125     FAIL_RETURN(Clone2DTexture(filename, texture, bMipmap));
126
127     _textures.insert(make_pair(filename, texture));  
128   }
129
130   return SKYRESULT_OK;
131 }
132
133
134 //------------------------------------------------------------------------------
135 // Function               : SkyTextureManager::Get3DTexture
136 // Description      : 
137 //------------------------------------------------------------------------------
138 /**
139  * @fn SkyTextureManager::Get3DTexture(const string& filename, SkyTexture& texture, unsigned int iDepth, bool bMipmap, bool bLoadFromSliceFiles)
140  * @brief Returns a 3D texture object from the texture set.
141  * 
142  * If the texture is already loaded, it is returned.  If it is not, the texture is loaded from 
143  * file, added to the texture set, and returned.  If the image cannot be loaded, returns an error.  
144  * Otherwise returns success. 
145  *
146  * For 3D textures, this simply loads a 2D image file, and duplicates it across each slice.  The 
147  * parameter iDepth must be set in order to use a 2D texture image for a 3D texture. 
148  */ 
149 SKYRESULT SkyTextureManager::Get3DTexture(const string& filename, 
150                                        SkyTexture& texture,
151                                        unsigned int iDepth,
152                                        bool bMipmap /* = false */,
153                                        bool bLoadFromSliceFiles /* = false */)
154 {
155   TextureIterator iter = _textures.find(filename);
156   
157   if (iter != _textures.end())
158   { // the texture is already loaded, just return it.
159     texture = iter->second;
160   }
161   else
162   { // the texture is being requested for the first time, load and return it
163     FAIL_RETURN(Clone3DTexture(filename, texture, iDepth, bMipmap, bLoadFromSliceFiles));
164
165     _textures.insert(make_pair(filename, texture));  
166   }
167
168   return SKYRESULT_OK;
169 }
170
171
172 //------------------------------------------------------------------------------
173 // Function               : roundPowerOf2
174 // Description      : 
175 //------------------------------------------------------------------------------
176 static int roundPowerOf2(int n)
177 {
178   int m;
179   for (m = 1; m < n; m *= 2);
180
181   // m >= n
182   if (m - n <= n - m/2) 
183     return m;
184   else
185     return m/2;
186 }
187
188
189 //------------------------------------------------------------------------------
190 // Function               : SkyTextureManager::Clone2DTexture
191 // Description      : 
192 //------------------------------------------------------------------------------
193 /**
194  * @fn SkyTextureManager::Clone2DTexture( const string &filename, SkyTexture& texture, bool bMipmap)
195  * @brief Returns a 2D texture object.
196  * 
197  * Ignores texture set.  This always loads the file, if it exists, and creates and returns the texture.
198  *
199  * If the image cannot be loaded, returns an error.  Otherwise returns success.
200  */ 
201 SKYRESULT SkyTextureManager::Clone2DTexture(const string &filename, 
202                                             SkyTexture& texture,
203                                             bool bMipmap /* = false */)
204 {
205   string pathFilename;
206   unsigned char *pImageData = NULL;
207   int iWidth       = 0;
208   int iHeight      = 0;
209   int iChannels    = 0;
210
211   enum ImageType
212   {
213     IMAGE_PPM,
214     IMAGE_TGA
215   };
216   ImageType eType;
217 /****
218   // first get the image type from its extension.
219   if (filename.find(".tga") != string.npos || filename.find(".TGA") != string.npos)
220     eType = IMAGE_TGA;
221   else if (filename.find(".ppm") != string.npos || filename.find(".PPM") != string.npos)
222     eType = IMAGE_PPM;
223   else 
224     FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureManager error: invalid image format");
225   ****/
226   // first try the filename sent in in case it includes a path.
227   //if (FileUtils::FileExists(filename.c_str()))
228   //{
229  // printf("Filename is %s\n",  filename.c_str() );
230   //eType = IMAGE_TGA;
231   /*  switch (eType)
232     {
233     case IMAGE_PPM:
234       LoadPPM(filename.c_str(), pImageData, iWidth, iHeight);
235       iChannels = 3;
236       break;
237     case IMAGE_TGA:      
238       LoadTGA(filename.c_str(), pImageData, iWidth, iHeight, iChannels);
239       break;
240     default:
241       break;
242     }*/
243     
244   //}
245   
246   if (!pImageData) // image not found in current directory.  Check the paths...
247   {
248     
249     for ( StringList::iterator iter = _texturePaths.begin(); 
250           iter != _texturePaths.end(); 
251           ++iter)
252
253     { // loop over all texture paths, looking for the filename
254       // get just the filename without path.
255       int iPos = filename.find_last_of("/");
256       if (iPos == filename.npos)
257         iPos = filename.find_last_of("/");
258       
259       // tack on the paths from the texture path list.
260       if (iPos != filename.npos)
261         pathFilename = (*iter) + "/" +  filename.substr(iPos+1);
262       else
263         pathFilename = (*iter) + "/" +  filename;
264         
265       //if (FileUtils::FileExists(pathFilename.c_str()))
266       //{
267        /* switch (eType)
268         {
269         case IMAGE_PPM:
270           LoadPPM(pathFilename.c_str(), pImageData, iWidth, iHeight);
271           break;
272         case IMAGE_TGA:
273           LoadTGA(pathFilename.c_str(), pImageData, iWidth, iHeight, iChannels);
274           break;
275         default:
276           break;
277         }*/
278         
279         //if (pImageData)
280           //break;
281       //}
282     }
283   }
284
285   if (!pImageData)
286   {
287     char buffer[256];
288     sprintf(buffer, "SkyTextureManager::Clone2DTexture(): Could not load image. %s.\n", filename.c_str());
289     FAIL_RETURN_MSG(SKYRESULT_OK, buffer);
290   }
291
292   // make sure it is power of 2 resolution.
293   int iNewWidth  = roundPowerOf2(iWidth);
294   int iNewHeight = roundPowerOf2(iHeight);
295   int iMaxsize;
296   glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
297   if (iNewWidth > iMaxsize) 
298   {
299     iNewWidth = iMaxsize;
300   }
301   if (iNewHeight> iMaxsize) 
302   {
303     iNewHeight = iMaxsize;
304   }
305
306   GLenum eFormat = (4 == iChannels) ? GL_RGBA : GL_RGB;
307
308   if (iNewWidth != iWidth || iNewHeight != iHeight)
309   {
310     unsigned char *pScaledImageData = new unsigned char[iChannels * iNewWidth * iNewHeight];  
311     gluScaleImage(eFormat, iWidth, iHeight, GL_UNSIGNED_BYTE, pImageData, 
312                   iNewWidth, iNewHeight, GL_UNSIGNED_BYTE, pScaledImageData);
313     SAFE_DELETE_ARRAY(pImageData);
314     pImageData = pScaledImageData;
315   }
316   
317   _Create2DTextureObject( texture, iNewWidth, iNewHeight, eFormat, pImageData);
318   
319   SAFE_DELETE_ARRAY(pImageData);
320   return SKYRESULT_OK;
321 }
322
323
324 //------------------------------------------------------------------------------
325 // Function               : SkyTextureManager::Clone3DTexture
326 // Description      : 
327 //------------------------------------------------------------------------------
328 /**
329  * @fn SkyTextureManager::Clone3DTexture( const string &filename, SkyTexture& texture, unsigned int iDepth, bool bMipmap, bool bLoadFromSliceFiles)
330  * @brief Returns a 3D texture object.
331  * 
332  * Ignores texture set.  This always loads the file, if it exists, and creates and returns the texture.
333  * If the image cannot be loaded, returns an error.  Otherwise returns success.
334  */ 
335 SKYRESULT SkyTextureManager::Clone3DTexture(const string &filename, 
336                                             SkyTexture& texture,
337                                             unsigned int iDepth,
338                                             bool bMipmap /* = false */,
339                                             bool bLoadFromSliceFiles /* = false */)
340 {
341   string pathFilename;
342   /*QImage  image;
343   QDir    dir;
344   unsigned char *pBits = NULL;
345   
346   if (!bLoadFromSliceFiles)
347   {
348     // first try the filename sent in in case it includes a path.
349     if (image.load(filename))
350     {
351       image = QGLWidget::convertToGLFormat(image);
352     }
353     else
354     {
355       image.reset();
356       
357       for ( QStringList::Iterator iter = _texturePaths.begin(); 
358       iter != _texturePaths.end(); 
359       iter++)
360       { // loop over all texture paths, looking for the filename
361         pathFilename = (*iter) + "\\" +  filename;
362         
363         if (image.load(pathFilename))
364         {
365           image = QGLWidget::convertToGLFormat(image);
366           break;
367         }
368         else
369           image.reset();
370       }
371     }
372     
373     if (image.isNull())
374     {
375       qWarning("SkyTextureManager::GetTexture(): Could not load image "
376         "%s.\n", filename);
377       return false;
378     }
379     
380     // make sure it is power of 2 resolutions.
381     int iWidth  = roundPowerOf2(image.width());
382     int iHeight = roundPowerOf2(image.height());
383     int iMaxsize;
384     if (s_bSlice3DTextures)
385       glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
386     else
387       glGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &iMaxsize );
388     if (iWidth > iMaxsize) 
389     {
390       iWidth = iMaxsize;
391     }
392     if (iHeight> iMaxsize) 
393     {
394       iHeight = iMaxsize;
395     }
396     
397     if (iWidth != image.width() || iHeight != image.height())
398       image = image.smoothScale(iWidth, iHeight);
399     
400     // first build an array of repeated 2D textures...
401     QImage inverted(image.mirror());
402     pBits = new unsigned char[image.numBytes() * iDepth];
403     unsigned int iSliceSize = image.numBytes();
404     int bInverted = false;
405     int iInvertedCount = 8;
406     for (unsigned int iSlice = 0; iSlice < iDepth; ++iSlice)
407     { 
408       memcpy(&(pBits[iSlice * iSliceSize]), 
409         (bInverted) ? inverted.bits() : image.bits(), 
410         image.numBytes());
411       if (--iInvertedCount <= 0) 
412       {
413         iInvertedCount = 8;
414         bInverted = !bInverted;
415       }
416     }
417   }
418   else /// Load from a set of files matching the file pattern
419   {
420     QFileInfo fi(filename);
421     fi.refresh();
422     
423     QString baseFilename = fi.baseName();
424     int truncPos = baseFilename.find(QRegExp("[0-9]"));
425     if (truncPos >= 0)
426       baseFilename.truncate(truncPos);
427
428     dir.setFilter(QDir::Files);
429     dir.setNameFilter(baseFilename + "*." + fi.extension());
430     dir.setSorting(QDir::Name);
431     QStringList files = dir.entryList();
432
433     bool bFound = true;
434     if (files.count() < iDepth)
435     {
436       bFound = false;
437       for ( QStringList::Iterator iter = _texturePaths.begin(); 
438           iter != _texturePaths.end(); 
439           iter++)
440       { 
441         dir.setCurrent(*iter);
442         files = dir.entryList();
443         if (files.count() >= iDepth)
444         {
445           bFound = true;
446           break;
447         }
448       }
449     }
450     if (!bFound)
451     {
452       qWarning("SkyTextureManager::Clone3DTexture: ERROR: could not find %d files matching "
453                "%s", iDepth, filename.latin1());
454       return false;
455     }
456     else
457     {
458       unsigned int iSlice = 0;
459       unsigned int  iSliceSize = 0;
460       for ( QStringList::Iterator iter = files.begin(); 
461             iter != files.end() && iSlice < iDepth; 
462             iter++)
463       {
464         if (image.load(*iter))
465         {
466           image = QGLWidget::convertToGLFormat(image);
467           // make sure it is power of 2 resolution.
468           int iWidth  = roundPowerOf2(image.width());
469           int iHeight = roundPowerOf2(image.height());
470           int iMaxsize;
471           if (s_bSlice3DTextures)
472             glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
473           else
474             glGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &iMaxsize );
475           if (iWidth > iMaxsize) 
476           {
477             iWidth = iMaxsize;
478           }
479           if (iHeight> iMaxsize) 
480           {
481             iHeight = iMaxsize;
482           }
483           
484           if (iWidth != image.width() || iHeight != image.height())
485             image = image.smoothScale(iWidth, iHeight);
486           if (0 == iSlice)
487           {
488             pBits       = new unsigned char[image.numBytes() * iDepth];
489             iSliceSize  = image.numBytes();
490           }
491           memcpy(&(pBits[iSlice * iSliceSize]), image.bits(), image.numBytes());
492           ++iSlice;
493         }
494         else
495         {
496           qWarning("SkyTextureManager::Clone3DTexture: ERROR: could not find %d files matching "
497                "%s", iDepth, filename);
498           return false;
499         }
500       }
501       
502     }
503   }
504
505   _Create3DTextureObject(texture, 
506                         image.width(), 
507                         image.height(),
508                         iDepth,
509                         GL_RGBA, 
510                         pBits);
511 */
512   return SKYRESULT_FAIL;
513 }
514
515
516
517 //! 
518 /*!  */
519
520 //------------------------------------------------------------------------------
521 // Function               : SkyTextureManager::GetCubeMapTexture
522 // Description      : 
523 //------------------------------------------------------------------------------
524 /**
525  * @fn SkyTextureManager::GetCubeMapTexture(const string& filename, SkyTexture& texture, bool bMipmap)
526  * @brief Returns a cube map texture object from the texture set
527  * 
528  * If the texture is already loaded, it is returned.  If it is not, the texture is loaded from file, 
529  * added to the texture set, and returned.  If any of the 6 images cannot be loaded, returns an error.  
530  * Otherwise returns success.
531  */ 
532 SKYRESULT SkyTextureManager::GetCubeMapTexture( const string& filename, 
533                                                 SkyTexture&   texture,
534                                                 bool          bMipmap)
535 {
536   TextureIterator iter = _textures.find(filename);
537   
538   if (iter != _textures.end())
539   { // the texture is already loaded, just return it.
540     texture = iter->second;
541   }
542   else
543   { // the texture is being requested for the first time, load and return it
544     if (!CloneCubeMapTexture(filename, texture, bMipmap))
545       return false;
546
547     _textures.insert(make_pair(filename, texture));  
548   }
549
550   return true;
551 }
552
553
554 //------------------------------------------------------------------------------
555 // Function               : SkyTextureManager::CloneCubeMapTexture
556 // Description      : 
557 //------------------------------------------------------------------------------
558 /**
559  * @fn SkyTextureManager::CloneCubeMapTexture(const string& filename, SkyTexture& texture, bool bMipmap)
560  * @brief Returns a cube map texture object.
561  * 
562  * Ignores the texture set.  This always loads the cube map texture, if all 6 face images exist, 
563  * creates the texture, and returns it.  If any of the 6 images cannot be loaded, returns an error.  
564  * Otherwise returns success.
565  */ 
566 SKYRESULT SkyTextureManager::CloneCubeMapTexture( const string& filename, 
567                                                   SkyTexture&   texture,
568                                                   bool          bMipmap)
569 {
570   string pathFilename;
571   /*QImage  images[6];
572
573   GLenum faces [] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
574                       GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
575                       GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
576                       GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
577                       GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
578                       GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB };
579   char* faceNames[] = {"posx", "negx", "posy", "negy", "posz", "negz" };
580
581   for ( QStringList::Iterator iter = _texturePaths.begin(); 
582         iter != _texturePaths.end(); 
583         iter++)
584   { // loop over all texture paths, looking for the filename
585     for (int i = 0; i < 6; i++)
586     {
587       char buffer[FILENAME_MAX];
588       sprintf(buffer, filename.ascii(), faceNames[i]);
589       pathFilename = (*iter) + "\\" + buffer;
590
591       if (images[i].load(pathFilename))
592       {
593         images[i] = QGLWidget::convertToGLFormat(images[i]);
594       }
595       else
596         images[i].reset();
597     }
598   }
599     
600   for (int i = 0; i < 6; i++)
601   {
602     if (images[i].isNull())
603     {
604       char buffer[FILENAME_MAX];
605       sprintf(buffer, filename.ascii(), faceNames[i]);
606       qWarning("SkyTextureManager::GetTexture(): Could not load image "
607                 "%s.\n", buffer);
608       return false;
609     }
610   }
611     
612   glGenTextures(1, &(texture.iTextureID));
613   texture.iWidth  = images[0].width();
614   texture.iHeight = images[0].height();
615   
616   // create and bind a cubemap texture object
617   glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texture.iTextureID);
618   
619   // enable automipmap generation if needed.
620   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_GENERATE_MIPMAP_SGIS, bMipmap);
621   if (bMipmap)
622     glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
623   else
624     glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
625   glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
626   glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
627   glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
628
629   for (i = 0; i < 6; i++)
630   {
631     glTexImage2D(faces[i], 
632                  0, 
633                  GL_RGBA8, 
634                  images[i].width(), 
635                  images[i].height(), 
636                  0, 
637                  GL_RGBA, 
638                  GL_UNSIGNED_BYTE, 
639                  images[i].bits());
640   }*/
641
642   return true;
643 }
644
645
646 //------------------------------------------------------------------------------
647 // Function               : SkyTextureManager::_Create2DTextureObject
648 // Description      : 
649 //------------------------------------------------------------------------------
650 /**
651  * @fn SkyTextureManager::_Create2DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iFormat, unsigned char *pData)
652  * @brief Creates a 2D texture.
653  * 
654  * Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
655  */ 
656 SKYRESULT SkyTextureManager::_Create2DTextureObject(SkyTexture &texture,
657                                                     unsigned int iWidth, 
658                                                     unsigned int iHeight,
659                                                     unsigned int iFormat,
660                                                     unsigned char *pData)
661
662   bool bNew = false;
663   unsigned int iTextureID;
664   if (!texture.GetID())
665   {
666     glGenTextures(1, &iTextureID);
667     texture.SetID(iTextureID);
668     bNew = true;
669   }
670   texture.SetWidth(iWidth);
671   texture.SetHeight(iHeight);
672
673   glBindTexture(GL_TEXTURE_2D, texture.GetID());
674     
675   if (bNew)
676   {
677     GLenum iInternalFormat;
678     switch (iFormat)
679     {
680     case GL_LUMINANCE:
681       iInternalFormat = GL_LUMINANCE;
682       break;
683     case GL_LUMINANCE_ALPHA:
684       iInternalFormat = GL_LUMINANCE_ALPHA;
685       break;
686     default:
687       iInternalFormat = GL_RGBA8;
688       break;
689     }
690
691     glTexImage2D( GL_TEXTURE_2D, 
692                   0, 
693                   iInternalFormat, 
694                   iWidth, iHeight,
695                   0, 
696                   (GLenum) iFormat,
697                   GL_UNSIGNED_BYTE, 
698                   pData);
699   }
700   else
701   {
702     glTexSubImage2D(GL_TEXTURE_2D,
703                     0, 0, 0,
704                     iWidth, iHeight, 
705                     (GLenum) iFormat, 
706                     GL_UNSIGNED_BYTE, 
707                     pData);
708   }
709   // set default filtering.
710   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
711   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
712   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
713   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
714
715   return SKYRESULT_OK;
716 }
717
718
719 //------------------------------------------------------------------------------
720 // Function               : SkyTextureManager::_Create3DTextureObject
721 // Description      : 
722 //------------------------------------------------------------------------------
723 /**
724  * @fn SkyTextureManager::_Create3DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iDepth, unsigned int iFormat, unsigned char *pData)
725  * @brief Creates a 3D texture
726  * 
727  * Creates an OpenGL 3D texture object (or a set of 2D slices) and returns its ID and dimensions 
728  * in a SkyTexture structure.
729  */ 
730 SKYRESULT SkyTextureManager::_Create3DTextureObject(SkyTexture &texture,
731                                                     unsigned int iWidth, 
732                                                     unsigned int iHeight,
733                                                     unsigned int iDepth,
734                                                     unsigned int iFormat,
735                                                     unsigned char *pData)
736
737 /*  bool bNew = false;
738   if (s_bSlice3DTextures) // create one 2D texture per slice!
739   {
740     if (!texture.pSliceIDs)
741     {
742       texture.pSliceIDs = new unsigned int[iDepth];
743       glGenTextures(iDepth, texture.pSliceIDs);
744       bNew = true;
745     }
746   }
747   else if (!texture.iTextureID)
748   {
749     glGenTextures(1, &(texture.iTextureID));
750     bNew = true;
751   }
752    
753   texture.iWidth    = iWidth;
754   texture.iHeight   = iHeight;
755   texture.iDepth    = iDepth;
756   texture.bSliced3D = s_bSlice3DTextures;
757
758   if (!s_bSlice3DTextures)
759   {
760     glBindTexture(GL_TEXTURE_3D, texture.iTextureID);
761     
762     if (bNew)
763     {
764       unsigned int iInternalFormat;
765       switch (iFormat)
766       {
767       case GL_LUMINANCE:
768         iInternalFormat = GL_LUMINANCE;
769         break;
770       case GL_LUMINANCE_ALPHA:
771         iInternalFormat = GL_LUMINANCE_ALPHA;
772         break;
773       default:
774         iInternalFormat = GL_RGBA;
775         break;
776       }
777
778       glTexImage3D( GL_TEXTURE_3D, 
779                     0, 
780                     iInternalFormat, 
781                     iWidth, iHeight, iDepth,
782                     0, 
783                     iFormat,
784                     GL_UNSIGNED_BYTE, 
785                     pData);
786     }
787     else
788     {
789       glTexSubImage3D(GL_TEXTURE_3D,
790                       0, 0, 0, 0,
791                       iWidth, iHeight, iDepth,
792                       iFormat, 
793                       GL_UNSIGNED_BYTE, 
794                       pData);
795     }
796     // set default filtering.
797     glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
798     glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
799     glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
800     glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
801   }
802   else
803   {
804     unsigned int iInternalFormat = 0;
805     unsigned int iBytesPerPixel  = 0;
806     switch (iFormat)
807     {
808     case GL_LUMINANCE:
809       iInternalFormat = GL_LUMINANCE;
810       iBytesPerPixel  = 1;
811       break;
812     case GL_LUMINANCE_ALPHA:
813       iInternalFormat = GL_LUMINANCE_ALPHA;
814       iBytesPerPixel  = 2;
815       break;
816     case GL_RGBA:
817     default:
818       iInternalFormat = GL_RGBA;
819       iBytesPerPixel  = 4;
820       break;
821     }
822
823     unsigned int iSliceSize = iWidth * iHeight * iBytesPerPixel;
824
825     // create iDepth 2D texture slices...
826     for (unsigned int iSlice = 0; iSlice < iDepth; ++iSlice)
827     {
828       glBindTexture(GL_TEXTURE_2D, texture.pSliceIDs[iSlice]);
829
830       if (bNew)
831       {
832         glTexImage2D( GL_TEXTURE_2D, 
833                       0, 
834                       iInternalFormat, 
835                       iWidth, iHeight,
836                       0, 
837                       iFormat,
838                       GL_UNSIGNED_BYTE, 
839                       (pData + iSlice * iSliceSize));   
840       }
841       else
842       {
843         glTexSubImage2D(GL_TEXTURE_2D,
844                         0, 0, 0,
845                         iWidth, iHeight,
846                         iFormat, 
847                         GL_UNSIGNED_BYTE, 
848                         (pData + iSlice * iSliceSize));
849       }
850       // set default filtering.
851       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
852       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
853       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
854       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
855     }
856   } 
857   GLVU::CheckForGLError("SkyTextureManager::_Create3DTextureObject()");
858
859   return SKYRESULT_OK;*/
860   return SKYRESULT_FAIL;
861 }
862
863
864 //------------------------------------------------------------------------------
865 // Function               : SkyTextureManager::DestroyTextureObject
866 // Description      : 
867 //------------------------------------------------------------------------------
868 /**
869  * @fn SkyTextureManager::DestroyTextureObject(SkyTexture &texture)
870  * @brief destroys a SkyTexture object.
871  * 
872  * Deletes the data as well as the OpenGL texture ID(s).
873  */ 
874 void SkyTextureManager::DestroyTextureObject(SkyTexture &texture)
875 { /*
876   if (texture.GetID)
877     glDeleteTextures(1, &(texture.iTextureID));
878   if (texture.bSliced3D && texture.pSliceIDs)
879   {
880     glDeleteTextures(texture.iDepth, texture.pSliceIDs);
881     delete [] texture.pSliceIDs;
882   } */
883 }