]> git.mxchange.org Git - simgear.git/commitdiff
Add mipmap control in the effect file
authorFrederic Bouvier <fredfgfs01@free.fr>
Sun, 10 Oct 2010 14:51:37 +0000 (16:51 +0200)
committerFrederic Bouvier <fredfgfs01@free.fr>
Sun, 24 Oct 2010 07:25:40 +0000 (09:25 +0200)
projects/VC90/SimGear.vcproj
simgear/scene/material/TextureBuilder.cxx
simgear/scene/material/mipmap.cxx [new file with mode: 0644]
simgear/scene/material/mipmap.hxx [new file with mode: 0644]

index cdfeb22265fbb2dea1c9c3e7e21446c906240b06..fca9e9938a5701b7577e07ac8f173547523250dd 100644 (file)
                                RelativePath="..\..\simgear\scene\material\matmodel.hxx"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\simgear\scene\material\mipmap.cxx"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\simgear\scene\material\mipmap.hxx"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\simgear\scene\material\Noise.cxx"\r
                                >\r
index 3773754b561761393c83cfc9d5f37ba9316be277..61b62dfec78221d92dd16fb6ce4426c1c18d3b82 100644 (file)
@@ -19,6 +19,7 @@
 #endif
 
 #include "TextureBuilder.hxx"
+#include "mipmap.hxx"
 
 #include "Pass.hxx"
 
@@ -67,7 +68,7 @@ osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
 
 typedef boost::tuple<string, Texture::FilterMode, Texture::FilterMode,
                      Texture::WrapMode, Texture::WrapMode, Texture::WrapMode,
-                     string> TexTuple;
+                     string, MipMapTuple> TexTuple;
 
 EffectNameValue<TexEnv::Mode> texEnvModesInit[] =
 {
@@ -134,7 +135,7 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
     catch (BuilderException& ) {
         SG_LOG(SG_INPUT, SG_ALERT, "No image file, "
             << "maybe the reader did not set the filename attribute, "
-            << "using white for type '" << type << "' on '" << pass->getName() << "', in " << prop->getPath() );
+            << "using white on " << pass->getName());
         texture = StateAttributeFactory::instance()->getWhiteTexture();
     }
     pass->setTextureAttributeAndModes(unit, texture);
@@ -181,7 +182,6 @@ EffectNameValue<Texture::WrapMode> wrapModesInit[] =
 };
 EffectPropertyMap<Texture::WrapMode> wrapModes(wrapModesInit);
 
-
 TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
                       const SGReaderWriterXMLOptions* options,
                       const string& texType)
@@ -214,8 +214,15 @@ TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
     if (pImage)
         imageName = pImage->getStringValue();
     string absFileName = osgDB::findDataFile(imageName, options);
+
+    const SGPropertyNode* pMipmapControl
+        = getEffectPropertyChild(effect, props, "mipmap-control");
+    MipMapTuple mipmapFunctions( AUTOMATIC, AUTOMATIC, AUTOMATIC, AUTOMATIC ); 
+    if ( pMipmapControl )
+        mipmapFunctions = makeMipMapTuple(effect, pMipmapControl, options);
+
     return TexTuple(absFileName, minFilter, magFilter, sWrap, tWrap, rWrap,
-                    texType);
+                    texType, mipmapFunctions);
 }
 
 void setAttrs(const TexTuple& attrs, Texture* tex,
@@ -228,7 +235,8 @@ void setAttrs(const TexTuple& attrs, Texture* tex,
         osgDB::ReaderWriter::ReadResult result
             = osgDB::Registry::instance()->readImage(imageName, options);
         if (result.success()) {
-            osg::Image* image = result.getImage();
+            osg::ref_ptr<osg::Image> image = result.getImage();
+            image = computeMipmap( image, attrs.get<7>() );
             tex->setImage(GL_FRONT_AND_BACK, image);
             int s = image->s();
             int t = image->t();
diff --git a/simgear/scene/material/mipmap.cxx b/simgear/scene/material/mipmap.cxx
new file mode 100644 (file)
index 0000000..b7ba9a7
--- /dev/null
@@ -0,0 +1,356 @@
+// Copyright (C) 2010  Frederic Bouvier\r
+//\r
+// This library is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU Library General Public\r
+// License as published by the Free Software Foundation; either\r
+// version 2 of the License, or (at your option) any later version.\r
+//\r
+// This library is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+// Library General Public License for more details.\r
+//\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software\r
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+\r
+#ifdef HAVE_CONFIG_H\r
+#  include <simgear_config.h>\r
+#endif\r
+\r
+#include "mipmap.hxx"\r
+#include "EffectBuilder.hxx"\r
+\r
+#include <limits>\r
+\r
+#include <osg/Image>\r
+#include <osg/Vec4>\r
+\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/tuple/tuple_comparison.hpp>\r
+\r
+namespace simgear { namespace effect {\r
+\r
+EffectNameValue<MipMapFunction> mipmapFunctionsInit[] =\r
+{\r
+    {"auto", AUTOMATIC},\r
+    {"average", AVERAGE},\r
+    {"sum", SUM},\r
+    {"product", PRODUCT},\r
+    {"min", MIN},\r
+    {"max", MAX}\r
+};\r
+EffectPropertyMap<MipMapFunction> mipmapFunctions(mipmapFunctionsInit);\r
+\r
+MipMapTuple makeMipMapTuple(Effect* effect, const SGPropertyNode* props,\r
+                      const SGReaderWriterXMLOptions* options)\r
+{\r
+    const SGPropertyNode* pMipmapR\r
+        = getEffectPropertyChild(effect, props, "function-r");\r
+    MipMapFunction mipmapR = AUTOMATIC;\r
+    if (pMipmapR)\r
+        findAttr(mipmapFunctions, pMipmapR, mipmapR);\r
+    const SGPropertyNode* pMipmapG\r
+        = getEffectPropertyChild(effect, props, "function-g");\r
+    MipMapFunction mipmapG = AUTOMATIC;\r
+    if (pMipmapG)\r
+        findAttr(mipmapFunctions, pMipmapG, mipmapG);\r
+    const SGPropertyNode* pMipmapB\r
+        = getEffectPropertyChild(effect, props, "function-b");\r
+    MipMapFunction mipmapB = AUTOMATIC;\r
+    if (pMipmapB)\r
+        findAttr(mipmapFunctions, pMipmapB, mipmapB);\r
+    const SGPropertyNode* pMipmapA\r
+        = getEffectPropertyChild(effect, props, "function-a");\r
+    MipMapFunction mipmapA = AUTOMATIC;\r
+    if (pMipmapA)\r
+        findAttr(mipmapFunctions, pMipmapA, mipmapA);\r
+    return MipMapTuple( mipmapR, mipmapG, mipmapB, mipmapA );\r
+}\r
+\r
+\r
+unsigned char* imageData(unsigned char* ptr, GLenum pixelFormat, GLenum dataType, int width, int height, int packing, int column, int row=0, int image=0)\r
+{\r
+    if (!ptr) return NULL;\r
+    return ptr +\r
+        ( column * osg::Image::computePixelSizeInBits( pixelFormat, dataType ) ) / 8 +\r
+        row * osg::Image::computeRowWidthInBytes( width, pixelFormat, dataType, packing ) +\r
+        image * height * osg::Image::computeRowWidthInBytes( width, pixelFormat, dataType, packing );\r
+}\r
+\r
+template <typename T>\r
+void _writeColor(GLenum pixelFormat, T* data, float scale, osg::Vec4 value)\r
+{\r
+    switch(pixelFormat)\r
+    {\r
+        case(GL_DEPTH_COMPONENT):   //intentionally fall through and execute the code for GL_LUMINANCE\r
+        case(GL_LUMINANCE):         { *data++ = value.r()*scale; break; }\r
+        case(GL_ALPHA):             { *data++ = value.a()*scale; break; }\r
+        case(GL_LUMINANCE_ALPHA):   { *data++ = value.r()*scale; *data++ = value.a()*scale; break; }\r
+        case(GL_RGB):               { *data++ = value.r()*scale; *data++ = value.g()*scale; *data++ = value.b()*scale; break; }\r
+        case(GL_RGBA):              { *data++ = value.r()*scale; *data++ = value.g()*scale; *data++ = value.b()*scale; *data++ = value.a()*scale; break; }\r
+        case(GL_BGR):               { *data++ = value.b()*scale; *data++ = value.g()*scale; *data++ = value.r()*scale; break; }\r
+        case(GL_BGRA):              { *data++ = value.b()*scale; *data++ = value.g()*scale; *data++ = value.r()*scale; *data++ = value.a()*scale; break; }\r
+    }\r
+}\r
+\r
+void setColor(unsigned char *ptr, GLenum pixelFormat, GLenum dataType, osg::Vec4 color)\r
+{\r
+    switch(dataType)\r
+    {\r
+        case(GL_BYTE):              return _writeColor(pixelFormat, (char*)ptr,             128.0f, color);\r
+        case(GL_UNSIGNED_BYTE):     return _writeColor(pixelFormat, (unsigned char*)ptr,    255.0f, color);\r
+        case(GL_SHORT):             return _writeColor(pixelFormat, (short*)ptr,            32768.0f, color);\r
+        case(GL_UNSIGNED_SHORT):    return _writeColor(pixelFormat, (unsigned short*)ptr,   65535.0f, color);\r
+        case(GL_INT):               return _writeColor(pixelFormat, (int*)ptr,              2147483648.0f, color);\r
+        case(GL_UNSIGNED_INT):      return _writeColor(pixelFormat, (unsigned int*)ptr,     4294967295.0f, color);\r
+        case(GL_FLOAT):             return _writeColor(pixelFormat, (float*)ptr,            1.0f, color);\r
+    }\r
+}\r
+\r
+template <typename T>    \r
+osg::Vec4 _readColor(GLenum pixelFormat, T* data,float scale)\r
+{\r
+    switch(pixelFormat)\r
+    {\r
+        case(GL_DEPTH_COMPONENT):   //intentionally fall through and execute the code for GL_LUMINANCE\r
+        case(GL_LUMINANCE):         { float l = float(*data++)*scale; return osg::Vec4(l, l, l, 1.0f); }\r
+        case(GL_ALPHA):             { float a = float(*data++)*scale; return osg::Vec4(1.0f, 1.0f, 1.0f, a); }\r
+        case(GL_LUMINANCE_ALPHA):   { float l = float(*data++)*scale; float a = float(*data++)*scale; return osg::Vec4(l,l,l,a); }\r
+        case(GL_RGB):               { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; return osg::Vec4(r,g,b,1.0f); }\r
+        case(GL_RGBA):              { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; float a = float(*data++)*scale; return osg::Vec4(r,g,b,a); }\r
+        case(GL_BGR):               { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; return osg::Vec4(r,g,b,1.0f); }\r
+        case(GL_BGRA):              { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; float a = float(*data++)*scale; return osg::Vec4(r,g,b,a); }\r
+    }\r
+    return osg::Vec4(1.0f,1.0f,1.0f,1.0f);\r
+}\r
+\r
+osg::Vec4 getColor(const unsigned char* ptr, GLenum pixelFormat, GLenum dataType)\r
+{\r
+    switch(dataType)\r
+    {\r
+        case(GL_BYTE):              return _readColor(pixelFormat, (char*)ptr,             1.0f/128.0f);\r
+        case(GL_UNSIGNED_BYTE):     return _readColor(pixelFormat, (unsigned char*)ptr,    1.0f/255.0f);\r
+        case(GL_SHORT):             return _readColor(pixelFormat, (short*)ptr,            1.0f/32768.0f);\r
+        case(GL_UNSIGNED_SHORT):    return _readColor(pixelFormat, (unsigned short*)ptr,   1.0f/65535.0f);\r
+        case(GL_INT):               return _readColor(pixelFormat, (int*)ptr,              1.0f/2147483648.0f);\r
+        case(GL_UNSIGNED_INT):      return _readColor(pixelFormat, (unsigned int*)ptr,     1.0f/4294967295.0f);\r
+        case(GL_FLOAT):             return _readColor(pixelFormat, (float*)ptr,            1.0f);\r
+    }\r
+    return osg::Vec4(1.0f,1.0f,1.0f,1.0f);\r
+}\r
+\r
+osg::Vec4::value_type computeAverage( int c, osg::Vec4 colors[2][2][2], bool colorValid[2][2][2] )\r
+{\r
+    osg::Vec4::value_type r = 0;\r
+    osg::Vec4::value_type nb = 0;\r
+    for ( int k = 0; k < 2; ++k ) for ( int j = 0; j < 2; ++j ) for ( int i = 0; i < 2; ++i )\r
+    {\r
+        if ( colorValid[i][j][k] )\r
+        {\r
+            r += colors[i][j][k][c];\r
+            nb += 1;\r
+        }\r
+    }\r
+    return r / nb;\r
+}\r
+\r
+osg::Vec4::value_type computeSum( int c, osg::Vec4 colors[2][2][2], bool colorValid[2][2][2] )\r
+{\r
+    osg::Vec4::value_type r = 0;\r
+    for ( int k = 0; k < 2; ++k ) for ( int j = 0; j < 2; ++j ) for ( int i = 0; i < 2; ++i )\r
+        if ( colorValid[i][j][k] )\r
+        {\r
+            r += colors[i][j][k][c];\r
+        }\r
+    return r;\r
+}\r
+\r
+osg::Vec4::value_type computeProduct( int c, osg::Vec4 colors[2][2][2], bool colorValid[2][2][2] )\r
+{\r
+    osg::Vec4::value_type r = 1;\r
+    for ( int k = 0; k < 2; ++k ) for ( int j = 0; j < 2; ++j ) for ( int i = 0; i < 2; ++i )\r
+        if ( colorValid[i][j][k] )\r
+        {\r
+            r *= colors[i][j][k][c];\r
+        }\r
+    return r;\r
+}\r
+\r
+osg::Vec4::value_type computeMin( int c, osg::Vec4 colors[2][2][2], bool colorValid[2][2][2] )\r
+{\r
+    osg::Vec4::value_type r = std::numeric_limits<osg::Vec4::value_type>::max();\r
+    for ( int k = 0; k < 2; ++k ) for ( int j = 0; j < 2; ++j ) for ( int i = 0; i < 2; ++i )\r
+        if ( colorValid[i][j][k] )\r
+        {\r
+            r = std::min( r, colors[i][j][k][c] );\r
+        }\r
+    return r;\r
+}\r
+\r
+osg::Vec4::value_type computeMax( int c, osg::Vec4 colors[2][2][2], bool colorValid[2][2][2] )\r
+{\r
+    osg::Vec4::value_type r = std::numeric_limits<osg::Vec4::value_type>::min();\r
+    for ( int k = 0; k < 2; ++k ) for ( int j = 0; j < 2; ++j ) for ( int i = 0; i < 2; ++i )\r
+        if ( colorValid[i][j][k] )\r
+        {\r
+            r = std::max( r, colors[i][j][k][c] );\r
+        }\r
+    return r;\r
+}\r
+\r
+osg::Vec4::value_type computeComponent( int c, osg::Vec4 colors[2][2][2], bool colorValid[2][2][2], MipMapFunction f )\r
+{\r
+    switch ( f )\r
+    {\r
+    case AVERAGE: return computeAverage( c, colors, colorValid );\r
+    case SUM: return computeSum( c, colors, colorValid );\r
+    case PRODUCT: return computeProduct( c, colors, colorValid );\r
+    case MIN: return computeMin( c, colors, colorValid );\r
+    case MAX: return computeMax( c, colors, colorValid );\r
+    }\r
+    return 0;\r
+}\r
+\r
+osg::Vec4 computeColor( osg::Vec4 colors[2][2][2], bool colorValid[2][2][2], MipMapTuple attrs )\r
+{\r
+    osg::Vec4 result;\r
+    result[0] = computeComponent( 0, colors, colorValid, attrs.get<0>() );\r
+    result[1] = computeComponent( 1, colors, colorValid, attrs.get<1>() );\r
+    result[2] = computeComponent( 2, colors, colorValid, attrs.get<2>() );\r
+    result[3] = computeComponent( 3, colors, colorValid, attrs.get<3>() );\r
+    return result;\r
+}\r
+\r
+osg::Image* computeMipmap( osg::Image* image, MipMapTuple attrs )\r
+{\r
+    bool computeMipmap = false;\r
+    if ( attrs.get<0>() != AUTOMATIC &&\r
+        attrs.get<1>() != AUTOMATIC &&\r
+        attrs.get<2>() != AUTOMATIC &&\r
+        attrs.get<3>() != AUTOMATIC )\r
+    {\r
+        computeMipmap = true;\r
+    }\r
+    else if ( attrs.get<0>() != AUTOMATIC ||\r
+        attrs.get<1>() != AUTOMATIC ||\r
+        attrs.get<2>() != AUTOMATIC ||\r
+        attrs.get<3>() != AUTOMATIC )\r
+    {\r
+        throw BuilderException("invalid mipmap control function combination");\r
+    }\r
+\r
+    if ( computeMipmap )\r
+    {\r
+        osg::ref_ptr<osg::Image> mipmaps = new osg::Image();\r
+        int s = image->s(),\r
+            t = image->t(),\r
+            r = image->r();\r
+        int nb = osg::Image::computeNumberOfMipmapLevels(s, t, r);\r
+        osg::Image::MipmapDataType mipmapOffsets;\r
+        unsigned int offset = 0;\r
+        for ( int i = 0; i < nb; ++i )\r
+        {\r
+            offset += t * r * osg::Image::computeRowWidthInBytes(s, image->getPixelFormat(), image->getDataType(), image->getPacking());\r
+            mipmapOffsets.push_back( offset );\r
+            s >>= 1; if ( s == 0 ) s = 1;\r
+            t >>= 1; if ( t == 0 ) t = 1;\r
+            r >>= 1; if ( r == 0 ) r = 1;\r
+        }\r
+        mipmapOffsets.pop_back();\r
+        unsigned char *data = new unsigned char[offset];\r
+        memcpy( data, image->data(), mipmapOffsets.front() );\r
+        s = image->s();\r
+        t = image->t();\r
+        r = image->r();\r
+        for ( int m = 0; m < nb-1; ++m )\r
+        {\r
+            unsigned char *src = data;\r
+            if ( m > 0 )\r
+                src += mipmapOffsets[m-1];\r
+\r
+            unsigned char *dest = data + mipmapOffsets[m];\r
+\r
+            int ns = s >> 1; if ( ns == 0 ) ns = 1;\r
+            int nt = t >> 1; if ( nt == 0 ) nt = 1;\r
+            int nr = r >> 1; if ( nr == 0 ) nr = 1;\r
+\r
+            for ( int k = 0; k < r; k += 2 )\r
+            {\r
+                for ( int j = 0; j < t; j += 2 )\r
+                {\r
+                    for ( int i = 0; i < s; i += 2 )\r
+                    {\r
+                        osg::Vec4 colors[2][2][2];\r
+                        bool colorValid[2][2][2];\r
+                        colorValid[0][0][0] = false; colorValid[0][0][1] = false; colorValid[0][1][0] = false; colorValid[0][1][1] = false;\r
+                        colorValid[1][0][0] = false; colorValid[1][0][1] = false; colorValid[1][1][0] = false; colorValid[1][1][1] = false;\r
+                        if ( true )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i, j, k );\r
+                            colors[0][0][0] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[0][0][0] = true;\r
+                        }\r
+                        if ( i + 1 < s )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i + 1, j, k );\r
+                            colors[0][0][1] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[0][0][1] = true;\r
+                        }\r
+                        if ( j + 1 < t )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i, j + 1, k );\r
+                            colors[0][1][0] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[0][1][0] = true;\r
+                        }\r
+                        if ( i + 1 < s && j + 1 < t )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i + 1, j + 1, k );\r
+                            colors[0][1][1] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[0][1][1] = true;\r
+                        }\r
+                        if ( k + 1 < r )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i, j, k + 1 );\r
+                            colors[1][0][0] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[1][0][0] = true;\r
+                        }\r
+                        if ( i + 1 < s && k + 1 < r )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i + 1, j, k + 1 );\r
+                            colors[1][0][1] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[1][0][1] = true;\r
+                        }\r
+                        if ( j + 1 < t && k + 1 < r )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i, j + 1, k + 1 );\r
+                            colors[1][1][0] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[1][1][0] = true;\r
+                        }\r
+                        if ( i + 1 < s && j + 1 < t && k + 1 < r )\r
+                        {\r
+                            unsigned char *ptr = imageData( src, image->getPixelFormat(), image->getDataType(), s, t, image->getPacking(), i + 1, j + 1, k + 1 );\r
+                            colors[1][1][1] = getColor( ptr, image->getPixelFormat(), image->getDataType() );\r
+                            colorValid[1][1][1] = true;\r
+                        }\r
+\r
+                        unsigned char *ptr = imageData( dest, image->getPixelFormat(), image->getDataType(), ns, nt, image->getPacking(), i/2, j/2, k/2 );\r
+                        osg::Vec4 color = computeColor( colors, colorValid, attrs );\r
+                        setColor( ptr, image->getPixelFormat(), image->getDataType(), color );\r
+                    }\r
+                }\r
+            }\r
+            s = ns;\r
+            t = nt;\r
+            r = nr;\r
+        }\r
+        mipmaps->setImage( image->s(), image->t(), image->r(), \r
+            image->getInternalTextureFormat(), image->getPixelFormat(),\r
+            image->getDataType(), data, osg::Image::USE_NEW_DELETE, image->getPacking() );\r
+        mipmaps->setMipmapLevels( mipmapOffsets );\r
+\r
+        return mipmaps.release();\r
+    }\r
+    return image;\r
+}\r
+} }\r
diff --git a/simgear/scene/material/mipmap.hxx b/simgear/scene/material/mipmap.hxx
new file mode 100644 (file)
index 0000000..d0fdcbb
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2010  Frederic Bouvier\r
+//\r
+// This library is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU Library General Public\r
+// License as published by the Free Software Foundation; either\r
+// version 2 of the License, or (at your option) any later version.\r
+//\r
+// This library is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+// Library General Public License for more details.\r
+//\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software\r
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+\r
+#ifndef SIMGEAR_MIPMAP_HXX\r
+#define SIMGEAR_MIPMAP_HXX 1\r
+\r
+#include <boost/tuple/tuple.hpp>\r
+\r
+class SGPropertyNode;\r
+\r
+namespace osg {\r
+    class Image;\r
+}\r
+\r
+namespace simgear\r
+{\r
+class Effect;\r
+class SGReaderWriterXMLOptions;\r
+\r
+namespace effect {\r
+enum MipMapFunction {\r
+    AUTOMATIC,\r
+    AVERAGE,\r
+    SUM,\r
+    PRODUCT,\r
+    MIN,\r
+    MAX\r
+};\r
+\r
+typedef boost::tuple<MipMapFunction, MipMapFunction, MipMapFunction, MipMapFunction> MipMapTuple;\r
+\r
+MipMapTuple makeMipMapTuple(Effect* effect, const SGPropertyNode* props,\r
+                      const SGReaderWriterXMLOptions* options);\r
+osg::Image* computeMipmap( osg::Image* image, MipMapTuple attrs );\r
+} }\r
+\r
+#endif\r