]> SALOME platform Git repositories - modules/geom.git/blob - src/Material/Material_Model.cxx
Salome HOME
Fix for PAL21179:
[modules/geom.git] / src / Material / Material_Model.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File   : Material_Model.cxx
21 // Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com)
22 //
23
24 #include "Material_Model.h"
25 #include "Material_ResourceMgr.h"
26
27 #include <GEOM_Constants.h>
28
29 #include <QtxResourceMgr.h>
30 #include <SUIT_ResourceMgr.h>
31 #include <SUIT_Session.h>
32
33 // OCCT Includes
34 #include <Graphic3d_AspectFillArea3d.hxx>
35
36 // VTK includes
37 #include <vtkProperty.h> 
38
39 /*!
40   \brief Constructor
41
42   Create new SALOME material model with default properties.
43 */
44 Material_Model::Material_Model()
45   : myResourceMgr( 0 )
46 {
47   myShininess = 0.0;
48 }
49
50 /*!
51   \brief Destructor
52 */
53 Material_Model::~Material_Model()
54 {
55 }
56
57 /*!
58   \brief Construct material model according to the given list of
59   material properties
60   
61   \param theProps the list of material properties
62   \return material model object with correspondent properties
63   \sa getMaterialProperty()
64 */
65 Material_Model* Material_Model::getMaterialModel( QStringList theProps )
66 {
67   Material_Model* aModel = new Material_Model();
68
69   foreach ( QString aProp, theProps ) {
70     if ( aProp.isNull() ) continue;
71     
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 );
76     
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 );
81     
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 );
86     
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 );
91     
92     // Set current shininess
93     QString aPropName = "Shininess=";
94     int anId = aProp.indexOf(aPropName);
95     if ( anId != -1 ) {
96       bool ok;
97       double aCoef = aProp.right( aProp.length() - (anId+aPropName.length()) ).toDouble(&ok);
98       if ( ok )
99         aModel->setShininess( aCoef );
100     }    
101   }
102
103   return aModel;
104 }
105
106 /*!
107   \brief Construct string of material properties for this model object
108   
109   \return a string representing a set of material properties
110   \sa getMaterialModel()
111 */
112 QString Material_Model::getMaterialProperty()
113 {
114   // Parse material properties of the current model and form a string for persistent purpose
115   QString aMaterial;
116
117   bool isReflectionTypeActive;  
118   QColor c;
119   double coef;
120
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 );
131   }
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 );
143   }
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 );
155   }
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 );
167   }
168   if ( !aMaterial.isEmpty() ) {
169     // Shininess
170     // Insert properties into persistent string
171     aMaterial += "%1Shininess=%2";
172     aMaterial = aMaterial.arg( DIGIT_SEPARATOR );
173     aMaterial = aMaterial.arg( shininess() );
174   }
175
176   return aMaterial;
177 }
178
179 /*!
180   \brief Construct OCCT material aspect object based on the current model
181   
182   \return material aspect object with correspondent properties
183 */
184 Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect()
185 {
186   // Get material aspect from the current model
187   Graphic3d_MaterialAspect aMat;
188
189   bool isReflectionTypeActive;
190   QColor c;
191   double coef;
192
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 );
201   }
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 );      
210   }
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 );
219   }
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 );
228   }
229   // Shininess
230   aMat.SetShininess( shininess() );
231
232   return aMat;
233 }
234
235 /*!
236   \brief Construct VTK property with properties of material based on the current model
237   
238   \return VTK property with correspondent material properties
239 */
240 vtkProperty* Material_Model::getMaterialVTKProperty()
241 {
242   // Get material properties from the current model
243   vtkProperty* aProperty = vtkProperty::New();
244   
245   bool isReflectionTypeActive;
246   QColor c;
247   double coef;
248
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 );
256   }
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 );       
264   }
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 );
272   }
273   // Shininess
274   aProperty->SetSpecularPower( shininess()*100.0 );
275
276   return aProperty;
277 }
278
279 /*!
280   \brief Initialize material model with default values
281 */
282 void Material_Model::initDefaults()
283 {  
284   // Set default ambient color
285   setColor( Ambient, "#333333" );
286   // Set default ambient coefficient
287   setCoefficient( Ambient, 0.3 );
288
289   // Set default diffuse color
290   setColor( Diffuse, "#000000" );
291   // Set default diffuse coefficient
292   setCoefficient( Diffuse, 0.65 );
293
294   // Set default specular color
295   setColor( Specular, "#ffffff" );
296   // Set default specular coefficient
297   setCoefficient( Specular, 0.0 );
298   
299   // Set default shininess
300   setShininess( 0.039 );
301 }
302
303 /*!
304   \brief Clear current content of this material model
305 */
306 void Material_Model::clearModel()
307 {
308   myColors.clear();
309   myCoefficients.clear();
310   myShininess = 0.0;
311 }
312
313 /*!
314   \brief Initialize material model from the resources
315
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.
319
320   \param theResMgr resources manager
321   \param theResSection resources section name
322   \sa save()
323 */
324 void Material_Model::fromResources( QtxResourceMgr* theResMgr,
325                                     const QString& theResSection,
326                                     bool theIsFront )
327 {
328   // Clear current content of the model
329   // before setting properties from resources
330   clearModel();
331
332   myResourceMgr     = theResMgr;
333   myResourceSection = theResSection;
334
335   // init from resource manager
336   if ( !resourceMgr() )
337     return;
338
339   if ( theResSection.compare( "Geometry" ) == 0 ) {
340     if ( theIsFront ) {
341       myResourceSection = theResMgr->stringValue("Geometry", "front_material", "Gold");
342     }
343     else {
344       myResourceSection = theResMgr->stringValue("Geometry", "back_material", "");
345       if ( myResourceSection.isEmpty() )
346         myResourceSection = theResMgr->stringValue("Geometry", "front_material", "Gold");
347     }
348       
349     myResourceMgr = new Material_ResourceMgr();
350   }
351   
352   QString section = resourceSection( theIsFront );
353
354   // If there is no material preference in XML files,
355   // use the default material hardcoded in material model
356   if ( section.isEmpty() ) {
357     initDefaults();
358     return;
359   }
360
361   // Set ambient color
362   if ( resourceMgr()->hasValue( section, "ambient-color" ) ) {
363     setColor( Ambient, resourceMgr()->colorValue( section, "ambient-color" ) );
364   }
365   // Set ambient coefficient
366   if ( resourceMgr()->hasValue( section, "ambient-coefficient" ) ) {
367     setCoefficient( Ambient, resourceMgr()->doubleValue( section, "ambient-coefficient" ) );
368   }
369
370   // Set diffuse color
371   if ( resourceMgr()->hasValue( section, "diffuse-color" ) ) {
372     setColor( Diffuse, resourceMgr()->colorValue( section, "diffuse-color" ) );
373   }
374   // Set diffuse coefficient
375   if ( resourceMgr()->hasValue( section, "diffuse-coefficient" ) ) {
376     setCoefficient( Diffuse, resourceMgr()->doubleValue( section, "diffuse-coefficient" ) );
377   }
378
379   // Set specular color
380   if ( resourceMgr()->hasValue( section, "specular-color" ) ) {
381     setColor( Specular, resourceMgr()->colorValue( section, "specular-color" ) );
382   }
383   // Set specular coefficient
384   if ( resourceMgr()->hasValue( section, "specular-coefficient" ) ) {
385     setCoefficient( Specular, resourceMgr()->doubleValue( section, "specular-coefficient" ) );
386   }
387
388   // Set emission color
389   if ( resourceMgr()->hasValue( section, "emission-color" ) ) {
390     setColor( Emission, resourceMgr()->colorValue( section, "emission-color" ) );
391   }
392   // Set emission coefficient
393   if ( resourceMgr()->hasValue( section, "emission-coefficient" ) ) {
394     setCoefficient( Emission, resourceMgr()->doubleValue( section, "emission-coefficient" ) );
395   }
396
397   // Set shininess
398   if ( resourceMgr()->hasValue( section, "shininess" ) ) {
399     setShininess( resourceMgr()->doubleValue( section, "shininess" ) );
400   }
401 }
402
403 /*!
404   \brief Save material properties to the resource file.
405   
406   If paremeters \a theResMgr and \a theResSection are not specified, default ones
407   (those passed to the fromResources() function) are used instead.
408
409   \param theResMgr resources manager
410   \param theResSection resources section name
411   \sa fromResources()
412 */
413 void Material_Model::save( QtxResourceMgr* theResMgr,
414                            const QString& theResSection,
415                            bool theIsFront )
416 {
417   if ( !theResMgr )
418     theResMgr = resourceMgr();
419   if ( !theResMgr )
420     return;
421
422   QString section = theResSection.isEmpty() ? resourceSection( theIsFront ) : theResSection;
423   myResourceSection = section;
424
425   if ( hasAmbientReflection() ) {
426     // Save ambient color
427     theResMgr->setValue( section, "ambient-color", color( Ambient ) );
428     // Save ambient coefficient
429     theResMgr->setValue( section, "ambient-coefficient", coefficient( Ambient ) );
430   }
431   else {
432     // Remove ambient color
433     theResMgr->remove( section, "ambient-color" );
434     // Remove ambient coefficient
435     theResMgr->remove( section, "ambient-coefficient" );
436   }
437
438   if ( hasDiffuseReflection() ) {
439     // Save diffuse color
440     theResMgr->setValue( section, "diffuse-color", color( Diffuse ) );
441     // Save diffuse coefficient
442     theResMgr->setValue( section, "diffuse-coefficient", coefficient( Diffuse ) );
443   }
444   else {
445     // Remove diffuse color
446     theResMgr->remove( section, "diffuse-color" );
447     // Remove diffuse coefficient
448     theResMgr->remove( section, "diffuse-coefficient" );
449   }
450
451   if ( hasSpecularReflection() ) {
452     // Save specular color
453     theResMgr->setValue( section, "specular-color", color( Specular ) );
454     // Save specular coefficient
455     theResMgr->setValue( section, "specular-coefficient", coefficient( Specular ) );
456   }
457   else {
458     // Remove specular color
459     theResMgr->remove( section, "specular-color" );
460     // Remove specular coefficient
461     theResMgr->remove( section, "specular-coefficient" );
462   }
463
464   if ( hasEmissionReflection() ) {
465     // Save emission color
466     theResMgr->setValue( section, "emission-color", color( Emission ) );
467     // Save emission coefficient
468     theResMgr->setValue( section, "emission-coefficient", coefficient( Emission ) );
469   }
470   else {
471     // Remove emission color
472     theResMgr->remove( section, "emission-color" );
473     // Remove emission coefficient
474     theResMgr->remove( section, "emission-coefficient" );
475   }
476
477   // Save shininess
478   theResMgr->setValue( section, "shininess", shininess() );
479 }
480
481 /*!
482   \brief Get resource manager used by this material model.
483
484   \return pointer to the resource manager passed previously to the fromResources() method
485   \sa fromResources(), resourceSection()
486 */
487 QtxResourceMgr* Material_Model::resourceMgr() const
488 {
489   return myResourceMgr;
490 }
491
492 /*!
493   \brief Get resources section name
494
495   If section name is empty, default material name from "Geometry" section
496   is returned ("front_material" or "back_material" is used depending on
497   the parameter value)
498
499   \param theIsFront the flag indicating that section of front or back material
500   is required
501   \return resource section name passed previously to the fromResources() method
502   \sa fromResources(), resourceMgr()
503 */
504 QString Material_Model::resourceSection( bool theIsFront ) const
505 {
506   return !myResourceSection.isEmpty() ? myResourceSection : 
507     SUIT_Session::session()->resourceMgr()->stringValue("Geometry", 
508                                                         ( theIsFront ? "front_material" : "back_material" ),
509                                                         "Gold");
510 }
511
512 /*!
513   \brief Check if ambient reflection type is defined for this material
514
515   \return true if ambient reflection type is defined for this material,
516   false - otherwise
517 */
518 bool Material_Model::hasAmbientReflection()
519 {
520   return ( !myColors.isEmpty() && myColors.contains(Ambient) || !myCoefficients.isEmpty() && myCoefficients.contains(Ambient) );
521 }
522
523 /*!
524   \brief Check if diffuse reflection type is defined for this material
525
526   \return true if diffuse reflection type is defined for this material,
527   false - otherwise
528 */
529 bool Material_Model::hasDiffuseReflection()
530 {
531   return ( !myColors.isEmpty() && myColors.contains(Diffuse) || !myCoefficients.isEmpty() && myCoefficients.contains(Diffuse) );
532 }
533
534 /*!
535   \brief Check if specular reflection type is defined for this material
536
537   \return true if specular reflection type is defined for this material,
538   false - otherwise
539 */
540 bool Material_Model::hasSpecularReflection()
541 {
542   return ( !myColors.isEmpty() && myColors.contains(Specular) || !myCoefficients.isEmpty() && myCoefficients.contains(Specular) );
543 }
544
545 /*!
546   \brief Check if emission reflection type is defined for this material
547
548   \return true if emission reflection type is defined for this material,
549   false - otherwise
550 */
551 bool Material_Model::hasEmissionReflection()
552 {
553   return ( !myColors.isEmpty() && myColors.contains(Emission) || !myCoefficients.isEmpty() && myCoefficients.contains(Emission) );
554 }
555
556 /*!
557   \brief Get color value for the given reflection type
558   \param theReflectionType reflection type
559   \return a color which should be used by the given reflection type
560   \sa setColor()
561 */
562 QColor Material_Model::color( ReflectionType theReflectionType ) const
563 {
564   return myColors[ theReflectionType ];
565 }
566
567 /*!
568   \brief Set color value for the given reflection type
569
570   \param theReflectionType reflection type
571   \param theColor a color to be used by the given reflection type
572   \sa color()
573 */
574 void Material_Model::setColor( ReflectionType theReflectionType,
575                                const QColor& theColor )
576 {
577   myColors[ theReflectionType ] = theColor;
578 }
579
580 /*!
581   \brief Set color of the current material from the given string
582   \param theProp the considered property
583   \param theColorName the name of the color property
584   \param theReflectionType the type of reflection
585 */
586 void Material_Model::setColor( QString theProp,
587                                QString theColorName,
588                                ReflectionType theReflectionType )
589 {
590   int anId = theProp.indexOf( theColorName );
591   if ( anId != -1 ) {
592     QColor c;
593     if ( Qtx::stringToColor( theProp.right( theProp.length() - ( anId + theColorName.length() ) ), c ) )
594       setColor( theReflectionType, c );
595   }
596 }
597
598 /*!
599   \brief Remove color value for the given reflection type
600
601   \param theReflectionType reflection type
602   \sa color(), setColor()
603 */
604 void Material_Model::removeColor( ReflectionType theReflectionType )
605 {
606   myColors.remove( theReflectionType );
607 }
608
609 /*!
610   \brief Get coefficient value for the given reflection type
611   \param theReflectionType reflection type
612   \return a coefficient which should be used by the given reflection type
613   \sa setCoefficient()
614 */
615 double Material_Model::coefficient( ReflectionType theReflectionType ) const
616 {
617   return myCoefficients[ theReflectionType ];
618 }
619
620 /*!
621   \brief Set coefficient value for the given reflection type
622
623   \param theReflectionType reflection type
624   \param theCoefficient a coefficient to be used by the given reflection type
625   \sa coefficient()
626 */
627 void Material_Model::setCoefficient( ReflectionType theReflectionType,
628                                      double theCoefficient )
629 {
630   myCoefficients[ theReflectionType ] = theCoefficient;
631 }
632
633 /*!
634   \brief Set coefficient of the current material from the given string
635   \param theProp the considered property
636   \param theCoefName the name of the color property
637   \param theReflectionType the type of reflection
638 */
639 void Material_Model::setCoefficient( QString theProp,
640                                      QString theCoefName,
641                                      ReflectionType theReflectionType )
642 {
643   int anId = theProp.indexOf( theCoefName );
644   if ( anId != -1 ) {
645     bool ok;
646     double aCoef = theProp.right( theProp.length() - ( anId + theCoefName.length() ) ).toDouble( &ok );
647     if ( ok )
648       setCoefficient( theReflectionType, aCoef );
649   }
650 }
651
652 /*!
653   \brief Remove coefficient value for the given reflection type
654
655   \param theReflectionType reflection type
656   \sa coefficient(), setCoefficient()
657 */
658 void Material_Model::removeCoefficient( ReflectionType theReflectionType )
659 {
660   myCoefficients.remove( theReflectionType );
661 }
662
663 /*!
664   \brief Get shininess value
665   \return a shininess value of this material
666   \sa setShininess()
667 */
668 double Material_Model::shininess() const
669 {
670   return myShininess;
671 }
672
673 /*!
674   \brief Set shininess value
675
676   \param theShininess a shininess value of this material
677   \sa shininess()
678 */
679 void Material_Model::setShininess( double theShininess)
680 {
681   myShininess = theShininess;
682 }