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 )
430 value = myReflection[ type ].front_coef;
432 value = myReflection[ type ].back_coef;
438 \brief Set coefficient value for the given reflection type
439 \param type reflection type
440 \param value coefficient to be used by the given reflection type
441 \param theIsFront boolean flag for choosing side
442 \sa reflection( bool = true)
444 void Material_Model::setReflection( ReflectionType type, double value, bool theIsFront )
446 if ( type >= 0 && type < 4 )
449 myReflection[ type ].front_coef = value;
451 myReflection[ type ].back_coef = value;
456 \brief Get shininess value
457 \param theIsFront boolean flag for choosing side
458 \return shininess value of the material
459 \sa setShininess( double, bool = true )
461 double Material_Model::shininess( bool theIsFront ) const
464 return myFrontShininess;
466 return myBackShininess;
470 \brief Set shininess value
471 \param value new shininess value
472 \param theIsFront boolean flag for choosing side
473 \sa shininess( bool = true )
475 void Material_Model::setShininess( double value, bool theIsFront )
478 myFrontShininess = value;
480 myBackShininess = value;
484 \brief Get transparency value
485 \return transparency value of the material
486 \sa setTransparency()
488 double Material_Model::transparency() const
490 return myTransparency;
494 \brief Set transparency value
495 \param value new transparency value
498 void Material_Model::setTransparency( double value )
500 myTransparency = value;
504 \brief Initialize material model with default values
506 void Material_Model::init()
510 // non-physical by default
511 setPhysical( false );
513 setShininess( 0.039 );
514 setShininess( 0.039, false );
516 setTransparency( 0.0 );
518 // ambient reflection (enabled by default)
519 Qtx::stringToColor( "#333333", c );
520 setColor( Ambient, c );
521 setReflection( Ambient, 0.3, true );
522 setReflection( Ambient, 0.3, false );
523 setReflection( Ambient, true );
525 // diffuse reflection (enabled by default)
526 Qtx::stringToColor( "#000000", c );
527 setColor( Diffuse, c );
528 setReflection( Diffuse, 0.65 );
529 setReflection( Diffuse, 0.65, false );
530 setReflection( Diffuse, true );
532 // specular reflection (enabled by default)
533 Qtx::stringToColor( "#ffffff", c );
534 setColor( Specular, c );
535 setReflection( Specular, 0.0 );
536 setReflection( Specular, 0.0, false );
537 setReflection( Specular, true );
539 // emissive reflection (disabled by default)
540 Qtx::stringToColor( "#000000", c );
541 setColor( Emissive, c );
542 setReflection( Emissive, 0.0 );
543 setReflection( Emissive, 0.0, false );
544 setReflection( Emissive, false );
548 \brief Construct OCCT material aspect from material model
549 \param theIsFront boolean flag for choosing side
550 \return material aspect object with corresponding properties
552 Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect( bool theIsFront )
554 // Get material aspect from the current model
555 Graphic3d_MaterialAspect aspect;
559 // ambient reflection
560 if ( color( Ambient ).isValid() ) {
561 c = color( Ambient );
562 aspect.SetAmbientColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
564 aspect.SetAmbient( reflection( Ambient, theIsFront ));
565 if ( hasReflection( Ambient ) )
566 aspect.SetReflectionModeOn( Graphic3d_TOR_AMBIENT );
568 aspect.SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
570 // diffuse reflection
571 if ( color( Diffuse ).isValid() ) {
572 c = color( Diffuse );
573 aspect.SetDiffuseColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
575 aspect.SetDiffuse( reflection( Diffuse, theIsFront ));
576 if ( hasReflection( Diffuse ) )
577 aspect.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE );
579 aspect.SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
581 // specular reflection
582 if ( color( Specular ).isValid() ) {
583 c = color( Specular );
584 aspect.SetSpecularColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
586 aspect.SetSpecular( reflection( Specular, theIsFront ));
587 if ( hasReflection( Specular ) )
588 aspect.SetReflectionModeOn( Graphic3d_TOR_SPECULAR );
590 aspect.SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
592 // emissive reflection
593 if ( color( Emissive ).isValid() ) {
594 c = color( Emissive );
595 aspect.SetEmissiveColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
597 aspect.SetEmissive( reflection( Emissive, theIsFront ));
598 if ( hasReflection( Emissive ) )
599 aspect.SetReflectionModeOn( Graphic3d_TOR_EMISSION );
601 aspect.SetReflectionModeOff( Graphic3d_TOR_EMISSION );
604 aspect.SetShininess( shininess( theIsFront ) );
607 aspect.SetTransparency( transparency() );
610 aspect.SetMaterialType( isPhysical() ? Graphic3d_MATERIAL_PHYSIC : Graphic3d_MATERIAL_ASPECT );
616 \brief Construct VTK property from material model
617 \param theIsFront boolean flag for choosing side
618 \return VTK property with correspondent material properties
620 GEOM_VTKPropertyMaterial* Material_Model::getMaterialVTKProperty( bool theIsFront )
622 // NOTE: In VTK it's impossible to switch on/off specific reflection type
623 // NOTE: In VTK emissive reflection type is not supported
624 // NOTE: In VTK shininess is specified via SpecularPower attribute
625 // NOTE: In VTK transparency is specified via Opacity attribute
627 // Get material properties from the current model
628 GEOM_VTKPropertyMaterial* prop = GEOM_VTKPropertyMaterial::New();
632 // ambient reflection
633 if ( color( Ambient ).isValid() && hasReflection( Ambient ) ) {
634 c = color( Ambient );
635 prop->SetAmbientColor( c.redF(), c.greenF(), c.blueF() );
636 prop->SetAmbient( reflection( Ambient, theIsFront ) );
639 // diffuse reflection
640 if ( color( Diffuse ).isValid() && hasReflection( Diffuse ) ) {
641 c = color( Diffuse );
642 prop->SetDiffuseColor( c.redF(), c.greenF(), c.blueF() );
643 prop->SetDiffuse( reflection( Diffuse, theIsFront ) );
646 // specular reflection
647 if ( color( Specular ).isValid() && hasReflection( Specular ) ) {
648 c = color( Specular );
649 prop->SetSpecularColor( c.redF(), c.greenF(), c.blueF() );
650 prop->SetSpecular( reflection( Specular, theIsFront ) );
654 prop->SetSpecularPower( shininess( theIsFront )*100.0 );
657 prop->SetOpacity( 1 - transparency() );
660 prop->SetPhysical( isPhysical() );