Salome HOME
EDF 2281: Transaltions
[modules/geom.git] / src / Material / Material_Model.cxx
1 // Copyright (C) 2007-2012  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 "GEOM_VTKPropertyMaterial.hxx"
26 #include "Material_ResourceMgr.h"
27
28 /*!
29   \brief Constructor
30
31   Create new SALOME material model with default properties.
32 */
33 Material_Model::Material_Model()
34 {
35   myReflection  = ReflectionList(4);
36   init(); // set default properties
37 }
38
39 /*!
40   \brief Destructor
41 */
42 Material_Model::~Material_Model()
43 {
44 }
45
46 /*!
47   \brief Initialize material data from the given properties list
48   \param props material properties
49   \sa toProperties()
50 */
51 void Material_Model::fromProperties( const QString& props )
52 {
53   // reset to default values
54   init();
55
56   // parse material properties
57   QStringList propList = props.split( ":", QString::SkipEmptyParts );
58   foreach ( QString prop, propList ) 
59   {
60     QStringList pdata = prop.split( "=" );
61     if ( pdata.count() < 2 ) continue;
62     QString key   = pdata[0].trimmed().toLower();
63     QString data  = pdata[1].trimmed().toLower();
64     bool dblOk, boolOk;
65     double dblValue  = data.toDouble( &dblOk );
66     bool   boolValue = (bool)( data.toInt( &boolOk ) );
67     QColor colorValue;
68     
69     if      ( key == "ambientcolor" && Qtx::stringToColor( data, colorValue ) ) {
70       setColor( Ambient, colorValue );
71     }
72     else if ( key == "diffusecolor" && Qtx::stringToColor( data, colorValue ) ) {
73       setColor( Diffuse, colorValue );
74     }
75     else if ( key == "specularcolor" && Qtx::stringToColor( data, colorValue ) ) {
76       setColor( Specular, colorValue );
77     }
78     else if ( key == "emissivecolor" && Qtx::stringToColor( data, colorValue ) ) {
79       setColor( Emissive, colorValue );
80     }
81     else if ( key == "ambientcoefficient" && dblOk ) {
82       setReflection( Ambient, dblValue );
83     }
84     else if ( key == "diffusecoefficient" && dblOk ) {
85       setReflection( Diffuse, dblValue );
86     }
87     else if ( key == "specularcoefficient" && dblOk ) {
88       setReflection( Specular, dblValue );
89     }
90     else if ( key == "emissivecoefficient" && dblOk ) {
91       setReflection( Emissive, dblValue );
92     }
93     else if ( key == "shininess" && dblOk ) {
94       setShininess( dblValue );
95     }
96     else if ( key == "transparency" && dblOk ) {
97       setTransparency( dblValue );
98     }
99     else if ( key == "physical" && boolOk ) {
100       setPhysical( boolValue );
101     }
102     else if ( key == "ambient" && boolOk ) {
103       setReflection( Ambient, boolValue );
104     }
105     else if ( key == "diffuse" && boolOk ) {
106       setReflection( Diffuse, boolValue );
107     }
108     else if ( key == "specular" && boolOk ) {
109       setReflection( Specular, boolValue );
110     }
111     else if ( key == "emissive" && boolOk ) {
112       setReflection( Emissive, boolValue );
113     }
114   }
115 }
116
117 /*!
118   \brief Get material properties string representation
119   \return string representing of material properties
120   \sa fromProperties()
121 */
122 QString Material_Model::toProperties()
123 {
124   QStringList props;
125   QString fmt = "%1=%2";
126
127   // physical
128   props << fmt.arg( "Physical" ).arg( isPhysical() );
129
130   // shininess
131   props << fmt.arg( "Shininess" ).arg( shininess() );
132
133   //transparency
134   props << fmt.arg( "Transparency" ).arg( transparency() );
135
136   // ambient reflection
137   props << fmt.arg( "Ambient" ).arg( hasReflection( Ambient ) );
138   if ( color( Ambient ).isValid() )
139     props << fmt.arg( "AmbientColor" ).arg( Qtx::colorToString( color( Ambient ) ) );
140   props << fmt.arg( "AmbientCoefficient" ).arg( reflection( Ambient ) );
141
142   // diffuse reflection
143   props << fmt.arg( "Diffuse" ).arg( hasReflection( Diffuse ) );
144   if ( color( Diffuse ).isValid() )
145     props << fmt.arg( "DiffuseColor" ).arg( Qtx::colorToString( color( Diffuse ) ) );
146   props << fmt.arg( "DiffuseCoefficient" ).arg( reflection( Diffuse ) );
147
148   // specular reflection
149   props << fmt.arg( "Specular" ).arg( hasReflection( Specular ) );
150   if ( color( Specular ).isValid() )
151     props << fmt.arg( "SpecularColor" ).arg( Qtx::colorToString( color( Specular ) ) );
152   props << fmt.arg( "SpecularCoefficient" ).arg( reflection( Specular ) );
153
154   // emissive reflection
155   props << fmt.arg( "Emissive" ).arg( hasReflection( Emissive ) );
156   if ( color( Emissive ).isValid() )
157     props << fmt.arg( "EmissiveColor" ).arg( Qtx::colorToString( color( Emissive ) ) );
158   props << fmt.arg( "EmissiveCoefficient" ).arg( reflection( Emissive ) );
159
160   return props.join( ":" );
161 }
162
163 /*!
164   \brief Initialize material model from the resources
165
166   This function can be used to retrieve material properties from the resource file.
167
168   \param material material name (if not specified, model is initialized by default material)
169   \param resMgr resource manager (if not specified, new resources manager is created)
170   \sa toResources()
171 */
172 void Material_Model::fromResources( const QString& material, QtxResourceMgr* resMgr )
173 {
174   static QString common = "[common]";
175   
176   // reset to default values
177   init();
178
179   // material name is not specified: use default values
180   if ( material.isEmpty() ) return;
181
182   bool ownResourcesMgr = resMgr == 0;
183   
184   if ( ownResourcesMgr )
185     resMgr = new Material_ResourceMgr();
186
187   // read common section
188   if ( material != common && resMgr->hasSection( common ) )
189     fromResources( common, resMgr );
190
191   // physical
192   if ( resMgr->hasValue( material, "physical" ) ) {
193     setPhysical( resMgr->booleanValue( material, "physical" ) );
194   }
195
196   // shininess
197   if ( resMgr->hasValue( material, "shininess" ) ) {
198     setShininess( resMgr->doubleValue( material, "shininess" ) );
199   }
200
201   // transparency
202   if ( resMgr->hasValue( material, "transparency" ) ) {
203     setTransparency( resMgr->doubleValue( material, "transparency" ) );
204   }
205
206   // ambient reflection
207   if ( resMgr->hasValue( material, "ambient-color" ) ) {
208     setColor( Ambient, resMgr->colorValue( material, "ambient-color" ) );
209   }
210   if ( resMgr->hasValue( material, "ambient-coefficient" ) ) {
211     setReflection( Ambient, resMgr->doubleValue( material, "ambient-coefficient" ) );
212   }
213   if ( resMgr->hasValue( material, "ambient" ) ) {
214     setReflection( Ambient, resMgr->booleanValue( material, "ambient" ) );
215   }
216
217   // diffuse reflection
218   if ( resMgr->hasValue( material, "diffuse-color" ) ) {
219     setColor( Diffuse, resMgr->colorValue( material, "diffuse-color" ) );
220   }
221   if ( resMgr->hasValue( material, "diffuse-coefficient" ) ) {
222     setReflection( Diffuse, resMgr->doubleValue( material, "diffuse-coefficient" ) );
223   }
224   if ( resMgr->hasValue( material, "diffuse" ) ) {
225     setReflection( Diffuse, resMgr->booleanValue( material, "diffuse" ) );
226   }
227
228   // specular reflection
229   if ( resMgr->hasValue( material, "specular-color" ) ) {
230     setColor( Specular, resMgr->colorValue( material, "specular-color" ) );
231   }
232   if ( resMgr->hasValue( material, "specular-coefficient" ) ) {
233     setReflection( Specular, resMgr->doubleValue( material, "specular-coefficient" ) );
234   }
235   if ( resMgr->hasValue( material, "specular" ) ) {
236     setReflection( Specular, resMgr->booleanValue( material, "specular" ) );
237   }
238
239   // emissive reflection
240   if ( resMgr->hasValue( material, "emissive-color" ) ) {
241     setColor( Emissive, resMgr->colorValue( material, "emissive-color" ) );
242   }
243   if ( resMgr->hasValue( material, "emissive-coefficient" ) ) {
244     setReflection( Emissive, resMgr->doubleValue( material, "emissive-coefficient" ) );
245   }
246   if ( resMgr->hasValue( material, "emissive" ) ) {
247     setReflection( Emissive, resMgr->booleanValue( material, "emissive" ) );
248   }
249
250   if ( ownResourcesMgr )
251     delete resMgr;
252 }
253
254 /*!
255   \brief Save material properties to the resource file.
256   \param material material name
257   \param resMgr resource manager
258   \sa fromResources()
259 */
260 void Material_Model::toResources( const QString& material, QtxResourceMgr* resMgr )
261 {
262   if ( resMgr && !material.isEmpty() ) {
263     // remove resources section (to clean-up all previous properties)
264     resMgr->remove( material );
265
266     // physical
267     resMgr->setValue( material, "physical", isPhysical() );
268
269     // shininess
270     resMgr->setValue( material, "shininess", shininess() );
271
272     // transparency
273     resMgr->setValue( material, "transparency", transparency() );
274
275     // ambient reflection
276     if ( color( Ambient ).isValid() )
277       resMgr->setValue( material, "ambient-color", color( Ambient ) );
278     resMgr->setValue( material, "ambient-coefficient", reflection( Ambient ) );
279     resMgr->setValue( material, "ambient", hasReflection( Ambient ) );
280
281     // diffuse reflection
282     if ( color( Diffuse ).isValid() )
283       resMgr->setValue( material, "diffuse-color", color( Diffuse ) );
284     resMgr->setValue( material, "diffuse-coefficient", reflection( Diffuse ) );
285     resMgr->setValue( material, "diffuse", hasReflection( Diffuse ) );
286
287     // Specular reflection
288     if ( color( Specular ).isValid() )
289       resMgr->setValue( material, "specular-color", color( Specular ) );
290     resMgr->setValue( material, "specular-coefficient", reflection( Specular ) );
291     resMgr->setValue( material, "specular", hasReflection( Specular ) );
292
293     // Emissive reflection
294     if ( color( Emissive ).isValid() )
295       resMgr->setValue( material, "emissive-color", color( Emissive ) );
296     resMgr->setValue( material, "emissive-coefficient", reflection( Emissive ) );
297     resMgr->setValue( material, "emissive", hasReflection( Emissive ) );
298   }
299 }
300
301 /*!
302   \brief Initialize material model from the preferences
303
304   The material name is retrieved from the "material" parameter of the "Geometry" section
305   of the specified resources manager.
306
307   \param resMgr resources manager
308   \sa fromResources(), toResources()
309 */
310 // void Material_Model::fromPreferences( QtxResourceMgr* resMgr )
311 // {
312 //   if ( resMgr ) {
313 //     // default material is Plastic
314 //     fromResources( resMgr->stringValue( "Geometry", "material", "Plastic" ) );
315 //   }
316 // }
317
318 /*!
319   \brief Get material type
320   \return \c true if material is physical or \c false otherwise
321   \sa setPhysical()
322 */
323 bool Material_Model::isPhysical() const
324 {
325   return myIsPhysical;
326 }
327
328 /*!
329   \brief Set material type
330   \param value \c true if material is physical or \c false otherwise
331   \sa isPhysical()
332 */
333 void Material_Model::setPhysical( bool value )
334 {
335   myIsPhysical = value;
336 }
337
338 /*!
339   \brief Check if given reflection is enabled
340   \param type reflection type
341   \return \c true if specified reflection type is enabled or \c false otherwise
342   \sa setReflection(ReflectionType, bool)
343 */
344 bool Material_Model::hasReflection( ReflectionType type ) const
345 {
346   bool value = false;
347   if ( type >= 0 && type < 4 )
348     value = myReflection[ type ].enabled;
349   return value;
350 }
351
352 /*!
353   \brief Enable/disable given reflection type
354   \param type reflection type
355   \param value boolean flag
356   \sa hasReflection()
357 */
358 void Material_Model::setReflection( ReflectionType type, bool value )
359 {
360   if ( type >= 0 && type < 4 )
361     myReflection[ type ].enabled = value;
362 }
363
364 /*!
365   \brief Get color value for the given reflection type
366   \param type reflection type
367   \return color associated with the specified reflection type
368   \sa setColor()
369 */
370 QColor Material_Model::color( ReflectionType type ) const
371 {
372   QColor value;
373   if ( type >= 0 && type < 4 )
374     value = myReflection[ type ].color;
375   return value;
376 }
377
378 /*!
379   \brief Set color value for the given reflection type
380   \param type reflection type
381   \param value color to be used for specified reflection type
382   \sa color()
383 */
384 void Material_Model::setColor( ReflectionType type, const QColor& value )
385 {
386   if ( type >= 0 && type < 4 )
387     myReflection[ type ].color = value;
388 }
389
390 /*!
391   \brief Get coefficient value for the given reflection type
392   \param type reflection type
393   \return coefficient value for the specified reflection type
394   \sa setReflection(ReflectionType, double)
395 */
396 double Material_Model::reflection( ReflectionType type ) const
397 {
398   double value = 0.0;
399   if ( type >= 0 && type < 4 )
400     value = myReflection[ type ].coef;
401   return value;
402 }
403
404 /*!
405   \brief Set coefficient value for the given reflection type
406   \param type reflection type
407   \param value coefficient to be used by the given reflection type
408   \sa reflection()
409 */
410 void Material_Model::setReflection( ReflectionType type, double value )
411 {
412   if ( type >= 0 && type < 4 )
413     myReflection[ type ].coef = value;
414 }
415
416 /*!
417   \brief Get shininess value
418   \return shininess value of the material
419   \sa setShininess()
420 */
421 double Material_Model::shininess() const
422 {
423   return myShininess;
424 }
425
426 /*!
427   \brief Set shininess value
428   \param value new shininess value
429   \sa shininess()
430 */
431 void Material_Model::setShininess( double value )
432 {
433   myShininess = value;
434 }
435
436 /*!
437   \brief Get transparency value
438   \return transparency value of the material
439   \sa setTransparency()
440 */
441 double Material_Model::transparency() const
442 {
443   return myTransparency;
444 }
445
446 /*!
447   \brief Set transparency value
448   \param value new transparency value
449   \sa transparency()
450 */
451 void Material_Model::setTransparency( double value )
452 {
453   myTransparency = value;
454 }
455
456 /*!
457   \brief Initialize material model with default values
458 */
459 void Material_Model::init()
460 {  
461   QColor c;
462
463   // non-physical by default
464   setPhysical( false );
465   // shininess
466   setShininess( 0.039 );
467   // transparency
468   setTransparency( 0.0 );
469
470   // ambient reflection (enabled by default)
471   Qtx::stringToColor( "#333333", c );
472   setColor( Ambient, c );
473   setReflection( Ambient, 0.3 );
474   setReflection( Ambient, true );
475
476   // diffuse reflection (enabled by default)
477   Qtx::stringToColor( "#000000", c );
478   setColor( Diffuse, c );
479   setReflection( Diffuse, 0.65 );
480   setReflection( Diffuse, true );
481
482   // specular reflection (enabled by default)
483   Qtx::stringToColor( "#ffffff", c );
484   setColor( Specular, c );
485   setReflection( Specular, 0.0  );
486   setReflection( Specular, true );
487
488   // emissive reflection (disabled by default)
489   Qtx::stringToColor( "#000000", c );
490   setColor( Emissive, c );
491   setReflection( Emissive, 0.0  );
492   setReflection( Emissive, false );
493 }
494
495 /*!
496   \brief Construct OCCT material aspect from material model
497   \return material aspect object with corresponding properties
498 */
499 Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect()
500 {
501   // Get material aspect from the current model
502   Graphic3d_MaterialAspect aspect;
503
504   QColor c;
505   
506   // ambient reflection
507   if ( color( Ambient ).isValid() ) {
508     c = color( Ambient );
509     aspect.SetAmbientColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
510   }
511   aspect.SetAmbient( reflection( Ambient ));
512   if ( hasReflection( Ambient ) )
513     aspect.SetReflectionModeOn( Graphic3d_TOR_AMBIENT );
514   else
515     aspect.SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
516   
517   // diffuse reflection
518   if ( color( Diffuse ).isValid() ) {
519     c = color( Diffuse );
520     aspect.SetDiffuseColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
521   }
522   aspect.SetDiffuse( reflection( Diffuse ));
523   if ( hasReflection( Diffuse ) )
524     aspect.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE );
525   else
526     aspect.SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
527
528   // specular reflection
529   if ( color( Specular ).isValid() ) {
530     c = color( Specular );
531     aspect.SetSpecularColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
532   }
533   aspect.SetSpecular( reflection( Specular ));
534   if ( hasReflection( Specular ) )
535     aspect.SetReflectionModeOn( Graphic3d_TOR_SPECULAR );
536   else
537     aspect.SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
538
539   // emissive reflection
540   if ( color( Emissive ).isValid() ) {
541     c = color( Emissive );
542     aspect.SetEmissiveColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) );
543   }
544   aspect.SetEmissive( reflection( Emissive ));
545   if ( hasReflection( Emissive ) )
546     aspect.SetReflectionModeOn( Graphic3d_TOR_EMISSION );
547   else
548     aspect.SetReflectionModeOff( Graphic3d_TOR_EMISSION );
549   
550   // shininess
551   aspect.SetShininess( shininess() );
552
553   // transparency
554   aspect.SetTransparency( transparency() );
555
556   // material type
557   aspect.SetMaterialType( isPhysical() ? Graphic3d_MATERIAL_PHYSIC : Graphic3d_MATERIAL_ASPECT );
558
559   return aspect;
560 }
561
562 /*!
563   \brief Construct VTK property from material model
564   \return VTK property with correspondent material properties
565 */
566 GEOM_VTKPropertyMaterial* Material_Model::getMaterialVTKProperty()
567 {
568   // NOTE: In VTK it's impossible to switch on/off specific reflection type
569   // NOTE: In VTK emissive reflection type is not supported
570   // NOTE: In VTK shininess is specified via SpecularPower attribute
571   // NOTE: In VTK transparency is specified via Opacity attribute
572
573   // Get material properties from the current model
574   GEOM_VTKPropertyMaterial* prop = GEOM_VTKPropertyMaterial::New();
575
576   QColor c;
577
578   // ambient reflection
579   if ( color( Ambient ).isValid() && hasReflection( Ambient ) ) {
580     c = color( Ambient );
581     prop->SetAmbientColor( c.redF(), c.greenF(), c.blueF() );
582     prop->SetAmbient( reflection( Ambient ) );
583   }
584
585   // diffuse reflection
586   if ( color( Diffuse ).isValid() && hasReflection( Diffuse ) ) {
587     c = color( Diffuse );
588     prop->SetDiffuseColor( c.redF(), c.greenF(), c.blueF() );
589     prop->SetDiffuse( reflection( Diffuse ) );
590   }
591
592   // specular reflection
593   if ( color( Specular ).isValid() && hasReflection( Specular ) ) {
594     c = color( Specular );
595     prop->SetSpecularColor( c.redF(), c.greenF(), c.blueF() );
596     prop->SetSpecular( reflection( Specular ) );
597   }
598
599   // shininess
600   prop->SetSpecularPower( shininess()*100.0 );
601
602   // transparency
603   prop->SetOpacity( 1 - transparency() );
604
605   // material type
606   prop->SetPhysical( isPhysical() );
607
608   return prop;
609 }
610