glc_material.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  http://glc-lib.sourceforge.net
00006 
00007  GLC-lib is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU Lesser General Public License as published by
00009  the Free Software Foundation; either version 3 of the License, or
00010  (at your option) any later version.
00011 
00012  GLC-lib is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU Lesser General Public License for more details.
00016 
00017  You should have received a copy of the GNU Lesser General Public License
00018  along with GLC-lib; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 *****************************************************************************/
00022 
00024 
00025 #include "glc_material.h"
00026 #include "../geometry/glc_geometry.h"
00027 #include "../glc_factory.h"
00028 
00029 #include <QtDebug>
00030 
00031 // Class chunk id
00032 quint32 GLC_Material::m_ChunkId= 0xA703;
00033 
00035 // Constructor Destructor
00037 // Default constructor
00038 GLC_Material::GLC_Material()
00039 :GLC_Object("Material")
00040 , m_AmbientColor()
00041 , m_DiffuseColor()
00042 , m_SpecularColor()
00043 , m_EmissiveColor()
00044 , m_Shininess(50.0)             // By default shininess 50
00045 , m_WhereUsed()
00046 , m_OtherUsage()
00047 , m_pTexture(NULL)                      // no texture
00048 , m_Opacity(1.0)
00049 {
00050         //qDebug() << "GLC_Material::GLC_Material" << id();
00051         // Diffuse Color
00052         initDiffuseColor();
00053 
00054         // Others
00055         initOtherColor();
00056 }
00057 
00058 GLC_Material::GLC_Material(const QColor &diffuseColor)
00059 :GLC_Object("Material")
00060 , m_AmbientColor()
00061 , m_DiffuseColor(diffuseColor)
00062 , m_SpecularColor()
00063 , m_EmissiveColor()
00064 , m_Shininess(50.0)             // By default shininess 50
00065 , m_WhereUsed()
00066 , m_OtherUsage()
00067 , m_pTexture(NULL)                      // no texture
00068 , m_Opacity(1.0)
00069 {
00070         // Others
00071         initOtherColor();
00072 }
00073 
00074 
00075 GLC_Material::GLC_Material(const QString& name ,const GLfloat *pDiffuseColor)
00076 :GLC_Object(name)
00077 , m_AmbientColor()
00078 , m_DiffuseColor()
00079 , m_SpecularColor()
00080 , m_EmissiveColor()
00081 , m_Shininess(50.0)             // By default shininess 50
00082 , m_WhereUsed()
00083 , m_OtherUsage()
00084 , m_pTexture(NULL)                      // no texture
00085 , m_Opacity(1.0)
00086 {
00087         //qDebug() << "GLC_Material::GLC_Material" << id();
00088         // Init Diffuse Color
00089         if (pDiffuseColor != 0)
00090         {
00091                 m_DiffuseColor.setRgbF(static_cast<qreal>(pDiffuseColor[0]),
00092                                                                 static_cast<qreal>(pDiffuseColor[1]),
00093                                                                 static_cast<qreal>(pDiffuseColor[2]),
00094                                                                 static_cast<qreal>(pDiffuseColor[3]));
00095         }
00096         else
00097         {
00098                 initDiffuseColor();
00099         }
00100         // Others
00101         initOtherColor();
00102 }
00103 GLC_Material::GLC_Material(GLC_Texture* pTexture, const QString& name)
00104 :GLC_Object(name)
00105 , m_AmbientColor()
00106 , m_DiffuseColor()
00107 , m_SpecularColor()
00108 , m_EmissiveColor()
00109 , m_Shininess(50.0)             // By default shininess 50
00110 , m_WhereUsed()
00111 , m_OtherUsage()
00112 , m_pTexture(pTexture)                  // init texture
00113 , m_Opacity(1.0)
00114 {
00115         Q_ASSERT(NULL != m_pTexture);
00116         //qDebug() << "GLC_Material::GLC_Material" << id();
00117 
00118         // Diffuse Color
00119         initDiffuseColor();
00120 
00121         // Others
00122         initOtherColor();
00123 
00124         //if (m_pTexture->hasAlphaChannel()) m_Transparency= 0.99;
00125 }
00126 
00127 // Copy constructor
00128 GLC_Material::GLC_Material(const GLC_Material &InitMaterial)
00129 :GLC_Object(InitMaterial)
00130 , m_AmbientColor(InitMaterial.m_AmbientColor)
00131 , m_DiffuseColor(InitMaterial.m_DiffuseColor)
00132 , m_SpecularColor(InitMaterial.m_SpecularColor)
00133 , m_EmissiveColor(InitMaterial.m_EmissiveColor)
00134 , m_Shininess(InitMaterial.m_Shininess)
00135 , m_WhereUsed()
00136 , m_OtherUsage()
00137 , m_pTexture(NULL)
00138 , m_Opacity(InitMaterial.m_Opacity)
00139 {
00140         //qDebug() << "GLC_Material::GLC_Material copy constructor" << id();
00141         if (NULL != InitMaterial.m_pTexture)
00142         {
00143                 m_pTexture= new GLC_Texture(*(InitMaterial.m_pTexture));
00144                 Q_ASSERT(m_pTexture != NULL);
00145         }
00146 
00147 }
00148 
00149 // Destructor
00150 GLC_Material::~GLC_Material(void)
00151 {
00152         delete m_pTexture;
00153 }
00154 
00155 
00157 // Get Functions
00159 // Return the class Chunk ID
00160 quint32 GLC_Material::chunckID()
00161 {
00162         return m_ChunkId;
00163 }
00164 
00165 // Get Ambiant color
00166 QColor GLC_Material::ambientColor() const
00167 {
00168         return m_AmbientColor;
00169 }
00170 
00171 // Get diffuse color
00172 QColor GLC_Material::diffuseColor() const
00173 {
00174         return m_DiffuseColor;
00175 }
00176 
00177 // Get specular color
00178 QColor GLC_Material::specularColor() const
00179 {
00180         return m_SpecularColor;
00181 }
00182 
00183 // Get the emissive color
00184 QColor GLC_Material::emissiveColor() const
00185 {
00186         return m_EmissiveColor;
00187 }
00188 // Get the texture File Name
00189 QString GLC_Material::textureFileName() const
00190 {
00191         if (m_pTexture != NULL)
00192         {
00193                 return m_pTexture->fileName();
00194         }
00195         else
00196         {
00197                 return "";
00198         }
00199 }
00200 
00201 // Get Texture Id
00202 GLuint GLC_Material::textureID() const
00203 {
00204         if (m_pTexture != NULL)
00205         {
00206                 return m_pTexture->GL_ID();
00207         }
00208         else
00209         {
00210                 return 0;
00211         }
00212 
00213 }
00214 
00215 // return true if the texture is loaded
00216 bool GLC_Material::textureIsLoaded() const
00217 {
00218         if (m_pTexture != NULL)
00219         {
00220                 return m_pTexture->isLoaded();
00221         }
00222         else
00223         {
00224                 return false;
00225         }
00226 }
00227 
00228 // Return true if materials are equivalent
00229 bool GLC_Material::operator==(const GLC_Material& mat) const
00230 {
00231         bool result;
00232         if (this == &mat)
00233         {
00234                 result= true;
00235         }
00236         else
00237         {
00238                 result= m_AmbientColor == mat.m_AmbientColor;
00239                 result= result && (m_DiffuseColor == mat.m_DiffuseColor);
00240                 result= result && (m_SpecularColor == mat.m_SpecularColor);
00241                 result= result && (m_EmissiveColor == mat.m_EmissiveColor);
00242                 result= result && (m_Shininess == mat.m_Shininess);
00243                 if ((NULL != m_pTexture) && (NULL != mat.m_pTexture))
00244                 {
00245                         result= result && ((*m_pTexture) == (*mat.m_pTexture));
00246                 }
00247                 else
00248                 {
00249                         result= result && (m_pTexture == mat.m_pTexture);
00250                 }
00251                 result= result && (m_Opacity == mat.m_Opacity);
00252         }
00253         return result;
00254 }
00255 
00256 // Return the material hash code
00257 uint GLC_Material::hashCode() const
00258 {
00259         QString stringKey= QString::number(m_AmbientColor.rgba());
00260         stringKey+= QString::number(m_DiffuseColor.rgba());
00261         stringKey+= QString::number(m_SpecularColor.rgba());
00262         stringKey+= QString::number(m_EmissiveColor.rgba());
00263         stringKey+= QString::number(m_Shininess);
00264         stringKey+= QString::number(m_Opacity);
00265         if (NULL != m_pTexture)
00266         {
00267                 stringKey+= m_pTexture->fileName();
00268         }
00269 
00270         return qHash(stringKey);
00271 }
00272 
00274 // Set Functions
00276 // Set Material properties
00277  void GLC_Material::setMaterial(const GLC_Material* pMat)
00278  {
00279         if (NULL != pMat->m_pTexture)
00280         {
00281                 GLC_Texture* pTexture= new GLC_Texture(*(pMat->m_pTexture));
00282                 setTexture(pTexture);
00283         }
00284         else if (NULL != m_pTexture)
00285         {
00286                 qDebug() << "Delete texture";
00287                 delete m_pTexture;
00288                 m_pTexture= NULL;
00289         }
00290         // Ambient Color
00291         m_AmbientColor= pMat->m_AmbientColor;
00292         // Diffuse Color
00293         m_DiffuseColor= pMat->m_DiffuseColor;
00294         // Specular Color
00295         m_SpecularColor= pMat->m_SpecularColor;
00296         // Lighting emit
00297         m_EmissiveColor= pMat->m_EmissiveColor;
00298         // Shininess
00299         m_Shininess= pMat->m_Shininess;
00300         // Transparency
00301         m_Opacity= pMat->m_Opacity;
00302         // Update geometry which use this material
00303         WhereUsed::const_iterator iGeom= m_WhereUsed.constBegin();
00304         while (iGeom != m_WhereUsed.constEnd())
00305         {
00306                 iGeom.value()->updateTransparentMaterialNumber();
00307                 ++iGeom;
00308         }
00309 
00310  }
00311 
00312 // Set Ambiant Color
00313 void GLC_Material::setAmbientColor(const QColor& ambientColor)
00314 {
00315         m_AmbientColor= ambientColor;
00316         m_AmbientColor.setAlphaF(m_Opacity);
00317 }
00318 
00319 // Set Diffuse color
00320 void GLC_Material::setDiffuseColor(const QColor& diffuseColor)
00321 {
00322         m_DiffuseColor= diffuseColor;
00323         m_DiffuseColor.setAlphaF(m_Opacity);
00324 }
00325 
00326 // Set Specular color
00327 void GLC_Material::setSpecularColor(const QColor& specularColor)
00328 {
00329         m_SpecularColor= specularColor;
00330         m_SpecularColor.setAlphaF(m_Opacity);
00331 }
00332 
00333 // Set Emissive
00334 void GLC_Material::setEmissiveColor(const QColor& lightEmission)
00335 {
00336         m_EmissiveColor= lightEmission;
00337         m_EmissiveColor.setAlphaF(m_Opacity);
00338 }
00339 
00340 // Set Texture
00341 void GLC_Material::setTexture(GLC_Texture* pTexture)
00342 {
00343         Q_ASSERT(NULL != pTexture);
00344         //qDebug() << "GLC_Material::SetTexture";
00345         if (m_pTexture != NULL)
00346         {
00347                 delete m_pTexture;
00348                 m_pTexture= pTexture;
00349                 glLoadTexture();
00350         }
00351         else
00352         {
00353                 // It is not sure that there is OpenGL context
00354                 m_pTexture= pTexture;
00355         }
00356 
00357         //if (m_pTexture->hasAlphaChannel()) m_Transparency= 0.99;
00358 }
00359 
00360 // remove Material Texture
00361 void GLC_Material::removeTexture()
00362 {
00363         if (m_pTexture != NULL)
00364         {
00365                 delete m_pTexture;
00366                 m_pTexture= NULL;
00367         }
00368 }
00369 
00370 // Add Geometry to where used hash table
00371 bool GLC_Material::addGLC_Geom(GLC_Geometry* pGeom)
00372 {
00373         QMutexLocker mutexLocker(&m_Mutex);
00374         //qDebug() << "GLC_Material::addGLC_Geom" << pGeom->id();
00375         WhereUsed::iterator iGeom= m_WhereUsed.find(pGeom->id());
00376 
00377         if (iGeom == m_WhereUsed.end())
00378         {       // Ok, ID doesn't exist
00379                 // Add Geometry to where used hash table
00380                 m_WhereUsed.insert(pGeom->id(), pGeom);
00381                 return true;
00382         }
00383         else
00384         {       // KO, ID exist
00385                 qDebug("GLC_Material::addGLC_Geom : Geometry not added");
00386                 return false;
00387         }
00388 }
00389 
00390 // Remove a geometry from the collection
00391 bool GLC_Material::delGLC_Geom(GLC_uint Key)
00392 {
00393         QMutexLocker mutexLocker(&m_Mutex);
00394 
00395         if (m_WhereUsed.contains(Key))
00396         {       // Ok, ID exist
00397                 m_WhereUsed.remove(Key);        // Remove container
00398 
00399                 return true;
00400         }
00401         else
00402         {       // KO doesn't exist
00403                 qDebug("GLC_Material::delGLC_Geom : Geometry not remove");
00404                 return false;
00405         }
00406 
00407 }
00408 // Add the id to the other used Set
00409 bool GLC_Material::addUsage(GLC_uint id)
00410 {
00411         QMutexLocker mutexLocker(&m_Mutex);
00412         if (!m_OtherUsage.contains(id))
00413         {
00414                 m_OtherUsage << id;
00415                 return true;
00416         }
00417         else
00418         {
00419                 qDebug("GLC_Material::addUsage : id not added");
00420                 return false;
00421         }
00422 }
00423 
00424 // Remove the id to the other used Set
00425 bool GLC_Material::delUsage(GLC_uint id)
00426 {
00427         QMutexLocker mutexLocker(&m_Mutex);
00428         if (m_OtherUsage.contains(id))
00429         {
00430                 m_OtherUsage.remove(id);
00431                 return true;
00432         }
00433         else
00434         {
00435                 qDebug() << "GLC_Material::delUsage : id not removed " << m_Uid;
00436                 return false;
00437         }
00438 }
00439 
00440 
00441 // Set the material opacity
00442 void GLC_Material::setOpacity(const qreal alpha)
00443 {
00444         m_Opacity= alpha;
00445         m_AmbientColor.setAlphaF(m_Opacity);
00446         m_DiffuseColor.setAlphaF(m_Opacity);
00447         m_SpecularColor.setAlphaF(m_Opacity);
00448         m_EmissiveColor.setAlphaF(m_Opacity);
00449         // Update geometry which use this material
00450         WhereUsed::const_iterator iGeom= m_WhereUsed.constBegin();
00451         while (iGeom != m_WhereUsed.constEnd())
00452         {
00453                 iGeom.value()->updateTransparentMaterialNumber();
00454                 ++iGeom;
00455         }
00456 }
00457 
00459 // OpenGL Functions
00461 
00462 // Load the texture
00463 void GLC_Material::glLoadTexture(QGLContext* pContext)
00464 {
00465         if (m_pTexture != NULL)
00466         {
00467                 m_pTexture->glLoadTexture(pContext);
00468         }
00469         else
00470         {
00471                 qDebug() << "GLC_Material::glLoadTexture : Material without texture !";
00472         }
00473 }
00474 
00475 // Execute OpenGL Material
00476 void GLC_Material::glExecute()
00477 {
00478 
00479         GLfloat pAmbientColor[4]= {ambientColor().redF(),
00480                                                                 ambientColor().greenF(),
00481                                                                 ambientColor().blueF(),
00482                                                                 ambientColor().alphaF()};
00483 
00484         GLfloat pDiffuseColor[4]= {diffuseColor().redF(),
00485                                                                 diffuseColor().greenF(),
00486                                                                 diffuseColor().blueF(),
00487                                                                 diffuseColor().alphaF()};
00488 
00489         GLfloat pSpecularColor[4]= {specularColor().redF(),
00490                                                                 specularColor().greenF(),
00491                                                                 specularColor().blueF(),
00492                                                                 specularColor().alphaF()};
00493 
00494         GLfloat pLightEmission[4]= {emissiveColor().redF(),
00495                                                                 emissiveColor().greenF(),
00496                                                                 emissiveColor().blueF(),
00497                                                                 emissiveColor().alphaF()};
00498 
00499         if (m_pTexture != NULL)
00500         {
00501                 glEnable(GL_TEXTURE_2D);
00502                 m_pTexture->glcBindTexture();
00503                 if (GLC_State::glslUsed())
00504                 {
00505                         if (GLC_Shader::hasActiveShader())
00506                         {
00507                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
00508                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", true);
00509                         }
00510                 }
00511 
00512         }
00513         else
00514         {
00515 
00516                 if (GLC_State::glslUsed() && GLC_Shader::hasActiveShader())
00517                 {
00518                                 glEnable(GL_TEXTURE_2D);
00519                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
00520                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", false);
00521                 }
00522                 else
00523                 {
00524                         glDisable(GL_TEXTURE_2D);
00525                 }
00526 
00527         }
00528 
00529         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pAmbientColor);
00530         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pDiffuseColor);
00531         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pSpecularColor);
00532         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, pLightEmission);
00533         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &m_Shininess);
00534 
00535         glColor4fv(pDiffuseColor);
00536 
00537         // OpenGL Error handler
00538         GLenum errCode;
00539         if ((errCode= glGetError()) != GL_NO_ERROR)
00540         {
00541                 const GLubyte* errString;
00542                 errString = gluErrorString(errCode);
00543                 qDebug("GLC_Material::GlExecute OpenGL Error %s", errString);
00544         }
00545 }
00546 
00547 // Execute OpenGL Material
00548 void GLC_Material::glExecute(float overwriteTransparency)
00549 {
00550         GLfloat pAmbientColor[4]= {ambientColor().redF(),
00551                                                                 ambientColor().greenF(),
00552                                                                 ambientColor().blueF(),
00553                                                                 overwriteTransparency};
00554 
00555         GLfloat pDiffuseColor[4]= {diffuseColor().redF(),
00556                                                                 diffuseColor().greenF(),
00557                                                                 diffuseColor().blueF(),
00558                                                                 overwriteTransparency};
00559 
00560         GLfloat pSpecularColor[4]= {specularColor().redF(),
00561                                                                 specularColor().greenF(),
00562                                                                 specularColor().blueF(),
00563                                                                 overwriteTransparency};
00564 
00565         GLfloat pLightEmission[4]= {emissiveColor().redF(),
00566                                                                 emissiveColor().greenF(),
00567                                                                 emissiveColor().blueF(),
00568                                                                 overwriteTransparency};
00569 
00570         if (m_pTexture != NULL)
00571         {
00572                 glEnable(GL_TEXTURE_2D);
00573                 m_pTexture->glcBindTexture();
00574                 if (GLC_State::glslUsed())
00575                 {
00576                         if (GLC_Shader::hasActiveShader())
00577                         {
00578                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
00579                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", true);
00580                         }
00581                 }
00582         }
00583         else
00584         {
00585                 glDisable(GL_TEXTURE_2D);
00586                 if (GLC_State::glslUsed())
00587                 {
00588                         if (GLC_Shader::hasActiveShader())
00589                         {
00590                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
00591                                 GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", false);
00592                         }
00593                 }
00594         }
00595 
00596         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pAmbientColor);
00597         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pDiffuseColor);
00598         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pSpecularColor);
00599         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, pLightEmission);
00600         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &m_Shininess);
00601 
00602         glColor4fv(pDiffuseColor);
00603 
00604         // OpenGL Error handler
00605         GLenum errCode;
00606         if ((errCode= glGetError()) != GL_NO_ERROR)
00607         {
00608                 const GLubyte* errString;
00609                 errString = gluErrorString(errCode);
00610                 qDebug("GLC_Material::glExecute(float) OpenGL Error %s", errString);
00611         }
00612 }
00613 
00615 // Private servicies Functions
00617 
00618 // Init Ambiant Color
00619 void GLC_Material::initDiffuseColor(void)
00620 {
00621         m_DiffuseColor.setRgbF(1.0, 1.0, 1.0, 1.0);
00622 }
00623 
00624 // Init default color
00625 void GLC_Material::initOtherColor(void)
00626 {
00627         //Ambiant Color
00628         m_AmbientColor.setRgbF(0.8, 0.8, 0.8, 1.0);
00629 
00630         // Specular Color
00631         m_SpecularColor.setRgbF(0.5, 0.5, 0.5, 1.0);
00632 
00633         // Lighting emit
00634         m_EmissiveColor.setRgbF(0.0, 0.0, 0.0, 1.0);
00635 }
00636 
00637 // Non Member methods
00638 // Non-member stream operator
00639 QDataStream &operator<<(QDataStream &stream, const GLC_Material &material)
00640 {
00641         quint32 chunckId= GLC_Material::m_ChunkId;
00642         stream << chunckId;
00643 
00644         // Store GLC_Object class members
00645         stream << material.id() << material.name();
00646 
00647         // Store GLC_Material class members
00648         stream << material.ambientColor() << material.diffuseColor() << material.specularColor();
00649         stream << material.emissiveColor() << material.shininess() << material.opacity();
00650 
00651         // Test if the material has texture
00652         bool hasTexture= material.hasTexture();
00653         stream << hasTexture;
00654         if (hasTexture)
00655         {
00656                 GLC_Texture texture(*(material.textureHandle()));
00657                 stream << texture;
00658         }
00659 
00660         return stream;
00661 }
00662 QDataStream &operator>>(QDataStream &stream, GLC_Material &material)
00663 {
00664         quint32 chunckId;
00665         stream >> chunckId;
00666 
00667         Q_ASSERT(chunckId == GLC_Material::m_ChunkId);
00668 
00669         // Retrieve GLC_Object members
00670         GLC_uint id;
00671         QString name;
00672         stream >> id >> name;
00673         material.setId(id);
00674         material.setName(name);
00675 
00676         // Retrieve GLC_Material members
00677         QColor ambient, diffuse, specular, lightEmission;
00678         float shininess;
00679         double alpha;
00680         stream >> ambient >> diffuse >> specular >> lightEmission;
00681         stream >> shininess >> alpha;
00682         material.setAmbientColor(ambient);
00683         material.setDiffuseColor(diffuse);
00684         material.setSpecularColor(specular);
00685         material.setEmissiveColor(lightEmission);
00686         material.setShininess(shininess);
00687         material.setOpacity(alpha);
00688 
00689         // Test if material has texture
00690         bool hasTexture;
00691         stream >> hasTexture;
00692         if (hasTexture)
00693         {
00694                 GLC_Texture texture;
00695                 stream >> texture;
00696                 material.setTexture(new GLC_Texture(texture));
00697         }
00698         return stream;
00699 }

SourceForge.net Logo

©2005-2011 Laurent Ribon