1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : Material_Model.cxx
21 // Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com)
24 #include "Material_Model.h"
25 #include "Material_ResourceMgr.h"
27 #include <GEOM_Constants.h>
29 #include <QtxResourceMgr.h>
30 #include <SUIT_ResourceMgr.h>
31 #include <SUIT_Session.h>
34 #include <Graphic3d_AspectFillArea3d.hxx>
37 #include <vtkProperty.h>
42 Create new SALOME material model with default properties.
44 Material_Model::Material_Model()
53 Material_Model::~Material_Model()
58 \brief Construct material model according to the given list of
61 \param theProps the list of material properties
62 \return material model object with correspondent properties
63 \sa getMaterialProperty()
65 Material_Model* Material_Model::getMaterialModel( QStringList theProps )
67 Material_Model* aModel = new Material_Model();
69 foreach ( QString aProp, theProps ) {
70 if ( aProp.isNull() ) continue;
72 // Set current ambient color
73 aModel->setColor( aProp, "AmbientColor=", Material_Model::Ambient );
74 // Set current ambient coefficient
75 aModel->setCoefficient( aProp, "AmbientCoefficient=", Material_Model::Ambient );
77 // Set current diffuse color
78 aModel->setColor( aProp, "DiffuseColor=", Material_Model::Diffuse );
79 // Set current diffuse coefficient
80 aModel->setCoefficient( aProp, "DiffuseCoefficient=", Material_Model::Diffuse );
82 // Set current specular color
83 aModel->setColor( aProp, "SpecularColor=", Material_Model::Specular );
84 // Set current specular coefficient
85 aModel->setCoefficient( aProp, "SpecularCoefficient=", Material_Model::Specular );
87 // Set current emission color
88 aModel->setColor( aProp, "EmissionColor=", Material_Model::Emission );
89 // Set current emission coefficient
90 aModel->setCoefficient( aProp, "EmissionCoefficient=", Material_Model::Emission );
92 // Set current shininess
93 QString aPropName = "Shininess=";
94 int anId = aProp.indexOf(aPropName);
97 double aCoef = aProp.right( aProp.length() - (anId+aPropName.length()) ).toDouble(&ok);
99 aModel->setShininess( aCoef );
107 \brief Construct string of material properties for this model object
109 \return a string representing a set of material properties
110 \sa getMaterialModel()
112 QString Material_Model::getMaterialProperty()
114 // Parse material properties of the current model and form a string for persistent purpose
117 bool isReflectionTypeActive;
121 // Ambient reflection
122 isReflectionTypeActive = hasAmbientReflection();
123 if ( isReflectionTypeActive ) {
124 c = color( Material_Model::Ambient );
125 coef = coefficient(Material_Model::Ambient);
126 // Insert properties into persistent string
127 aMaterial = "AmbientColor=%1%2AmbientCoefficient=%3";
128 aMaterial = aMaterial.arg( Qtx::colorToString(c) );
129 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
130 aMaterial = aMaterial.arg( coef );
132 // Diffuse reflection
133 isReflectionTypeActive = hasDiffuseReflection();
134 if ( isReflectionTypeActive ) {
135 c = color( Material_Model::Diffuse );
136 coef = coefficient(Material_Model::Diffuse);
137 // Insert properties into persistent string
138 aMaterial += "%1DiffuseColor=%2%3DiffuseCoefficient=%4";
139 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
140 aMaterial = aMaterial.arg( Qtx::colorToString(c) );
141 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
142 aMaterial = aMaterial.arg( coef );
144 // Specular reflection
145 isReflectionTypeActive = hasSpecularReflection();
146 if ( isReflectionTypeActive ) {
147 c = color( Material_Model::Specular );
148 coef = coefficient(Material_Model::Specular);
149 // Insert properties into persistent string
150 aMaterial += "%1SpecularColor=%2%3SpecularCoefficient=%4";
151 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
152 aMaterial = aMaterial.arg( Qtx::colorToString(c) );
153 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
154 aMaterial = aMaterial.arg( coef );
156 // Emission reflection
157 isReflectionTypeActive = hasEmissionReflection();
158 if ( isReflectionTypeActive ) {
159 c = color( Material_Model::Emission );
160 coef = coefficient(Material_Model::Emission);
161 // Insert properties into persistent string
162 aMaterial += "%1EmissionColor=%2%3EmissionCoefficient=%4";
163 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
164 aMaterial = aMaterial.arg( Qtx::colorToString(c) );
165 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
166 aMaterial = aMaterial.arg( coef );
168 if ( !aMaterial.isEmpty() ) {
170 // Insert properties into persistent string
171 aMaterial += "%1Shininess=%2";
172 aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
173 aMaterial = aMaterial.arg( shininess() );
180 \brief Construct OCCT material aspect object based on the current model
182 \return material aspect object with correspondent properties
184 Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect()
186 // Get material aspect from the current model
187 Graphic3d_MaterialAspect aMat;
189 bool isReflectionTypeActive;
193 // Ambient reflection
194 isReflectionTypeActive = hasAmbientReflection();
195 if ( isReflectionTypeActive ) {
196 aMat.SetReflectionModeOn( Graphic3d_TOR_AMBIENT );
197 c = color( Material_Model::Ambient );
198 aMat.SetAmbientColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
199 coef = coefficient( Material_Model::Ambient );
200 aMat.SetAmbient( coef );
202 // Diffuse reflection
203 isReflectionTypeActive = hasDiffuseReflection();
204 if ( isReflectionTypeActive ) {
205 aMat.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE );
206 c = color( Material_Model::Diffuse );
207 aMat.SetDiffuseColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
208 coef = coefficient( Material_Model::Diffuse );
209 aMat.SetDiffuse( coef );
211 // Specular reflection
212 isReflectionTypeActive = hasSpecularReflection();
213 if ( isReflectionTypeActive ) {
214 aMat.SetReflectionModeOn( Graphic3d_TOR_SPECULAR );
215 c = color( Material_Model::Specular );
216 aMat.SetSpecularColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
217 coef = coefficient( Material_Model::Specular );
218 aMat.SetSpecular( coef );
220 // Emission reflection
221 isReflectionTypeActive = hasEmissionReflection();
222 if ( isReflectionTypeActive ) {
223 aMat.SetReflectionModeOn( Graphic3d_TOR_EMISSION );
224 c = color( Material_Model::Emission );
225 aMat.SetEmissiveColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
226 coef = coefficient( Material_Model::Emission );
227 aMat.SetEmissive( coef );
230 aMat.SetShininess( shininess() );
236 \brief Construct VTK property with properties of material based on the current model
238 \return VTK property with correspondent material properties
240 vtkProperty* Material_Model::getMaterialVTKProperty()
242 // Get material properties from the current model
243 vtkProperty* aProperty = vtkProperty::New();
245 bool isReflectionTypeActive;
249 // Ambient reflection
250 isReflectionTypeActive = hasAmbientReflection();
251 if ( isReflectionTypeActive ) {
252 c = color( Material_Model::Ambient );
253 aProperty->SetAmbientColor( c.redF(), c.greenF(), c.blueF() ); //SalomeApp_Tools::color( c )
254 coef = coefficient( Material_Model::Ambient );
255 aProperty->SetAmbient( coef );
257 // Diffuse reflection
258 isReflectionTypeActive = hasDiffuseReflection();
259 if ( isReflectionTypeActive ) {
260 c = color( Material_Model::Diffuse );
261 aProperty->SetDiffuseColor( c.redF(), c.greenF(), c.blueF() );
262 coef = coefficient( Material_Model::Diffuse );
263 aProperty->SetDiffuse( coef );
265 // Specular reflection
266 isReflectionTypeActive = hasSpecularReflection();
267 if ( isReflectionTypeActive ) {
268 c = color( Material_Model::Specular );
269 aProperty->SetSpecularColor( c.redF(), c.greenF(), c.blueF() );
270 coef = coefficient( Material_Model::Specular );
271 aProperty->SetSpecular( coef );
274 aProperty->SetSpecularPower( shininess()*100.0 );
280 \brief Initialize material model with default values
282 void Material_Model::initDefaults()
284 // Set default ambient color
285 setColor( Ambient, "#333333" );
286 // Set default ambient coefficient
287 setCoefficient( Ambient, 0.3 );
289 // Set default diffuse color
290 setColor( Diffuse, "#000000" );
291 // Set default diffuse coefficient
292 setCoefficient( Diffuse, 0.65 );
294 // Set default specular color
295 setColor( Specular, "#ffffff" );
296 // Set default specular coefficient
297 setCoefficient( Specular, 0.0 );
299 // Set default shininess
300 setShininess( 0.039 );
304 \brief Clear current content of this material model
306 void Material_Model::clearModel()
309 myCoefficients.clear();
314 \brief Initialize material model from the resources
316 This function can be used to retrieve material properties from the resource file(s).
317 Note, that paremeters \a theResMgr and \a theResSection are stored by the model to be used
318 later with save() method.
320 \param theResMgr resources manager
321 \param theResSection resources section name
322 \param theIsFront if True, it is front material, else it is back material
325 void Material_Model::fromResources( QtxResourceMgr* theResMgr,
326 const QString& theResSection,
329 // Clear current content of the model
330 // before setting properties from resources
333 myResourceMgr = theResMgr;
334 myResourceSection = theResSection;
336 // init from resource manager
337 if ( !resourceMgr() )
340 if ( theResSection.compare( "Geometry" ) == 0 ) {
342 myResourceSection = theResMgr->stringValue("Geometry", "front_material", "Gold");
345 myResourceSection = theResMgr->stringValue("Geometry", "back_material", "");
346 if ( myResourceSection.isEmpty() )
347 myResourceSection = theResMgr->stringValue("Geometry", "front_material", "Gold");
350 myResourceMgr = new Material_ResourceMgr();
353 QString section = resourceSection( theIsFront );
355 // If there is no material preference in XML files,
356 // use the default material hardcoded in material model
357 if ( section.isEmpty() ) {
363 if ( resourceMgr()->hasValue( section, "ambient-color" ) ) {
364 setColor( Ambient, resourceMgr()->colorValue( section, "ambient-color" ) );
366 // Set ambient coefficient
367 if ( resourceMgr()->hasValue( section, "ambient-coefficient" ) ) {
368 setCoefficient( Ambient, resourceMgr()->doubleValue( section, "ambient-coefficient" ) );
372 if ( resourceMgr()->hasValue( section, "diffuse-color" ) ) {
373 setColor( Diffuse, resourceMgr()->colorValue( section, "diffuse-color" ) );
375 // Set diffuse coefficient
376 if ( resourceMgr()->hasValue( section, "diffuse-coefficient" ) ) {
377 setCoefficient( Diffuse, resourceMgr()->doubleValue( section, "diffuse-coefficient" ) );
380 // Set specular color
381 if ( resourceMgr()->hasValue( section, "specular-color" ) ) {
382 setColor( Specular, resourceMgr()->colorValue( section, "specular-color" ) );
384 // Set specular coefficient
385 if ( resourceMgr()->hasValue( section, "specular-coefficient" ) ) {
386 setCoefficient( Specular, resourceMgr()->doubleValue( section, "specular-coefficient" ) );
389 // Set emission color
390 if ( resourceMgr()->hasValue( section, "emission-color" ) ) {
391 setColor( Emission, resourceMgr()->colorValue( section, "emission-color" ) );
393 // Set emission coefficient
394 if ( resourceMgr()->hasValue( section, "emission-coefficient" ) ) {
395 setCoefficient( Emission, resourceMgr()->doubleValue( section, "emission-coefficient" ) );
399 if ( resourceMgr()->hasValue( section, "shininess" ) ) {
400 setShininess( resourceMgr()->doubleValue( section, "shininess" ) );
405 \brief Save material properties to the resource file.
407 If paremeters \a theResMgr and \a theResSection are not specified, default ones
408 (those passed to the fromResources() function) are used instead.
410 \param theResMgr resources manager
411 \param theResSection resources section name
412 \param theIsFront if True, it is front material, else it is back material
415 void Material_Model::save( QtxResourceMgr* theResMgr,
416 const QString& theResSection,
420 theResMgr = resourceMgr();
424 QString section = theResSection.isEmpty() ? resourceSection( theIsFront ) : theResSection;
425 myResourceSection = section;
427 if ( hasAmbientReflection() ) {
428 // Save ambient color
429 theResMgr->setValue( section, "ambient-color", color( Ambient ) );
430 // Save ambient coefficient
431 theResMgr->setValue( section, "ambient-coefficient", coefficient( Ambient ) );
434 // Remove ambient color
435 theResMgr->remove( section, "ambient-color" );
436 // Remove ambient coefficient
437 theResMgr->remove( section, "ambient-coefficient" );
440 if ( hasDiffuseReflection() ) {
441 // Save diffuse color
442 theResMgr->setValue( section, "diffuse-color", color( Diffuse ) );
443 // Save diffuse coefficient
444 theResMgr->setValue( section, "diffuse-coefficient", coefficient( Diffuse ) );
447 // Remove diffuse color
448 theResMgr->remove( section, "diffuse-color" );
449 // Remove diffuse coefficient
450 theResMgr->remove( section, "diffuse-coefficient" );
453 if ( hasSpecularReflection() ) {
454 // Save specular color
455 theResMgr->setValue( section, "specular-color", color( Specular ) );
456 // Save specular coefficient
457 theResMgr->setValue( section, "specular-coefficient", coefficient( Specular ) );
460 // Remove specular color
461 theResMgr->remove( section, "specular-color" );
462 // Remove specular coefficient
463 theResMgr->remove( section, "specular-coefficient" );
466 if ( hasEmissionReflection() ) {
467 // Save emission color
468 theResMgr->setValue( section, "emission-color", color( Emission ) );
469 // Save emission coefficient
470 theResMgr->setValue( section, "emission-coefficient", coefficient( Emission ) );
473 // Remove emission color
474 theResMgr->remove( section, "emission-color" );
475 // Remove emission coefficient
476 theResMgr->remove( section, "emission-coefficient" );
480 theResMgr->setValue( section, "shininess", shininess() );
484 \brief Get resource manager used by this material model.
486 \return pointer to the resource manager passed previously to the fromResources() method
487 \sa fromResources(), resourceSection()
489 QtxResourceMgr* Material_Model::resourceMgr() const
491 return myResourceMgr;
495 \brief Get resources section name
497 If section name is empty, default material name from "Geometry" section
498 is returned ("front_material" or "back_material" is used depending on
501 \param theIsFront the flag indicating that section of front or back material
503 \return resource section name passed previously to the fromResources() method
504 \sa fromResources(), resourceMgr()
506 QString Material_Model::resourceSection( bool theIsFront ) const
508 return !myResourceSection.isEmpty() ? myResourceSection :
509 SUIT_Session::session()->resourceMgr()->stringValue("Geometry",
510 ( theIsFront ? "front_material" : "back_material" ),
515 \brief Check if ambient reflection type is defined for this material
517 \return true if ambient reflection type is defined for this material,
520 bool Material_Model::hasAmbientReflection()
522 return ( !myColors.isEmpty() && myColors.contains(Ambient) || !myCoefficients.isEmpty() && myCoefficients.contains(Ambient) );
526 \brief Check if diffuse reflection type is defined for this material
528 \return true if diffuse reflection type is defined for this material,
531 bool Material_Model::hasDiffuseReflection()
533 return ( !myColors.isEmpty() && myColors.contains(Diffuse) || !myCoefficients.isEmpty() && myCoefficients.contains(Diffuse) );
537 \brief Check if specular reflection type is defined for this material
539 \return true if specular reflection type is defined for this material,
542 bool Material_Model::hasSpecularReflection()
544 return ( !myColors.isEmpty() && myColors.contains(Specular) || !myCoefficients.isEmpty() && myCoefficients.contains(Specular) );
548 \brief Check if emission reflection type is defined for this material
550 \return true if emission reflection type is defined for this material,
553 bool Material_Model::hasEmissionReflection()
555 return ( !myColors.isEmpty() && myColors.contains(Emission) || !myCoefficients.isEmpty() && myCoefficients.contains(Emission) );
559 \brief Get color value for the given reflection type
560 \param theReflectionType reflection type
561 \return a color which should be used by the given reflection type
564 QColor Material_Model::color( ReflectionType theReflectionType ) const
566 return myColors[ theReflectionType ];
570 \brief Set color value for the given reflection type
572 \param theReflectionType reflection type
573 \param theColor a color to be used by the given reflection type
576 void Material_Model::setColor( ReflectionType theReflectionType,
577 const QColor& theColor )
579 myColors[ theReflectionType ] = theColor;
583 \brief Set color of the current material from the given string
584 \param theProp the considered property
585 \param theColorName the name of the color property
586 \param theReflectionType the type of reflection
588 void Material_Model::setColor( QString theProp,
589 QString theColorName,
590 ReflectionType theReflectionType )
592 int anId = theProp.indexOf( theColorName );
595 if ( Qtx::stringToColor( theProp.right( theProp.length() - ( anId + theColorName.length() ) ), c ) )
596 setColor( theReflectionType, c );
601 \brief Remove color value for the given reflection type
603 \param theReflectionType reflection type
604 \sa color(), setColor()
606 void Material_Model::removeColor( ReflectionType theReflectionType )
608 myColors.remove( theReflectionType );
612 \brief Get coefficient value for the given reflection type
613 \param theReflectionType reflection type
614 \return a coefficient which should be used by the given reflection type
617 double Material_Model::coefficient( ReflectionType theReflectionType ) const
619 return myCoefficients[ theReflectionType ];
623 \brief Set coefficient value for the given reflection type
625 \param theReflectionType reflection type
626 \param theCoefficient a coefficient to be used by the given reflection type
629 void Material_Model::setCoefficient( ReflectionType theReflectionType,
630 double theCoefficient )
632 myCoefficients[ theReflectionType ] = theCoefficient;
636 \brief Set coefficient of the current material from the given string
637 \param theProp the considered property
638 \param theCoefName the name of the color property
639 \param theReflectionType the type of reflection
641 void Material_Model::setCoefficient( QString theProp,
643 ReflectionType theReflectionType )
645 int anId = theProp.indexOf( theCoefName );
648 double aCoef = theProp.right( theProp.length() - ( anId + theCoefName.length() ) ).toDouble( &ok );
650 setCoefficient( theReflectionType, aCoef );
655 \brief Remove coefficient value for the given reflection type
657 \param theReflectionType reflection type
658 \sa coefficient(), setCoefficient()
660 void Material_Model::removeCoefficient( ReflectionType theReflectionType )
662 myCoefficients.remove( theReflectionType );
666 \brief Get shininess value
667 \return a shininess value of this material
670 double Material_Model::shininess() const
676 \brief Set shininess value
678 \param theShininess a shininess value of this material
681 void Material_Model::setShininess( double theShininess)
683 myShininess = theShininess;