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

SourceForge.net Logo

©2005-2010 Laurent Ribon