1 // Copyright (C) 2007-2019 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, or (at your option) any later version.
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>
30 #include <Basics_OCCTVersion.hxx>
35 Create new SALOME material model with default properties.
37 Material_Model::Material_Model()
39 myReflection = ReflectionList(4);
40 init(); // set default properties
46 Material_Model::~Material_Model()
51 \brief Initialize material data from the given properties list
52 \param props material properties
55 void Material_Model::fromProperties( const QString& props )
57 // reset to default values
60 // parse material properties
61 QStringList propList = props.split( ":", QString::SkipEmptyParts );
62 foreach ( QString prop, propList )
64 QStringList pdata = prop.split( "=" );
65 if ( pdata.count() < 2 ) continue;
66 QString key = pdata[0].trimmed().toLower();
67 QString data = pdata[1].trimmed().toLower();
69 double dblValue = data.toDouble( &dblOk );
70 bool boolValue = (bool)( data.toInt( &boolOk ) );
73 if ( key == "ambientcolor" && Qtx::stringToColor( data, colorValue ) ) {
74 setColor( Ambient, colorValue );
76 else if ( key == "diffusecolor" && Qtx::stringToColor( data, colorValue ) ) {
77 setColor( Diffuse, colorValue );
79 else if ( key == "specularcolor" && Qtx::stringToColor( data, colorValue ) ) {
80 setColor( Specular, colorValue );
82 else if ( key == "emissivecolor" && Qtx::stringToColor( data, colorValue ) ) {
83 setColor( Emissive, colorValue );
85 else if ( key == "frontambientcoefficient" && dblOk ) {
86 setReflection( Ambient, dblValue );
88 else if ( key == "backambientcoefficient" && dblOk ) {
89 setReflection( Ambient, dblValue, false );
91 else if ( key == "frontdiffusecoefficient" && dblOk ) {
92 setReflection( Diffuse, dblValue );
94 else if ( key == "backdiffusecoefficient" && dblOk ) {
95 setReflection( Diffuse, dblValue, false );
97 else if ( key == "frontspecularcoefficient" && dblOk ) {
98 setReflection( Specular, dblValue );
100 else if ( key == "backspecularcoefficient" && dblOk ) {
101 setReflection( Specular, dblValue, false );
103 else if ( key == "frontemissivecoefficient" && dblOk ) {
104 setReflection( Emissive, dblValue );
106 else if ( key == "backemissivecoefficient" && dblOk ) {
107 setReflection( Emissive, dblValue, false );
109 else if ( key == "frontshininess" && dblOk ) {
110 setShininess( dblValue );
112 else if ( key == "backshininess" && dblOk ) {
113 setShininess( dblValue, false );
115 else if ( key == "transparency" && dblOk ) {
116 setTransparency( dblValue );
118 else if ( key == "physical" && boolOk ) {
119 setPhysical( boolValue );
121 else if ( key == "ambient" && boolOk ) {
122 setReflection( Ambient, boolValue );
124 else if ( key == "diffuse" && boolOk ) {
125 setReflection( Diffuse, boolValue );
127 else if ( key == "specular" && boolOk ) {
128 setReflection( Specular, boolValue );
130 else if ( key == "emissive" && boolOk ) {
131 setReflection( Emissive, boolValue );
137 \brief Get material properties string representation
138 \return string representing of material properties
141 QString Material_Model::toProperties()
144 QString fmt = "%1=%2";
147 props << fmt.arg( "Physical" ).arg( isPhysical() );
150 props << fmt.arg( "FrontShininess" ).arg( QString::number ( shininess( true ), 'g', 4 ) ) << fmt.arg( "BackShininess" ).arg( QString::number ( shininess( false ), 'g', 4 ) );
153 props << fmt.arg( "Transparency" ).arg( transparency() );
155 // ambient reflection
156 props << fmt.arg( "Ambient" ).arg( hasReflection( Ambient ) );
157 if ( color( Ambient ).isValid() )
158 props << fmt.arg( "AmbientColor" ).arg( Qtx::colorToString( color( Ambient ) ) );
159 props << fmt.arg( "FrontAmbientCoefficient" ).arg( QString::number ( reflection( Ambient, true ), 'g', 4 ) ) << fmt.arg( "BackAmbientCoefficient" ).arg( QString::number ( reflection( Ambient, false ), 'g', 4 ) );
161 // diffuse reflection
162 props << fmt.arg( "Diffuse" ).arg( hasReflection( Diffuse ) );
163 if ( color( Diffuse ).isValid() )
164 props << fmt.arg( "DiffuseColor" ).arg( Qtx::colorToString( color( Diffuse ) ) );
165 props << fmt.arg( "FrontDiffuseCoefficient" ).arg( QString::number ( reflection( Diffuse, true ), 'g', 4 ) ) << fmt.arg( "BackDiffuseCoefficient" ).arg( QString::number ( reflection( Diffuse, false ), 'g', 4 ) );
167 // specular reflection
168 props << fmt.arg( "Specular" ).arg( hasReflection( Specular ) );
169 if ( color( Specular ).isValid() )
170 props << fmt.arg( "SpecularColor" ).arg( Qtx::colorToString( color( Specular ) ) );
171 props << fmt.arg( "FrontSpecularCoefficient" ).arg( QString::number ( reflection( Specular, true ), 'g', 4 ) ) << fmt.arg( "BackSpecularCoefficient" ).arg( QString::number ( reflection( Specular, false ), 'g', 4 ) );
173 // emissive reflection
174 props << fmt.arg( "Emissive" ).arg( hasReflection( Emissive ) );
175 if ( color( Emissive ).isValid() )
176 props << fmt.arg( "EmissiveColor" ).arg( Qtx::colorToString( color( Emissive ) ) );
177 props << fmt.arg( "FrontEmissiveCoefficient" ).arg( QString::number ( reflection( Emissive, true ), 'g', 4 ) ) << fmt.arg( "BackEmissiveCoefficient" ).arg( QString::number ( reflection( Emissive, false ), 'g', 4 ) );
179 return props.join( ":" );
183 \brief Initialize material model from the resources
185 This function can be used to retrieve material properties from the resource file.
187 \param material material name (if not specified, model is initialized by default material)
188 \param resMgr resource manager (if not specified, new resources manager is created)
191 void Material_Model::fromResources( const QString& material, Material_ResourceMgr* resMgr )
193 static QString common = "[common]";
195 // reset to default values
198 // material name is not specified: use default values
199 if ( material.isEmpty() ) return;
202 resMgr = Material_ResourceMgr::resourceMgr();
204 // lock resources manager
205 QMutexLocker lock( &resMgr->myMutex );
207 // read common section
208 if ( material != common && resMgr->hasSection( common ) )
209 read( common, resMgr );
211 // read material section
212 read( material, resMgr );
215 void Material_Model::read( const QString& material, Material_ResourceMgr* resMgr )
218 if ( resMgr->hasValue( material, "physical" ) ) {
219 setPhysical( resMgr->booleanValue( material, "physical" ) );
223 if ( resMgr->hasValue( material, "front_shininess" ) ) {
224 setShininess( resMgr->doubleValue( material, "front_shininess" ) );
226 if ( resMgr->hasValue( material, "back_shininess" ) ) {
227 setShininess( resMgr->doubleValue( material, "back_shininess" ), false );
231 if ( resMgr->hasValue( material, "transparency" ) ) {
232 setTransparency( resMgr->doubleValue( material, "transparency" ) );
235 // ambient reflection
236 if ( resMgr->hasValue( material, "ambient-color" ) ) {
237 setColor( Ambient, resMgr->colorValue( material, "ambient-color" ) );
239 if ( resMgr->hasValue( material, "front_ambient-coefficient" ) ) {
240 setReflection( Ambient, resMgr->doubleValue( material, "front_ambient-coefficient" ) );
242 if ( resMgr->hasValue( material, "back_ambient-coefficient" ) ) {
243 setReflection( Ambient, resMgr->doubleValue( material, "back_ambient-coefficient" ), false );
245 if ( resMgr->hasValue( material, "ambient" ) ) {
246 setReflection( Ambient, resMgr->booleanValue( material, "ambient" ) );
249 // diffuse reflection
250 if ( resMgr->hasValue( material, "diffuse-color" ) ) {
251 setColor( Diffuse, resMgr->colorValue( material, "diffuse-color" ) );
253 if ( resMgr->hasValue( material, "front_diffuse-coefficient" ) ) {
254 setReflection( Diffuse, resMgr->doubleValue( material, "front_diffuse-coefficient" ) );
256 if ( resMgr->hasValue( material, "back_diffuse-coefficient" ) ) {
257 setReflection( Diffuse, resMgr->doubleValue( material, "back_diffuse-coefficient" ), false );
259 if ( resMgr->hasValue( material, "diffuse" ) ) {
260 setReflection( Diffuse, resMgr->booleanValue( material, "diffuse" ) );
263 // specular reflection
264 if ( resMgr->hasValue( material, "specular-color" ) ) {
265 setColor( Specular, resMgr->colorValue( material, "specular-color" ) );
267 if ( resMgr->hasValue( material, "front_specular-coefficient" ) ) {
268 setReflection( Specular, resMgr->doubleValue( material, "front_specular-coefficient" ) );
270 if ( resMgr->hasValue( material, "back_specular-coefficient" ) ) {
271 setReflection( Specular, resMgr->doubleValue( material, "back_specular-coefficient" ), false );
273 if ( resMgr->hasValue( material, "specular" ) ) {
274 setReflection( Specular, resMgr->booleanValue( material, "specular" ) );
277 // emissive reflection
278 if ( resMgr->hasValue( material, "emissive-color" ) ) {
279 setColor( Emissive, resMgr->colorValue( material, "emissive-color" ) );
281 if ( resMgr->hasValue( material, "front_emissive-coefficient" ) ) {
282 setReflection( Emissive, resMgr->doubleValue( material, "front_emissive-coefficient" ) );
284 if ( resMgr->hasValue( material, "back_emissive-coefficient" ) ) {
285 setReflection( Emissive, resMgr->doubleValue( material, "back_emissive-coefficient" ), false );
287 if ( resMgr->hasValue( material, "emissive" ) ) {
288 setReflection( Emissive, resMgr->booleanValue( material, "emissive" ) );
293 \brief Save material properties to the resource file.
294 \param material material name
295 \param resMgr resource manager
298 void Material_Model::toResources( const QString& material, Material_ResourceMgr* resMgr )
300 if ( resMgr && !material.isEmpty() ) {
301 // lock resources manager
302 QMutexLocker lock( &resMgr->myMutex );
304 // remove resources section (to clean-up all previous properties)
305 resMgr->remove( material );
308 resMgr->setValue( material, "physical", isPhysical() );
311 resMgr->setValue( material, "front_shininess", shininess( true) );
312 resMgr->setValue( material, "back_shininess", shininess( false ) );
315 resMgr->setValue( material, "transparency", transparency() );
317 // ambient reflection
318 if ( color( Ambient ).isValid() )
319 resMgr->setValue( material, "ambient-color", color( Ambient ) );
320 resMgr->setValue( material, "front_ambient-coefficient", reflection( Ambient ) );
321 resMgr->setValue( material, "back_ambient-coefficient", reflection( Ambient, false ) );
322 resMgr->setValue( material, "ambient", hasReflection( Ambient ) );
324 // diffuse reflection
325 if ( color( Diffuse ).isValid() )
326 resMgr->setValue( material, "diffuse-color", color( Diffuse ) );
327 resMgr->setValue( material, "front_diffuse-coefficient", reflection( Diffuse ) );
328 resMgr->setValue( material, "back_diffuse-coefficient", reflection( Diffuse, false ) );
329 resMgr->setValue( material, "diffuse", hasReflection( Diffuse ) );
331 // Specular reflection
332 if ( color( Specular ).isValid() )
333 resMgr->setValue( material, "specular-color", color( Specular ) );
334 resMgr->setValue( material, "front_specular-coefficient", reflection( Specular ) );
335 resMgr->setValue( material, "back_specular-coefficient", reflection( Specular, false ) );
336 resMgr->setValue( material, "specular", hasReflection( Specular ) );
338 // Emissive reflection
339 if ( color( Emissive ).isValid() )
340 resMgr->setValue( material, "emissive-color", color( Emissive ) );
341 resMgr->setValue( material, "front_emissive-coefficient", reflection( Emissive ) );
342 resMgr->setValue( material, "back_emissive-coefficient", reflection( Emissive, false ) );
343 resMgr->setValue( material, "emissive", hasReflection( Emissive ) );
348 \brief Get material type
349 \return \c true if material is physical or \c false otherwise
352 bool Material_Model::isPhysical() const
358 \brief Set material type
359 \param value \c true if material is physical or \c false otherwise
362 void Material_Model::setPhysical( bool value )
364 myIsPhysical = value;
368 \brief Check if given reflection is enabled
369 \param type reflection type
370 \return \c true if specified reflection type is enabled or \c false otherwise
371 \sa setReflection(ReflectionType, bool)
373 bool Material_Model::hasReflection( ReflectionType type ) const
376 if ( type >= 0 && type < 4 )
377 value = myReflection[ type ].enabled;
382 \brief Enable/disable given reflection type
383 \param type reflection type
384 \param value boolean flag
387 void Material_Model::setReflection( ReflectionType type, bool value )
389 if ( type >= 0 && type < 4 )
390 myReflection[ type ].enabled = value;
394 \brief Get color value for the given reflection type
395 \param type reflection type
396 \return color associated with the specified reflection type
399 QColor Material_Model::color( ReflectionType type ) const
402 if ( type >= 0 && type < 4 )
403 value = myReflection[ type ].color;
408 \brief Set color value for the given reflection type
409 \param type reflection type
410 \param value color to be used for specified reflection type
413 void Material_Model::setColor( ReflectionType type, const QColor& value )
415 if ( type >= 0 && type < 4 )
416 myReflection[ type ].color = value;
420 \brief Get coefficient value for the given reflection type
421 \param type reflection type
422 \param theIsFront boolean flag for choosing side
423 \return coefficient value for the specified reflection type
424 \sa setReflection(ReflectionType, double, bool = true)
426 double Material_Model::reflection( ReflectionType type, bool theIsFront ) const
429 if ( type >= 0 && type < 4 )
432 value = myReflection[ type ].front_coef;
434 value = myReflection[ type ].back_coef;
440 \brief Set coefficient value for the given reflection type
441 \param type reflection type
442 \param value coefficient to be used by the given reflection type
443 \param theIsFront boolean flag for choosing side
444 \sa reflection( bool = true)
446 void Material_Model::setReflection( ReflectionType type, double value, bool theIsFront )
448 if ( type >= 0 && type < 4 )
451 myReflection[ type ].front_coef = value;
453 myReflection[ type ].back_coef = value;
458 \brief Get shininess value
459 \param theIsFront boolean flag for choosing side
460 \return shininess value of the material
461 \sa setShininess( double, bool = true )
463 double Material_Model::shininess( bool theIsFront ) const
466 return myFrontShininess;
468 return myBackShininess;
472 \brief Set shininess value
473 \param value new shininess value
474 \param theIsFront boolean flag for choosing side
475 \sa shininess( bool = true )
477 void Material_Model::setShininess( double value, bool theIsFront )
480 myFrontShininess = value;
482 myBackShininess = value;
486 \brief Get transparency value
487 \return transparency value of the material
488 \sa setTransparency()
490 double Material_Model::transparency() const
492 return myTransparency;
496 \brief Set transparency value
497 \param value new transparency value
500 void Material_Model::setTransparency( double value )
502 myTransparency = value;
506 \brief Initialize material model with default values
508 void Material_Model::init()
512 // non-physical by default
513 setPhysical( false );
515 setShininess( 0.039 );
516 setShininess( 0.039, false );
518 setTransparency( 0.0 );
520 // ambient reflection (enabled by default)
521 Qtx::stringToColor( "#333333", c );
522 setColor( Ambient, c );
523 setReflection( Ambient, 0.3, true );
524 setReflection( Ambient, 0.3, false );
525 setReflection( Ambient, true );
527 // diffuse reflection (enabled by default)
528 Qtx::stringToColor( "#000000", c );
529 setColor( Diffuse, c );
530 setReflection( Diffuse, 0.65 );
531 setReflection( Diffuse, 0.65, false );
532 setReflection( Diffuse, true );
534 // specular reflection (enabled by default)
535 Qtx::stringToColor( "#ffffff", c );
536 setColor( Specular, c );
537 setReflection( Specular, 0.0 );
538 setReflection( Specular, 0.0, false );
539 setReflection( Specular, true );
541 // emissive reflection (disabled by default)
542 Qtx::stringToColor( "#000000", c );
543 setColor( Emissive, c );
544 setReflection( Emissive, 0.0 );
545 setReflection( Emissive, 0.0, false );
546 setReflection( Emissive, false );
550 \brief Construct OCCT material aspect from material model
551 \param theIsFront boolean flag for choosing side
552 \return material aspect object with corresponding properties
554 Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect( bool theIsFront )
556 // Get material aspect from the current model
557 Graphic3d_MaterialAspect aspect;
561 // ambient reflection
562 #if OCC_VERSION_LARGE >= 0x07040000
563 if ( color( Ambient ).isValid() ) {
564 c = color( Ambient );
565 aspect.SetAmbientColor( Quantity_Color( Graphic3d_Vec3( c.redF(), c.greenF(), c.blueF() ) * reflection( Ambient, theIsFront ) ) );
567 if ( !hasReflection( Ambient ) )
568 aspect.SetAmbientColor( Quantity_NOC_BLACK );
570 if ( color( Ambient ).isValid() ) {
571 c = color( Ambient );
572 aspect.SetAmbientColor( ( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
574 aspect.SetAmbient( reflection( Ambient, theIsFront ));
575 if ( hasReflection( Ambient ) )
576 aspect.SetReflectionModeOn( Graphic3d_TOR_AMBIENT );
578 aspect.SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
581 // diffuse reflection
582 #if OCC_VERSION_LARGE >= 0x07040000
583 if ( color( Diffuse ).isValid() ) {
584 c = color( Diffuse );
585 aspect.SetDiffuseColor( Quantity_Color( Graphic3d_Vec3( c.redF(), c.greenF(), c.blueF() ) * reflection( Diffuse, theIsFront ) ) );
587 if ( !hasReflection( Diffuse ) )
588 aspect.SetDiffuseColor( Quantity_NOC_BLACK );
590 if ( color( Diffuse ).isValid() ) {
591 c = color( Diffuse );
592 aspect.SetDiffuseColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
594 aspect.SetDiffuse( reflection( Diffuse, theIsFront ));
595 if ( hasReflection( Diffuse ) )
596 aspect.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE );
598 aspect.SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
601 // specular reflection
602 #if OCC_VERSION_LARGE >= 0x07040000
603 if ( color( Specular ).isValid() ) {
604 c = color( Specular );
605 aspect.SetSpecularColor( Quantity_Color( Graphic3d_Vec3( c.redF(), c.greenF(), c.blueF() ) * reflection( Specular, theIsFront ) ) );
607 if ( !hasReflection( Specular ) )
608 aspect.SetSpecularColor( Quantity_NOC_BLACK );
610 if ( color( Specular ).isValid() ) {
611 c = color( Specular );
612 aspect.SetSpecularColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
614 aspect.SetSpecular( reflection( Specular, theIsFront ));
615 if ( hasReflection( Specular ) )
616 aspect.SetReflectionModeOn( Graphic3d_TOR_SPECULAR );
618 aspect.SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
621 // emissive reflection
622 #if OCC_VERSION_LARGE >= 0x07040000
623 if ( color( Emissive ).isValid() ) {
624 c = color( Emissive );
625 aspect.SetEmissiveColor( Quantity_Color( Graphic3d_Vec3( c.redF(), c.greenF(), c.blueF() ) * reflection( Emissive, theIsFront ) ) );
627 if ( !hasReflection( Emissive ) )
628 aspect.SetEmissiveColor( Quantity_NOC_BLACK );
630 if ( color( Emissive ).isValid() ) {
631 c = color( Emissive );
632 aspect.SetEmissiveColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
634 aspect.SetEmissive( reflection( Emissive, theIsFront ));
635 if ( hasReflection( Emissive ) )
636 aspect.SetReflectionModeOn( Graphic3d_TOR_EMISSION );
638 aspect.SetReflectionModeOff( Graphic3d_TOR_EMISSION );
642 aspect.SetShininess( shininess( theIsFront ) );
645 aspect.SetTransparency( transparency() );
648 aspect.SetMaterialType( isPhysical() ? Graphic3d_MATERIAL_PHYSIC : Graphic3d_MATERIAL_ASPECT );
654 \brief Construct VTK property from material model
655 \param theIsFront boolean flag for choosing side
656 \return VTK property with correspondent material properties
658 GEOM_VTKPropertyMaterial* Material_Model::getMaterialVTKProperty( bool theIsFront )
660 // NOTE: In VTK it's impossible to switch on/off specific reflection type
661 // NOTE: In VTK emissive reflection type is not supported
662 // NOTE: In VTK shininess is specified via SpecularPower attribute
663 // NOTE: In VTK transparency is specified via Opacity attribute
665 // Get material properties from the current model
666 GEOM_VTKPropertyMaterial* prop = GEOM_VTKPropertyMaterial::New();
670 // ambient reflection
671 if ( color( Ambient ).isValid() && hasReflection( Ambient ) ) {
672 c = color( Ambient );
673 prop->SetAmbientColor( c.redF(), c.greenF(), c.blueF() );
674 prop->SetAmbient( reflection( Ambient, theIsFront ) );
677 // diffuse reflection
678 if ( color( Diffuse ).isValid() && hasReflection( Diffuse ) ) {
679 c = color( Diffuse );
680 prop->SetDiffuseColor( c.redF(), c.greenF(), c.blueF() );
681 prop->SetDiffuse( reflection( Diffuse, theIsFront ) );
684 // specular reflection
685 if ( color( Specular ).isValid() && hasReflection( Specular ) ) {
686 c = color( Specular );
687 prop->SetSpecularColor( c.redF(), c.greenF(), c.blueF() );
688 prop->SetSpecular( reflection( Specular, theIsFront ) );
692 prop->SetSpecularPower( shininess( theIsFront )*100.0 );
695 prop->SetOpacity( 1 - transparency() );
698 prop->SetPhysical( isPhysical() );