geom/src/Material/Material_Model.cxx
2012-04-13 11:09:23 +00:00

718 lines
22 KiB
C++

// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// File : Material_Model.cxx
// Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com)
//
#include "Material_Model.h"
#include "Material_ResourceMgr.h"
#include "GEOM_VTKPropertyMaterial.hxx"
#include <GEOM_Constants.h>
#include <QtxResourceMgr.h>
#include <SUIT_ResourceMgr.h>
#include <SUIT_Session.h>
// OCCT Includes
#include <Graphic3d_AspectFillArea3d.hxx>
/*!
\brief Constructor
Create new SALOME material model with default properties.
*/
Material_Model::Material_Model()
: myResourceMgr( 0 )
{
myShininess = 0.0;
myIsPhysical = false;
}
/*!
\brief Destructor
*/
Material_Model::~Material_Model()
{
}
/*!
\brief Construct material model according to the given list of
material properties
\param theProps the list of material properties
\return material model object with correspondent properties
\sa getMaterialProperty()
*/
Material_Model* Material_Model::getMaterialModel( QStringList theProps )
{
Material_Model* aModel = new Material_Model();
foreach ( QString aProp, theProps ) {
if ( aProp.isNull() ) continue;
// Set current ambient color
aModel->setColor( aProp, "AmbientColor=", Material_Model::Ambient );
// Set current ambient coefficient
aModel->setCoefficient( aProp, "AmbientCoefficient=", Material_Model::Ambient );
// Set current diffuse color
aModel->setColor( aProp, "DiffuseColor=", Material_Model::Diffuse );
// Set current diffuse coefficient
aModel->setCoefficient( aProp, "DiffuseCoefficient=", Material_Model::Diffuse );
// Set current specular color
aModel->setColor( aProp, "SpecularColor=", Material_Model::Specular );
// Set current specular coefficient
aModel->setCoefficient( aProp, "SpecularCoefficient=", Material_Model::Specular );
// Set current emission color
aModel->setColor( aProp, "EmissionColor=", Material_Model::Emission );
// Set current emission coefficient
aModel->setCoefficient( aProp, "EmissionCoefficient=", Material_Model::Emission );
// Set current shininess
QString aPropName = "Shininess=";
int anId = aProp.indexOf(aPropName);
if ( anId != -1 ) {
bool ok;
double aCoef = aProp.right( aProp.length() - (anId+aPropName.length()) ).toDouble(&ok);
if ( ok )
aModel->setShininess( aCoef );
}
// Set current material type: physical or artificial
aPropName = "Physical=";
anId = aProp.indexOf(aPropName);
if ( anId != -1 ) {
bool ok;
bool aFlag = aProp.right( aProp.length() - (anId+aPropName.length()) ).toInt( &ok );
if ( ok )
aModel->setPhysical( aFlag );
}
}
return aModel;
}
/*!
\brief Construct string of material properties for this model object
\return a string representing a set of material properties
\sa getMaterialModel()
*/
QString Material_Model::getMaterialProperty()
{
// Parse material properties of the current model and form a string for persistent purpose
QString aMaterial;
bool isReflectionTypeActive;
QColor c;
double coef;
// Ambient reflection
isReflectionTypeActive = hasAmbientReflection();
if ( isReflectionTypeActive ) {
c = color( Material_Model::Ambient );
coef = coefficient(Material_Model::Ambient);
// Insert properties into persistent string
aMaterial = "AmbientColor=%1%2AmbientCoefficient=%3";
aMaterial = aMaterial.arg( Qtx::colorToString(c) );
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( coef );
}
// Diffuse reflection
isReflectionTypeActive = hasDiffuseReflection();
if ( isReflectionTypeActive ) {
c = color( Material_Model::Diffuse );
coef = coefficient(Material_Model::Diffuse);
// Insert properties into persistent string
aMaterial += "%1DiffuseColor=%2%3DiffuseCoefficient=%4";
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( Qtx::colorToString(c) );
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( coef );
}
// Specular reflection
isReflectionTypeActive = hasSpecularReflection();
if ( isReflectionTypeActive ) {
c = color( Material_Model::Specular );
coef = coefficient(Material_Model::Specular);
// Insert properties into persistent string
aMaterial += "%1SpecularColor=%2%3SpecularCoefficient=%4";
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( Qtx::colorToString(c) );
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( coef );
}
// Emission reflection
isReflectionTypeActive = hasEmissionReflection();
if ( isReflectionTypeActive ) {
c = color( Material_Model::Emission );
coef = coefficient(Material_Model::Emission);
// Insert properties into persistent string
aMaterial += "%1EmissionColor=%2%3EmissionCoefficient=%4";
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( Qtx::colorToString(c) );
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( coef );
}
if ( !aMaterial.isEmpty() ) {
// Shininess
// Insert properties into persistent string
aMaterial += "%1Shininess=%2";
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( shininess() );
// Type: physical - True, artificial - False
// Insert properties into persistent string
aMaterial += "%1Physical=%2";
aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
aMaterial = aMaterial.arg( isPhysical() );
}
return aMaterial;
}
/*!
\brief Construct OCCT material aspect object based on the current model
\return material aspect object with correspondent properties
*/
Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect()
{
// Get material aspect from the current model
Graphic3d_MaterialAspect aMat;
bool isReflectionTypeActive;
QColor c;
double coef;
// Ambient reflection
isReflectionTypeActive = hasAmbientReflection();
if ( isReflectionTypeActive ) {
aMat.SetReflectionModeOn( Graphic3d_TOR_AMBIENT );
c = color( Material_Model::Ambient );
aMat.SetAmbientColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
coef = coefficient( Material_Model::Ambient );
aMat.SetAmbient( coef );
}
// Diffuse reflection
isReflectionTypeActive = hasDiffuseReflection();
if ( isReflectionTypeActive ) {
aMat.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE );
c = color( Material_Model::Diffuse );
aMat.SetDiffuseColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
coef = coefficient( Material_Model::Diffuse );
aMat.SetDiffuse( coef );
}
// Specular reflection
isReflectionTypeActive = hasSpecularReflection();
if ( isReflectionTypeActive ) {
aMat.SetReflectionModeOn( Graphic3d_TOR_SPECULAR );
c = color( Material_Model::Specular );
aMat.SetSpecularColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
coef = coefficient( Material_Model::Specular );
aMat.SetSpecular( coef );
}
// Emission reflection
isReflectionTypeActive = hasEmissionReflection();
if ( isReflectionTypeActive ) {
aMat.SetReflectionModeOn( Graphic3d_TOR_EMISSION );
c = color( Material_Model::Emission );
aMat.SetEmissiveColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
coef = coefficient( Material_Model::Emission );
aMat.SetEmissive( coef );
}
// Shininess
aMat.SetShininess( shininess() );
aMat.SetMaterialType(isPhysical() ? Graphic3d_MATERIAL_PHYSIC : Graphic3d_MATERIAL_ASPECT);
return aMat;
}
/*!
\brief Construct VTK property with properties of material based on the current model
\return VTK property with correspondent material properties
*/
GEOM_VTKPropertyMaterial* Material_Model::getMaterialVTKProperty()
{
// Get material properties from the current model
GEOM_VTKPropertyMaterial* aProperty = GEOM_VTKPropertyMaterial::New();
bool isReflectionTypeActive;
QColor c;
double coef;
// Ambient reflection
isReflectionTypeActive = hasAmbientReflection();
if ( isReflectionTypeActive ) {
c = color( Material_Model::Ambient );
aProperty->SetAmbientColor( c.redF(), c.greenF(), c.blueF() ); //SalomeApp_Tools::color( c )
coef = coefficient( Material_Model::Ambient );
aProperty->SetAmbient( coef );
}
// Diffuse reflection
isReflectionTypeActive = hasDiffuseReflection();
if ( isReflectionTypeActive ) {
c = color( Material_Model::Diffuse );
aProperty->SetDiffuseColor( c.redF(), c.greenF(), c.blueF() );
coef = coefficient( Material_Model::Diffuse );
aProperty->SetDiffuse( coef );
}
// Specular reflection
isReflectionTypeActive = hasSpecularReflection();
if ( isReflectionTypeActive ) {
c = color( Material_Model::Specular );
aProperty->SetSpecularColor( c.redF(), c.greenF(), c.blueF() );
coef = coefficient( Material_Model::Specular );
aProperty->SetSpecular( coef );
}
// Shininess
aProperty->SetSpecularPower( shininess()*100.0 );
//Type
aProperty->SetPhysical( isPhysical() );
return aProperty;
}
/*!
\brief Initialize material model with default values
*/
void Material_Model::initDefaults()
{
// Set default ambient color
setColor( Ambient, "#333333" );
// Set default ambient coefficient
setCoefficient( Ambient, 0.3 );
// Set default diffuse color
setColor( Diffuse, "#000000" );
// Set default diffuse coefficient
setCoefficient( Diffuse, 0.65 );
// Set default specular color
setColor( Specular, "#ffffff" );
// Set default specular coefficient
setCoefficient( Specular, 0.0 );
// Set default shininess
setShininess( 0.039 );
// Set default type - artificial
setPhysical( false );
}
/*!
\brief Clear current content of this material model
*/
void Material_Model::clearModel()
{
myColors.clear();
myCoefficients.clear();
myShininess = 0.0;
myIsPhysical = false;
}
/*!
\brief Initialize material model from the resources
This function can be used to retrieve material properties from the resource file(s).
Note, that paremeters \a theResMgr and \a theResSection are stored by the model to be used
later with save() method.
\param theResMgr resources manager
\param theResSection resources section name
\sa save()
*/
void Material_Model::fromResources( QtxResourceMgr* theResMgr,
const QString& theResSection/*, bool theIsFront*/ )
{
// Clear current content of the model
// before setting properties from resources
clearModel();
myResourceMgr = theResMgr;
myResourceSection = theResSection;
// init from resource manager
if ( !resourceMgr() )
return;
if ( theResSection.compare( "Geometry" ) == 0 ) {
myResourceSection = theResMgr->stringValue("Geometry", "material", "Gold");
myResourceMgr = new Material_ResourceMgr();
}
QString section = resourceSection();
// If there is no material preference in XML files,
// use the default material hardcoded in material model
if ( section.isEmpty() ) {
initDefaults();
return;
}
// Set ambient color
if ( resourceMgr()->hasValue( section, "ambient-color" ) ) {
setColor( Ambient, resourceMgr()->colorValue( section, "ambient-color" ) );
}
// Set ambient coefficient
if ( resourceMgr()->hasValue( section, "ambient-coefficient" ) ) {
setCoefficient( Ambient, resourceMgr()->doubleValue( section, "ambient-coefficient" ) );
}
// Set diffuse color
if ( resourceMgr()->hasValue( section, "diffuse-color" ) ) {
setColor( Diffuse, resourceMgr()->colorValue( section, "diffuse-color" ) );
}
// Set diffuse coefficient
if ( resourceMgr()->hasValue( section, "diffuse-coefficient" ) ) {
setCoefficient( Diffuse, resourceMgr()->doubleValue( section, "diffuse-coefficient" ) );
}
// Set specular color
if ( resourceMgr()->hasValue( section, "specular-color" ) ) {
setColor( Specular, resourceMgr()->colorValue( section, "specular-color" ) );
}
// Set specular coefficient
if ( resourceMgr()->hasValue( section, "specular-coefficient" ) ) {
setCoefficient( Specular, resourceMgr()->doubleValue( section, "specular-coefficient" ) );
}
// Set emission color
if ( resourceMgr()->hasValue( section, "emission-color" ) ) {
setColor( Emission, resourceMgr()->colorValue( section, "emission-color" ) );
}
// Set emission coefficient
if ( resourceMgr()->hasValue( section, "emission-coefficient" ) ) {
setCoefficient( Emission, resourceMgr()->doubleValue( section, "emission-coefficient" ) );
}
// Set shininess
if ( resourceMgr()->hasValue( section, "shininess" ) ) {
setShininess( resourceMgr()->doubleValue( section, "shininess" ) );
}
// Set type: physical or artificial
if ( resourceMgr()->hasValue( section, "physical" ) ) {
setPhysical( resourceMgr()->booleanValue( section, "physical" ) );
}
}
/*!
\brief Save material properties to the resource file.
If paremeters \a theResMgr and \a theResSection are not specified, default ones
(those passed to the fromResources() function) are used instead.
\param theResMgr resources manager
\param theResSection resources section name
\sa fromResources()
*/
void Material_Model::save( QtxResourceMgr* theResMgr,
const QString& theResSection)
{
if ( !theResMgr )
theResMgr = resourceMgr();
if ( !theResMgr )
return;
QString section = theResSection.isEmpty() ? resourceSection() : theResSection;
myResourceSection = section;
if ( hasAmbientReflection() ) {
// Save ambient color
theResMgr->setValue( section, "ambient-color", color( Ambient ) );
// Save ambient coefficient
theResMgr->setValue( section, "ambient-coefficient", coefficient( Ambient ) );
}
else {
// Remove ambient color
theResMgr->remove( section, "ambient-color" );
// Remove ambient coefficient
theResMgr->remove( section, "ambient-coefficient" );
}
if ( hasDiffuseReflection() ) {
// Save diffuse color
theResMgr->setValue( section, "diffuse-color", color( Diffuse ) );
// Save diffuse coefficient
theResMgr->setValue( section, "diffuse-coefficient", coefficient( Diffuse ) );
}
else {
// Remove diffuse color
theResMgr->remove( section, "diffuse-color" );
// Remove diffuse coefficient
theResMgr->remove( section, "diffuse-coefficient" );
}
if ( hasSpecularReflection() ) {
// Save specular color
theResMgr->setValue( section, "specular-color", color( Specular ) );
// Save specular coefficient
theResMgr->setValue( section, "specular-coefficient", coefficient( Specular ) );
}
else {
// Remove specular color
theResMgr->remove( section, "specular-color" );
// Remove specular coefficient
theResMgr->remove( section, "specular-coefficient" );
}
if ( hasEmissionReflection() ) {
// Save emission color
theResMgr->setValue( section, "emission-color", color( Emission ) );
// Save emission coefficient
theResMgr->setValue( section, "emission-coefficient", coefficient( Emission ) );
}
else {
// Remove emission color
theResMgr->remove( section, "emission-color" );
// Remove emission coefficient
theResMgr->remove( section, "emission-coefficient" );
}
// Save shininess
theResMgr->setValue( section, "shininess", shininess() );
// Save type: physical or artificial
theResMgr->setValue( section, "physical", isPhysical() );
}
/*!
\brief Get resource manager used by this material model.
\return pointer to the resource manager passed previously to the fromResources() method
\sa fromResources(), resourceSection()
*/
QtxResourceMgr* Material_Model::resourceMgr() const
{
return myResourceMgr;
}
/*!
\brief Get resources section name
If section name is empty, default material name from "Geometry" section
is returned.
\return resource section name passed previously to the fromResources() method
\sa fromResources(), resourceMgr()
*/
QString Material_Model::resourceSection() const
{
return !myResourceSection.isEmpty() ? myResourceSection :
SUIT_Session::session()->resourceMgr()->stringValue("Geometry", "material", "Gold");
}
/*!
\brief Check if ambient reflection type is defined for this material
\return true if ambient reflection type is defined for this material,
false - otherwise
*/
bool Material_Model::hasAmbientReflection()
{
return ( !myColors.isEmpty() && myColors.contains(Ambient) || !myCoefficients.isEmpty() && myCoefficients.contains(Ambient) );
}
/*!
\brief Check if diffuse reflection type is defined for this material
\return true if diffuse reflection type is defined for this material,
false - otherwise
*/
bool Material_Model::hasDiffuseReflection()
{
return ( !myColors.isEmpty() && myColors.contains(Diffuse) || !myCoefficients.isEmpty() && myCoefficients.contains(Diffuse) );
}
/*!
\brief Check if specular reflection type is defined for this material
\return true if specular reflection type is defined for this material,
false - otherwise
*/
bool Material_Model::hasSpecularReflection()
{
return ( !myColors.isEmpty() && myColors.contains(Specular) || !myCoefficients.isEmpty() && myCoefficients.contains(Specular) );
}
/*!
\brief Check if emission reflection type is defined for this material
\return true if emission reflection type is defined for this material,
false - otherwise
*/
bool Material_Model::hasEmissionReflection()
{
return ( !myColors.isEmpty() && myColors.contains(Emission) || !myCoefficients.isEmpty() && myCoefficients.contains(Emission) );
}
/*!
\brief Get color value for the given reflection type
\param theReflectionType reflection type
\return a color which should be used by the given reflection type
\sa setColor()
*/
QColor Material_Model::color( ReflectionType theReflectionType ) const
{
return myColors[ theReflectionType ];
}
/*!
\brief Set color value for the given reflection type
\param theReflectionType reflection type
\param theColor a color to be used by the given reflection type
\sa color()
*/
void Material_Model::setColor( ReflectionType theReflectionType,
const QColor& theColor )
{
myColors[ theReflectionType ] = theColor;
}
/*!
\brief Set color of the current material from the given string
\param theProp the considered property
\param theColorName the name of the color property
\param theReflectionType the type of reflection
*/
void Material_Model::setColor( QString theProp,
QString theColorName,
ReflectionType theReflectionType )
{
int anId = theProp.indexOf( theColorName );
if ( anId != -1 ) {
QColor c;
if ( Qtx::stringToColor( theProp.right( theProp.length() - ( anId + theColorName.length() ) ), c ) )
setColor( theReflectionType, c );
}
}
/*!
\brief Remove color value for the given reflection type
\param theReflectionType reflection type
\sa color(), setColor()
*/
void Material_Model::removeColor( ReflectionType theReflectionType )
{
myColors.remove( theReflectionType );
}
/*!
\brief Get coefficient value for the given reflection type
\param theReflectionType reflection type
\return a coefficient which should be used by the given reflection type
\sa setCoefficient()
*/
double Material_Model::coefficient( ReflectionType theReflectionType ) const
{
return myCoefficients[ theReflectionType ];
}
/*!
\brief Set coefficient value for the given reflection type
\param theReflectionType reflection type
\param theCoefficient a coefficient to be used by the given reflection type
\sa coefficient()
*/
void Material_Model::setCoefficient( ReflectionType theReflectionType,
double theCoefficient )
{
myCoefficients[ theReflectionType ] = theCoefficient;
}
/*!
\brief Set coefficient of the current material from the given string
\param theProp the considered property
\param theCoefName the name of the color property
\param theReflectionType the type of reflection
*/
void Material_Model::setCoefficient( QString theProp,
QString theCoefName,
ReflectionType theReflectionType )
{
int anId = theProp.indexOf( theCoefName );
if ( anId != -1 ) {
bool ok;
double aCoef = theProp.right( theProp.length() - ( anId + theCoefName.length() ) ).toDouble( &ok );
if ( ok )
setCoefficient( theReflectionType, aCoef );
}
}
/*!
\brief Remove coefficient value for the given reflection type
\param theReflectionType reflection type
\sa coefficient(), setCoefficient()
*/
void Material_Model::removeCoefficient( ReflectionType theReflectionType )
{
myCoefficients.remove( theReflectionType );
}
/*!
\brief Get shininess value
\return a shininess value of this material
\sa setShininess()
*/
double Material_Model::shininess() const
{
return myShininess;
}
/*!
\brief Set shininess value
\param theShininess a shininess value of this material
\sa shininess()
*/
void Material_Model::setShininess( double theShininess)
{
myShininess = theShininess;
}
/*!
\brief Get type value: physical or artificial
\return True if the material is physical and False if the material is artificial
\sa setShininess()
*/
bool Material_Model::isPhysical() const
{
return myIsPhysical;
}
/*!
\brief Set type: physical or artificial
\param theFlag True if the material is physical and False if the material is artificial
\sa isPhysical()
*/
void Material_Model::setPhysical( bool theFlag)
{
myIsPhysical = theFlag;
}