1 // Copyright (C) 2007-2013 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 "GEOM_VTKPropertyMaterial.hxx"
26 #include "Material_ResourceMgr.h"
28 #include <QMutexLocker>
33 Create new SALOME material model with default properties.
35 Material_Model::Material_Model()
37 myReflection = ReflectionList(4);
38 init(); // set default properties
44 Material_Model::~Material_Model()
49 \brief Initialize material data from the given properties list
50 \param props material properties
53 void Material_Model::fromProperties( const QString& props )
55 // reset to default values
58 // parse material properties
59 QStringList propList = props.split( ":", QString::SkipEmptyParts );
60 foreach ( QString prop, propList )
62 QStringList pdata = prop.split( "=" );
63 if ( pdata.count() < 2 ) continue;
64 QString key = pdata[0].trimmed().toLower();
65 QString data = pdata[1].trimmed().toLower();
67 double dblValue = data.toDouble( &dblOk );
68 bool boolValue = (bool)( data.toInt( &boolOk ) );
71 if ( key == "ambientcolor" && Qtx::stringToColor( data, colorValue ) ) {
72 setColor( Ambient, colorValue );
74 else if ( key == "diffusecolor" && Qtx::stringToColor( data, colorValue ) ) {
75 setColor( Diffuse, colorValue );
77 else if ( key == "specularcolor" && Qtx::stringToColor( data, colorValue ) ) {
78 setColor( Specular, colorValue );
80 else if ( key == "emissivecolor" && Qtx::stringToColor( data, colorValue ) ) {
81 setColor( Emissive, colorValue );
83 else if ( key == "frontambientcoefficient" && dblOk ) {
84 setReflection( Ambient, dblValue );
86 else if ( key == "backambientcoefficient" && dblOk ) {
87 setReflection( Ambient, dblValue, false );
89 else if ( key == "frontdiffusecoefficient" && dblOk ) {
90 setReflection( Diffuse, dblValue );
92 else if ( key == "backdiffusecoefficient" && dblOk ) {
93 setReflection( Diffuse, dblValue, false );
95 else if ( key == "frontspecularcoefficient" && dblOk ) {
96 setReflection( Specular, dblValue );
98 else if ( key == "backspecularcoefficient" && dblOk ) {
99 setReflection( Specular, dblValue, false );
101 else if ( key == "frontemissivecoefficient" && dblOk ) {
102 setReflection( Emissive, dblValue );
104 else if ( key == "backemissivecoefficient" && dblOk ) {
105 setReflection( Emissive, dblValue, false );
107 else if ( key == "frontshininess" && dblOk ) {
108 setShininess( dblValue );
110 else if ( key == "backshininess" && dblOk ) {
111 setShininess( dblValue, false );
113 else if ( key == "transparency" && dblOk ) {
114 setTransparency( dblValue );
116 else if ( key == "physical" && boolOk ) {
117 setPhysical( boolValue );
119 else if ( key == "ambient" && boolOk ) {
120 setReflection( Ambient, boolValue );
122 else if ( key == "diffuse" && boolOk ) {
123 setReflection( Diffuse, boolValue );
125 else if ( key == "specular" && boolOk ) {
126 setReflection( Specular, boolValue );
128 else if ( key == "emissive" && boolOk ) {
129 setReflection( Emissive, boolValue );
135 \brief Get material properties string representation
136 \return string representing of material properties
139 QString Material_Model::toProperties()
142 QString fmt = "%1=%2";
145 props << fmt.arg( "Physical" ).arg( isPhysical() );
148 props << fmt.arg( "FrontShininess" ).arg( QString::number ( shininess( true ), 'g', 4 ) ) << fmt.arg( "BackShininess" ).arg( QString::number ( shininess( false ), 'g', 4 ) );
151 props << fmt.arg( "Transparency" ).arg( transparency() );
153 // ambient reflection
154 props << fmt.arg( "Ambient" ).arg( hasReflection( Ambient ) );
155 if ( color( Ambient ).isValid() )
156 props << fmt.arg( "AmbientColor" ).arg( Qtx::colorToString( color( Ambient ) ) );
157 props << fmt.arg( "FrontAmbientCoefficient" ).arg( QString::number ( reflection( Ambient, true ), 'g', 4 ) ) << fmt.arg( "BackAmbientCoefficient" ).arg( QString::number ( reflection( Ambient, false ), 'g', 4 ) );
159 // diffuse reflection
160 props << fmt.arg( "Diffuse" ).arg( hasReflection( Diffuse ) );
161 if ( color( Diffuse ).isValid() )
162 props << fmt.arg( "DiffuseColor" ).arg( Qtx::colorToString( color( Diffuse ) ) );
163 props << fmt.arg( "FrontDiffuseCoefficient" ).arg( QString::number ( reflection( Diffuse, true ), 'g', 4 ) ) << fmt.arg( "BackDiffuseCoefficient" ).arg( QString::number ( reflection( Diffuse, false ), 'g', 4 ) );
165 // specular reflection
166 props << fmt.arg( "Specular" ).arg( hasReflection( Specular ) );
167 if ( color( Specular ).isValid() )
168 props << fmt.arg( "SpecularColor" ).arg( Qtx::colorToString( color( Specular ) ) );
169 props << fmt.arg( "FrontSpecularCoefficient" ).arg( QString::number ( reflection( Specular, true ), 'g', 4 ) ) << fmt.arg( "BackSpecularCoefficient" ).arg( QString::number ( reflection( Specular, false ), 'g', 4 ) );
171 // emissive reflection
172 props << fmt.arg( "Emissive" ).arg( hasReflection( Emissive ) );
173 if ( color( Emissive ).isValid() )
174 props << fmt.arg( "EmissiveColor" ).arg( Qtx::colorToString( color( Emissive ) ) );
175 props << fmt.arg( "FrontEmissiveCoefficient" ).arg( QString::number ( reflection( Emissive, true ), 'g', 4 ) ) << fmt.arg( "BackEmissiveCoefficient" ).arg( QString::number ( reflection( Emissive, false ), 'g', 4 ) );
177 return props.join( ":" );
181 \brief Initialize material model from the resources
183 This function can be used to retrieve material properties from the resource file.
185 \param material material name (if not specified, model is initialized by default material)
186 \param resMgr resource manager (if not specified, new resources manager is created)
189 void Material_Model::fromResources( const QString& material, Material_ResourceMgr* resMgr )
191 static QString common = "[common]";
193 // reset to default values
196 // material name is not specified: use default values
197 if ( material.isEmpty() ) return;
200 resMgr = Material_ResourceMgr::resourceMgr();
202 // lock resources manager
203 QMutexLocker lock( &resMgr->myMutex );
205 // read common section
206 if ( material != common && resMgr->hasSection( common ) )
207 read( common, resMgr );
209 // read material section
210 read( material, resMgr );
213 void Material_Model::read( const QString& material, Material_ResourceMgr* resMgr )
216 if ( resMgr->hasValue( material, "physical" ) ) {
217 setPhysical( resMgr->booleanValue( material, "physical" ) );
221 if ( resMgr->hasValue( material, "front_shininess" ) ) {
222 setShininess( resMgr->doubleValue( material, "front_shininess" ) );
224 if ( resMgr->hasValue( material, "back_shininess" ) ) {
225 setShininess( resMgr->doubleValue( material, "back_shininess" ), false );
229 if ( resMgr->hasValue( material, "transparency" ) ) {
230 setTransparency( resMgr->doubleValue( material, "transparency" ) );
233 // ambient reflection
234 if ( resMgr->hasValue( material, "ambient-color" ) ) {
235 setColor( Ambient, resMgr->colorValue( material, "ambient-color" ) );
237 if ( resMgr->hasValue( material, "front_ambient-coefficient" ) ) {
238 setReflection( Ambient, resMgr->doubleValue( material, "front_ambient-coefficient" ) );
240 if ( resMgr->hasValue( material, "back_ambient-coefficient" ) ) {
241 setReflection( Ambient, resMgr->doubleValue( material, "back_ambient-coefficient" ), false );
243 if ( resMgr->hasValue( material, "ambient" ) ) {
244 setReflection( Ambient, resMgr->booleanValue( material, "ambient" ) );
247 // diffuse reflection
248 if ( resMgr->hasValue( material, "diffuse-color" ) ) {
249 setColor( Diffuse, resMgr->colorValue( material, "diffuse-color" ) );
251 if ( resMgr->hasValue( material, "front_diffuse-coefficient" ) ) {
252 setReflection( Diffuse, resMgr->doubleValue( material, "front_diffuse-coefficient" ) );
254 if ( resMgr->hasValue( material, "back_diffuse-coefficient" ) ) {
255 setReflection( Diffuse, resMgr->doubleValue( material, "back_diffuse-coefficient" ), false );
257 if ( resMgr->hasValue( material, "diffuse" ) ) {
258 setReflection( Diffuse, resMgr->booleanValue( material, "diffuse" ) );
261 // specular reflection
262 if ( resMgr->hasValue( material, "specular-color" ) ) {
263 setColor( Specular, resMgr->colorValue( material, "specular-color" ) );
265 if ( resMgr->hasValue( material, "front_specular-coefficient" ) ) {
266 setReflection( Specular, resMgr->doubleValue( material, "front_specular-coefficient" ) );
268 if ( resMgr->hasValue( material, "back_specular-coefficient" ) ) {
269 setReflection( Specular, resMgr->doubleValue( material, "back_specular-coefficient" ), false );
271 if ( resMgr->hasValue( material, "specular" ) ) {
272 setReflection( Specular, resMgr->booleanValue( material, "specular" ) );
275 // emissive reflection
276 if ( resMgr->hasValue( material, "emissive-color" ) ) {
277 setColor( Emissive, resMgr->colorValue( material, "emissive-color" ) );
279 if ( resMgr->hasValue( material, "front_emissive-coefficient" ) ) {
280 setReflection( Emissive, resMgr->doubleValue( material, "front_emissive-coefficient" ) );
282 if ( resMgr->hasValue( material, "back_emissive-coefficient" ) ) {
283 setReflection( Emissive, resMgr->doubleValue( material, "back_emissive-coefficient" ), false );
285 if ( resMgr->hasValue( material, "emissive" ) ) {
286 setReflection( Emissive, resMgr->booleanValue( material, "emissive" ) );
291 \brief Save material properties to the resource file.
292 \param material material name
293 \param resMgr resource manager
296 void Material_Model::toResources( const QString& material, Material_ResourceMgr* resMgr )
298 if ( resMgr && !material.isEmpty() ) {
299 // lock resources manager
300 QMutexLocker lock( &resMgr->myMutex );
302 // remove resources section (to clean-up all previous properties)
303 resMgr->remove( material );
306 resMgr->setValue( material, "physical", isPhysical() );
309 resMgr->setValue( material, "front_shininess", shininess( true) );
310 resMgr->setValue( material, "back_shininess", shininess( false ) );
313 resMgr->setValue( material, "transparency", transparency() );
315 // ambient reflection
316 if ( color( Ambient ).isValid() )
317 resMgr->setValue( material, "ambient-color", color( Ambient ) );
318 resMgr->setValue( material, "front_ambient-coefficient", reflection( Ambient ) );
319 resMgr->setValue( material, "back_ambient-coefficient", reflection( Ambient, false ) );
320 resMgr->setValue( material, "ambient", hasReflection( Ambient ) );
322 // diffuse reflection
323 if ( color( Diffuse ).isValid() )
324 resMgr->setValue( material, "diffuse-color", color( Diffuse ) );
325 resMgr->setValue( material, "front_diffuse-coefficient", reflection( Diffuse ) );
326 resMgr->setValue( material, "back_diffuse-coefficient", reflection( Diffuse, false ) );
327 resMgr->setValue( material, "diffuse", hasReflection( Diffuse ) );
329 // Specular reflection
330 if ( color( Specular ).isValid() )
331 resMgr->setValue( material, "specular-color", color( Specular ) );
332 resMgr->setValue( material, "front_specular-coefficient", reflection( Specular ) );
333 resMgr->setValue( material, "back_specular-coefficient", reflection( Specular, false ) );
334 resMgr->setValue( material, "specular", hasReflection( Specular ) );
336 // Emissive reflection
337 if ( color( Emissive ).isValid() )
338 resMgr->setValue( material, "emissive-color", color( Emissive ) );
339 resMgr->setValue( material, "front_emissive-coefficient", reflection( Emissive ) );
340 resMgr->setValue( material, "back_emissive-coefficient", reflection( Emissive, false ) );
341 resMgr->setValue( material, "emissive", hasReflection( Emissive ) );
346 \brief Get material type
347 \return \c true if material is physical or \c false otherwise
350 bool Material_Model::isPhysical() const
356 \brief Set material type
357 \param value \c true if material is physical or \c false otherwise
360 void Material_Model::setPhysical( bool value )
362 myIsPhysical = value;
366 \brief Check if given reflection is enabled
367 \param type reflection type
368 \return \c true if specified reflection type is enabled or \c false otherwise
369 \sa setReflection(ReflectionType, bool)
371 bool Material_Model::hasReflection( ReflectionType type ) const
374 if ( type >= 0 && type < 4 )
375 value = myReflection[ type ].enabled;
380 \brief Enable/disable given reflection type
381 \param type reflection type
382 \param value boolean flag
385 void Material_Model::setReflection( ReflectionType type, bool value )
387 if ( type >= 0 && type < 4 )
388 myReflection[ type ].enabled = value;
392 \brief Get color value for the given reflection type
393 \param type reflection type
394 \return color associated with the specified reflection type
397 QColor Material_Model::color( ReflectionType type ) const
400 if ( type >= 0 && type < 4 )
401 value = myReflection[ type ].color;
406 \brief Set color value for the given reflection type
407 \param type reflection type
408 \param value color to be used for specified reflection type
411 void Material_Model::setColor( ReflectionType type, const QColor& value )
413 if ( type >= 0 && type < 4 )
414 myReflection[ type ].color = value;
418 \brief Get coefficient value for the given reflection type
419 \param type reflection type
420 \param theIsFront boolean flag for choosing side
421 \return coefficient value for the specified reflection type
422 \sa setReflection(ReflectionType, double, bool = true)
424 double Material_Model::reflection( ReflectionType type, bool theIsFront ) const
427 if ( type >= 0 && type < 4 )
429 value = myReflection[ type ].front_coef;
431 value = myReflection[ type ].back_coef;
436 \brief Set coefficient value for the given reflection type
437 \param type reflection type
438 \param value coefficient to be used by the given reflection type
439 \param theIsFront boolean flag for choosing side
440 \sa reflection( bool = true)
442 void Material_Model::setReflection( ReflectionType type, double value, bool theIsFront )
444 if ( type >= 0 && type < 4 )
446 myReflection[ type ].front_coef = value;
448 myReflection[ type ].back_coef = value;
452 \brief Get shininess value
453 \param theIsFront boolean flag for choosing side
454 \return shininess value of the material
455 \sa setShininess( double, bool = true )
457 double Material_Model::shininess( bool theIsFront ) const
460 return myFrontShininess;
462 return myBackShininess;
466 \brief Set shininess value
467 \param value new shininess value
468 \param theIsFront boolean flag for choosing side
469 \sa shininess( bool = true )
471 void Material_Model::setShininess( double value, bool theIsFront )
474 myFrontShininess = value;
476 myBackShininess = value;
480 \brief Get transparency value
481 \return transparency value of the material
482 \sa setTransparency()
484 double Material_Model::transparency() const
486 return myTransparency;
490 \brief Set transparency value
491 \param value new transparency value
494 void Material_Model::setTransparency( double value )
496 myTransparency = value;
500 \brief Initialize material model with default values
502 void Material_Model::init()
506 // non-physical by default
507 setPhysical( false );
509 setShininess( 0.039 );
510 setShininess( 0.039, false );
512 setTransparency( 0.0 );
514 // ambient reflection (enabled by default)
515 Qtx::stringToColor( "#333333", c );
516 setColor( Ambient, c );
517 setReflection( Ambient, 0.3, true );
518 setReflection( Ambient, 0.3, false );
519 setReflection( Ambient, true );
521 // diffuse reflection (enabled by default)
522 Qtx::stringToColor( "#000000", c );
523 setColor( Diffuse, c );
524 setReflection( Diffuse, 0.65 );
525 setReflection( Diffuse, 0.65, false );
526 setReflection( Diffuse, true );
528 // specular reflection (enabled by default)
529 Qtx::stringToColor( "#ffffff", c );
530 setColor( Specular, c );
531 setReflection( Specular, 0.0 );
532 setReflection( Specular, 0.0, false );
533 setReflection( Specular, true );
535 // emissive reflection (disabled by default)
536 Qtx::stringToColor( "#000000", c );
537 setColor( Emissive, c );
538 setReflection( Emissive, 0.0 );
539 setReflection( Emissive, 0.0, false );
540 setReflection( Emissive, false );
544 \brief Construct OCCT material aspect from material model
545 \param theIsFront boolean flag for choosing side
546 \return material aspect object with corresponding properties
548 Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect( bool theIsFront )
550 // Get material aspect from the current model
551 Graphic3d_MaterialAspect aspect;
555 // ambient reflection
556 if ( color( Ambient ).isValid() ) {
557 c = color( Ambient );
558 aspect.SetAmbientColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
560 aspect.SetAmbient( reflection( Ambient, theIsFront ));
561 if ( hasReflection( Ambient ) )
562 aspect.SetReflectionModeOn( Graphic3d_TOR_AMBIENT );
564 aspect.SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
566 // diffuse reflection
567 if ( color( Diffuse ).isValid() ) {
568 c = color( Diffuse );
569 aspect.SetDiffuseColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
571 aspect.SetDiffuse( reflection( Diffuse, theIsFront ));
572 if ( hasReflection( Diffuse ) )
573 aspect.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE );
575 aspect.SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
577 // specular reflection
578 if ( color( Specular ).isValid() ) {
579 c = color( Specular );
580 aspect.SetSpecularColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
582 aspect.SetSpecular( reflection( Specular, theIsFront ));
583 if ( hasReflection( Specular ) )
584 aspect.SetReflectionModeOn( Graphic3d_TOR_SPECULAR );
586 aspect.SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
588 // emissive reflection
589 if ( color( Emissive ).isValid() ) {
590 c = color( Emissive );
591 aspect.SetEmissiveColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
593 aspect.SetEmissive( reflection( Emissive, theIsFront ));
594 if ( hasReflection( Emissive ) )
595 aspect.SetReflectionModeOn( Graphic3d_TOR_EMISSION );
597 aspect.SetReflectionModeOff( Graphic3d_TOR_EMISSION );
600 aspect.SetShininess( shininess( theIsFront ) );
603 aspect.SetTransparency( transparency() );
606 aspect.SetMaterialType( isPhysical() ? Graphic3d_MATERIAL_PHYSIC : Graphic3d_MATERIAL_ASPECT );
612 \brief Construct VTK property from material model
613 \param theIsFront boolean flag for choosing side
614 \return VTK property with correspondent material properties
616 GEOM_VTKPropertyMaterial* Material_Model::getMaterialVTKProperty( bool theIsFront )
618 // NOTE: In VTK it's impossible to switch on/off specific reflection type
619 // NOTE: In VTK emissive reflection type is not supported
620 // NOTE: In VTK shininess is specified via SpecularPower attribute
621 // NOTE: In VTK transparency is specified via Opacity attribute
623 // Get material properties from the current model
624 GEOM_VTKPropertyMaterial* prop = GEOM_VTKPropertyMaterial::New();
628 // ambient reflection
629 if ( color( Ambient ).isValid() && hasReflection( Ambient ) ) {
630 c = color( Ambient );
631 prop->SetAmbientColor( c.redF(), c.greenF(), c.blueF() );
632 prop->SetAmbient( reflection( Ambient, theIsFront ) );
635 // diffuse reflection
636 if ( color( Diffuse ).isValid() && hasReflection( Diffuse ) ) {
637 c = color( Diffuse );
638 prop->SetDiffuseColor( c.redF(), c.greenF(), c.blueF() );
639 prop->SetDiffuse( reflection( Diffuse, theIsFront ) );
642 // specular reflection
643 if ( color( Specular ).isValid() && hasReflection( Specular ) ) {
644 c = color( Specular );
645 prop->SetSpecularColor( c.redF(), c.greenF(), c.blueF() );
646 prop->SetSpecular( reflection( Specular, theIsFront ) );
650 prop->SetSpecularPower( shininess( theIsFront )*100.0 );
653 prop->SetOpacity( 1 - transparency() );
656 prop->SetPhysical( isPhysical() );