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