GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_material.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 *****************************************************************************/
22 
24 
25 #include "glc_material.h"
26 #include "../geometry/glc_geometry.h"
27 #include "../glc_factory.h"
28 #include "../glc_openglexception.h"
29 
30 #include <QtDebug>
31 
32 // Class chunk id
33 quint32 GLC_Material::m_ChunkId= 0xA703;
34 
36 // Constructor Destructor
38 // Default constructor
40 :GLC_Object("Material")
41 , m_AmbientColor()
42 , m_DiffuseColor()
43 , m_SpecularColor()
44 , m_EmissiveColor()
45 , m_Shininess(50.0) // By default shininess 50
46 , m_WhereUsed()
47 , m_OtherUsage()
48 , m_pTexture(NULL) // no texture
49 , m_Opacity(1.0)
50 {
51  //qDebug() << "GLC_Material::GLC_Material" << id();
52  // Diffuse Color
54 
55  // Others
57 }
58 
59 GLC_Material::GLC_Material(const QColor &diffuseColor)
60 :GLC_Object("Material")
61 , m_AmbientColor()
62 , m_DiffuseColor(diffuseColor)
63 , m_SpecularColor()
64 , m_EmissiveColor()
65 , m_Shininess(50.0) // By default shininess 50
66 , m_WhereUsed()
67 , m_OtherUsage()
68 , m_pTexture(NULL) // no texture
69 , m_Opacity(1.0)
70 {
71  // Others
73 }
74 
75 
76 GLC_Material::GLC_Material(const QString& name ,const GLfloat *pDiffuseColor)
77 :GLC_Object(name)
78 , m_AmbientColor()
79 , m_DiffuseColor()
80 , m_SpecularColor()
81 , m_EmissiveColor()
82 , m_Shininess(50.0) // By default shininess 50
83 , m_WhereUsed()
84 , m_OtherUsage()
85 , m_pTexture(NULL) // no texture
86 , m_Opacity(1.0)
87 {
88  //qDebug() << "GLC_Material::GLC_Material" << id();
89  // Init Diffuse Color
90  if (pDiffuseColor != 0)
91  {
92  m_DiffuseColor.setRgbF(static_cast<qreal>(pDiffuseColor[0]),
93  static_cast<qreal>(pDiffuseColor[1]),
94  static_cast<qreal>(pDiffuseColor[2]),
95  static_cast<qreal>(pDiffuseColor[3]));
96  }
97  else
98  {
100  }
101  // Others
102  initOtherColor();
103 }
104 GLC_Material::GLC_Material(GLC_Texture* pTexture, const QString& name)
105 :GLC_Object(name)
106 , m_AmbientColor()
107 , m_DiffuseColor()
108 , m_SpecularColor()
109 , m_EmissiveColor()
110 , m_Shininess(50.0) // By default shininess 50
111 , m_WhereUsed()
112 , m_OtherUsage()
113 , m_pTexture(pTexture) // init texture
114 , m_Opacity(1.0)
115 {
116  Q_ASSERT(NULL != m_pTexture);
117  //qDebug() << "GLC_Material::GLC_Material" << id();
118 
119  // Diffuse Color
121 
122  // Others
123  initOtherColor();
124 
125  //if (m_pTexture->hasAlphaChannel()) m_Transparency= 0.99;
126 }
127 
128 // Copy constructor
130 :GLC_Object(InitMaterial)
131 , m_AmbientColor(InitMaterial.m_AmbientColor)
132 , m_DiffuseColor(InitMaterial.m_DiffuseColor)
133 , m_SpecularColor(InitMaterial.m_SpecularColor)
134 , m_EmissiveColor(InitMaterial.m_EmissiveColor)
135 , m_Shininess(InitMaterial.m_Shininess)
136 , m_WhereUsed()
137 , m_OtherUsage()
138 , m_pTexture(NULL)
139 , m_Opacity(InitMaterial.m_Opacity)
140 {
141  //qDebug() << "GLC_Material::GLC_Material copy constructor" << id();
142  if (NULL != InitMaterial.m_pTexture)
143  {
144  m_pTexture= new GLC_Texture(*(InitMaterial.m_pTexture));
145  Q_ASSERT(m_pTexture != NULL);
146  }
147 
148 }
149 
150 // Destructor
152 {
153  delete m_pTexture;
154 }
155 
156 
158 // Get Functions
160 // Return the class Chunk ID
162 {
163  return m_ChunkId;
164 }
165 
166 // Get Ambiant color
168 {
169  return m_AmbientColor;
170 }
171 
172 // Get diffuse color
174 {
175  return m_DiffuseColor;
176 }
177 
178 // Get specular color
180 {
181  return m_SpecularColor;
182 }
183 
184 // Get the emissive color
186 {
187  return m_EmissiveColor;
188 }
189 // Get the texture File Name
191 {
192  if (m_pTexture != NULL)
193  {
194  return m_pTexture->fileName();
195  }
196  else
197  {
198  return "";
199  }
200 }
201 
202 // Get Texture Id
204 {
205  if (m_pTexture != NULL)
206  {
207  return m_pTexture->GL_ID();
208  }
209  else
210  {
211  return 0;
212  }
213 
214 }
215 
216 // return true if the texture is loaded
218 {
219  if (m_pTexture != NULL)
220  {
221  return m_pTexture->isLoaded();
222  }
223  else
224  {
225  return false;
226  }
227 }
228 
229 // Return true if materials are equivalent
231 {
232  bool result;
233  if (this == &mat)
234  {
235  result= true;
236  }
237  else
238  {
239  result= m_AmbientColor == mat.m_AmbientColor;
240  result= result && (m_DiffuseColor == mat.m_DiffuseColor);
241  result= result && (m_SpecularColor == mat.m_SpecularColor);
242  result= result && (m_EmissiveColor == mat.m_EmissiveColor);
243  result= result && (m_Shininess == mat.m_Shininess);
244  if ((NULL != m_pTexture) && (NULL != mat.m_pTexture))
245  {
246  result= result && ((*m_pTexture) == (*mat.m_pTexture));
247  }
248  else
249  {
250  result= result && (m_pTexture == mat.m_pTexture);
251  }
252  result= result && (m_Opacity == mat.m_Opacity);
253  }
254  return result;
255 }
256 
257 // Return the material hash code
259 {
260  QString stringKey= QString::number(m_AmbientColor.rgba());
261  stringKey+= QString::number(m_DiffuseColor.rgba());
262  stringKey+= QString::number(m_SpecularColor.rgba());
263  stringKey+= QString::number(m_EmissiveColor.rgba());
264  stringKey+= QString::number(m_Shininess);
265  stringKey+= QString::number(m_Opacity);
266  if (NULL != m_pTexture)
267  {
268  stringKey+= m_pTexture->fileName();
269  }
270 
271  return qHash(stringKey);
272 }
273 
275 // Set Functions
277 // Set Material properties
279  {
280  if (NULL != pMat->m_pTexture)
281  {
282  GLC_Texture* pTexture= new GLC_Texture(*(pMat->m_pTexture));
283  setTexture(pTexture);
284  }
285  else if (NULL != m_pTexture)
286  {
287  qDebug() << "Delete texture";
288  delete m_pTexture;
289  m_pTexture= NULL;
290  }
291  // Ambient Color
293  // Diffuse Color
295  // Specular Color
297  // Lighting emit
299  // Shininess
300  m_Shininess= pMat->m_Shininess;
301  // Transparency
302  m_Opacity= pMat->m_Opacity;
303  // Update geometry which use this material
304  WhereUsed::const_iterator iGeom= m_WhereUsed.constBegin();
305  while (iGeom != m_WhereUsed.constEnd())
306  {
307  iGeom.value()->updateTransparentMaterialNumber();
308  ++iGeom;
309  }
310 
311  }
312 
313 // Set Ambiant Color
314 void GLC_Material::setAmbientColor(const QColor& ambientColor)
315 {
317  m_AmbientColor.setAlphaF(m_Opacity);
318 }
319 
320 // Set Diffuse color
321 void GLC_Material::setDiffuseColor(const QColor& diffuseColor)
322 {
324  m_DiffuseColor.setAlphaF(m_Opacity);
325 }
326 
327 // Set Specular color
328 void GLC_Material::setSpecularColor(const QColor& specularColor)
329 {
331  m_SpecularColor.setAlphaF(m_Opacity);
332 }
333 
334 // Set Emissive
335 void GLC_Material::setEmissiveColor(const QColor& lightEmission)
336 {
337  m_EmissiveColor= lightEmission;
338  m_EmissiveColor.setAlphaF(m_Opacity);
339 }
340 
341 // Set Texture
343 {
344  Q_ASSERT(NULL != pTexture);
345  //qDebug() << "GLC_Material::SetTexture";
346  if (m_pTexture != NULL)
347  {
348  delete m_pTexture;
349  m_pTexture= pTexture;
350  glLoadTexture();
351  }
352  else
353  {
354  // It is not sure that there is OpenGL context
355  m_pTexture= pTexture;
356  }
357 
358  //if (m_pTexture->hasAlphaChannel()) m_Transparency= 0.99;
359 }
360 
361 // remove Material Texture
363 {
364  if (m_pTexture != NULL)
365  {
366  delete m_pTexture;
367  m_pTexture= NULL;
368  }
369 }
370 
371 // Add Geometry to where used hash table
373 {
374  QMutexLocker mutexLocker(&m_Mutex);
375  //qDebug() << "GLC_Material::addGLC_Geom" << pGeom->id();
376  WhereUsed::iterator iGeom= m_WhereUsed.find(pGeom->id());
377 
378  if (iGeom == m_WhereUsed.end())
379  { // Ok, ID doesn't exist
380  // Add Geometry to where used hash table
381  m_WhereUsed.insert(pGeom->id(), pGeom);
382  return true;
383  }
384  else
385  { // KO, ID exist
386  qDebug("GLC_Material::addGLC_Geom : Geometry not added");
387  return false;
388  }
389 }
390 
391 // Remove a geometry from the collection
393 {
394  QMutexLocker mutexLocker(&m_Mutex);
395 
396  if (m_WhereUsed.contains(Key))
397  { // Ok, ID exist
398  m_WhereUsed.remove(Key); // Remove container
399 
400  return true;
401  }
402  else
403  { // KO doesn't exist
404  qDebug("GLC_Material::delGLC_Geom : Geometry not remove");
405  return false;
406  }
407 
408 }
409 // Add the id to the other used Set
411 {
412  QMutexLocker mutexLocker(&m_Mutex);
413  if (!m_OtherUsage.contains(id))
414  {
415  m_OtherUsage << id;
416  return true;
417  }
418  else
419  {
420  qDebug("GLC_Material::addUsage : id not added");
421  return false;
422  }
423 }
424 
425 // Remove the id to the other used Set
427 {
428  QMutexLocker mutexLocker(&m_Mutex);
429  if (m_OtherUsage.contains(id))
430  {
431  m_OtherUsage.remove(id);
432  return true;
433  }
434  else
435  {
436  qDebug() << "GLC_Material::delUsage : id not removed " << m_Uid;
437  return false;
438  }
439 }
440 
441 
442 // Set the material opacity
443 void GLC_Material::setOpacity(const qreal alpha)
444 {
445  m_Opacity= alpha;
446  m_AmbientColor.setAlphaF(m_Opacity);
447  m_DiffuseColor.setAlphaF(m_Opacity);
448  m_SpecularColor.setAlphaF(m_Opacity);
449  m_EmissiveColor.setAlphaF(m_Opacity);
450  // Update geometry which use this material
451  WhereUsed::const_iterator iGeom= m_WhereUsed.constBegin();
452  while (iGeom != m_WhereUsed.constEnd())
453  {
454  iGeom.value()->updateTransparentMaterialNumber();
455  ++iGeom;
456  }
457 }
458 
460 // OpenGL Functions
462 
463 // Load the texture
464 void GLC_Material::glLoadTexture(QGLContext* pContext)
465 {
466  if (m_pTexture != NULL)
467  {
468  m_pTexture->glLoadTexture(pContext);
469  }
470  else
471  {
472  qDebug() << "GLC_Material::glLoadTexture : Material without texture !";
473  }
474 }
475 
476 // Execute OpenGL Material
478 {
479 
480  GLfloat pAmbientColor[4]= {ambientColor().redF(),
481  ambientColor().greenF(),
482  ambientColor().blueF(),
483  ambientColor().alphaF()};
484 
485  GLfloat pDiffuseColor[4]= {diffuseColor().redF(),
486  diffuseColor().greenF(),
487  diffuseColor().blueF(),
488  diffuseColor().alphaF()};
489 
490  GLfloat pSpecularColor[4]= {specularColor().redF(),
491  specularColor().greenF(),
492  specularColor().blueF(),
493  specularColor().alphaF()};
494 
495  GLfloat pLightEmission[4]= {emissiveColor().redF(),
496  emissiveColor().greenF(),
497  emissiveColor().blueF(),
498  emissiveColor().alphaF()};
499 
500  const bool textureIsEnable= glIsEnabled(GL_TEXTURE_2D);
501  if (m_pTexture != NULL)
502  {
503  if (!textureIsEnable) glEnable(GL_TEXTURE_2D);
505  if (GLC_State::glslUsed())
506  {
508  {
509  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
510  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", true);
511  }
512  }
513 
514  }
515  else
516  {
517 
519  {
520  if (!textureIsEnable) glEnable(GL_TEXTURE_2D);
521  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
522  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", false);
523  }
524  else
525  {
526  if (textureIsEnable) glDisable(GL_TEXTURE_2D);
527  }
528 
529  }
530 
531  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pAmbientColor);
532  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pDiffuseColor);
533  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pSpecularColor);
534  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, pLightEmission);
535  glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &m_Shininess);
536 
537  glColor4fv(pDiffuseColor);
538 
539 
540  // OpenGL Error handler
541  GLenum error= glGetError();
542  if (error != GL_NO_ERROR)
543  {
544  GLC_OpenGlException OpenGlException("GLC_Material::glExecute() ", error);
545  throw(OpenGlException);
546  }
547 
548 }
549 
550 // Execute OpenGL Material
551 void GLC_Material::glExecute(float overwriteTransparency)
552 {
553  GLfloat pAmbientColor[4]= {ambientColor().redF(),
554  ambientColor().greenF(),
555  ambientColor().blueF(),
556  overwriteTransparency};
557 
558  GLfloat pDiffuseColor[4]= {diffuseColor().redF(),
559  diffuseColor().greenF(),
560  diffuseColor().blueF(),
561  overwriteTransparency};
562 
563  GLfloat pSpecularColor[4]= {specularColor().redF(),
564  specularColor().greenF(),
565  specularColor().blueF(),
566  overwriteTransparency};
567 
568  GLfloat pLightEmission[4]= {emissiveColor().redF(),
569  emissiveColor().greenF(),
570  emissiveColor().blueF(),
571  overwriteTransparency};
572 
573  const bool textureIsEnable= glIsEnabled(GL_TEXTURE_2D);
574 
575  if (m_pTexture != NULL)
576  {
577  if (!textureIsEnable) glEnable(GL_TEXTURE_2D);
579  if (GLC_State::glslUsed())
580  {
582  {
583  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
584  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", true);
585  }
586  }
587  }
588  else
589  {
590  if (textureIsEnable) glDisable(GL_TEXTURE_2D);
591  if (GLC_State::glslUsed())
592  {
594  {
595  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("tex", GLint(0));
596  GLC_Shader::currentShaderHandle()->programShaderHandle()->setUniformValue("useTexture", false);
597  }
598  }
599  }
600 
601  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pAmbientColor);
602  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pDiffuseColor);
603  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pSpecularColor);
604  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, pLightEmission);
605  glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &m_Shininess);
606 
607  glColor4fv(pDiffuseColor);
608 
609  // OpenGL Error handler
610  GLenum error= glGetError();
611  if (error != GL_NO_ERROR)
612  {
613  GLC_OpenGlException OpenGlException("GLC_Material::glExecute(float overwriteTransparency) ", error);
614  throw(OpenGlException);
615  }
616 }
617 
619 // Private servicies Functions
621 
622 // Init Ambiant Color
624 {
625  m_DiffuseColor.setRgbF(1.0, 1.0, 1.0, 1.0);
626 }
627 
628 // Init default color
630 {
631  //Ambiant Color
632  m_AmbientColor.setRgbF(0.8, 0.8, 0.8, 1.0);
633 
634  // Specular Color
635  m_SpecularColor.setRgbF(0.5, 0.5, 0.5, 1.0);
636 
637  // Lighting emit
638  m_EmissiveColor.setRgbF(0.0, 0.0, 0.0, 1.0);
639 }
640 
641 // Non Member methods
642 // Non-member stream operator
643 QDataStream &operator<<(QDataStream &stream, const GLC_Material &material)
644 {
645  quint32 chunckId= GLC_Material::m_ChunkId;
646  stream << chunckId;
647 
648  // Store GLC_Object class members
649  stream << material.id() << material.name();
650 
651  // Store GLC_Material class members
652  stream << material.ambientColor() << material.diffuseColor() << material.specularColor();
653  stream << material.emissiveColor() << material.shininess() << material.opacity();
654 
655  // Test if the material has texture
656  bool hasTexture= material.hasTexture();
657  stream << hasTexture;
658  if (hasTexture)
659  {
660  GLC_Texture texture(*(material.textureHandle()));
661  stream << texture;
662  }
663 
664  return stream;
665 }
666 QDataStream &operator>>(QDataStream &stream, GLC_Material &material)
667 {
668  quint32 chunckId;
669  stream >> chunckId;
670 
671  Q_ASSERT(chunckId == GLC_Material::m_ChunkId);
672 
673  // Retrieve GLC_Object members
674  GLC_uint id;
675  QString name;
676  stream >> id >> name;
677  material.setId(id);
678  material.setName(name);
679 
680  // Retrieve GLC_Material members
681  QColor ambient, diffuse, specular, lightEmission;
682  float shininess;
683  double alpha;
684  stream >> ambient >> diffuse >> specular >> lightEmission;
685  stream >> shininess >> alpha;
686  material.setAmbientColor(ambient);
687  material.setDiffuseColor(diffuse);
688  material.setSpecularColor(specular);
689  material.setEmissiveColor(lightEmission);
690  material.setShininess(shininess);
691  material.setOpacity(alpha);
692 
693  // Test if material has texture
694  bool hasTexture;
695  stream >> hasTexture;
696  if (hasTexture)
697  {
698  GLC_Texture texture;
699  stream >> texture;
700  material.setTexture(new GLC_Texture(texture));
701  }
702  return stream;
703 }

©2005-2013 Laurent Ribon